Destructuring Tweets - 에피소드 7 - 훨씬 더 사악한 평가
금주의 단편
이번 주 출처:
function challenge(input){
eval(input.toUpperCase())
}
// provide an input that makes function challenge call alert(1)
challenge('alert(1)');
여기에서 우리는 진흙탕으로 이동합니다. 작성자는 challenge
라는 함수를 선언하고 이 함수는 eval
를 래핑합니다. 비결은 래퍼 함수의 인수가 먼저 .toUpperCase()
를 통해 연결된다는 것입니다.
연습은 함수를 실행하는 것입니다alert(1)
.
출력
여기서 출력은 훌륭하지는 않지만 eval
가 정확히 무엇을 하는지 모르는 경우 일종의 마술처럼 느껴집니다. 그러나 상당히 간단합니다. eval
는 문자열로 전달되는 코드 조각을 실행합니다.
따라서 우리 스니펫의 경우 eval
가 전역 범위에서 정의되지 않은 "ALERT"를 실행하려고 시도하기 때문에 인터프리터에서 오류가 발생합니다.
ReferenceError: ALERT is not defined
분석
따라서 먼저 스니펫으로 돌아가서 정확히 어떤 일이 일어나는지 살펴보겠습니다. 인수alert(1)
를 전달합니다. 래퍼 함수가 없는 경우 이 코드는 alert
잘 실행됩니다.
eval('alert(1)');
그러나 .toUpperCase()
를 통해 파이프되기 때문에 호출된 함수인 문자열은 실제로 ALERT
이고 JavaScript는 대소문자를 구분하는 언어입니다!
이제 우리는 이 문제를 극복해야 합니다. 나는 세 가지 가능한 해결책을 생각해 냈습니다. 하나씩 확인해보자.
문자열의 프로토타입 변경
toUpperCase
메서드는 String
프로토타입의 일부이므로 함수 본문을 쉽게 변경할 수 있습니다.
function challenge(input){
eval(input.toUpperCase())
}
String.prototype.toUpperCase = () => alert(1);
challenge('alert(1)');
이 경우 toUpperCase
가 input
에서 호출되면 문자열을 파이프 및 구문 분석하지 않고 대신 경고를 실행합니다. 호출된 함수는 대상 동작으로 덮어씁니다.
ALERT 기능 추가
다른 방향으로 가서 누락된 함수ALERT
를 전역 객체에 추가할 수도 있습니다.
function challenge(input){
eval(input.toUpperCase())
}
window.ALERT = input => alert(input);
challenge('alert(1)');
그 접근 방식은 간단합니다. 올바른 이름으로 다른 기능을 추가합니다. alert
를 호출하는 대신 ALERT
를 호출하면 인수가 alert
에 전달됩니다.
객체 전달
처음 두 가지 솔루션은 실제로 불법이었습니다. 저자는 입력을 전달하여 문제를 해결한다고 명시적으로 명시했습니다. 이것이 우리가 그 접근 방식에서 하는 일입니다. toUpperCase
함수로 객체를 전달합니다.
function challenge(input){
eval(input.toUpperCase())
}
challenge({ toUpperCase: () => 'alert(1)' });
String의 프로토타입에서 구현을 사용하는 대신 자체 버전의 toUpperCase
개체를 전달합니다.
스니펫 요약
function challenge(input){
eval(input.toUpperCase())
}
// provide an input that makes function challenge call alert(1)
challenge('alert(1)');
여기서 출력은 훌륭하지는 않지만
eval
가 정확히 무엇을 하는지 모르는 경우 일종의 마술처럼 느껴집니다. 그러나 상당히 간단합니다. eval
는 문자열로 전달되는 코드 조각을 실행합니다.따라서 우리 스니펫의 경우
eval
가 전역 범위에서 정의되지 않은 "ALERT"를 실행하려고 시도하기 때문에 인터프리터에서 오류가 발생합니다.ReferenceError: ALERT is not defined
분석
따라서 먼저 스니펫으로 돌아가서 정확히 어떤 일이 일어나는지 살펴보겠습니다. 인수alert(1)
를 전달합니다. 래퍼 함수가 없는 경우 이 코드는 alert
잘 실행됩니다.
eval('alert(1)');
그러나 .toUpperCase()
를 통해 파이프되기 때문에 호출된 함수인 문자열은 실제로 ALERT
이고 JavaScript는 대소문자를 구분하는 언어입니다!
이제 우리는 이 문제를 극복해야 합니다. 나는 세 가지 가능한 해결책을 생각해 냈습니다. 하나씩 확인해보자.
문자열의 프로토타입 변경
toUpperCase
메서드는 String
프로토타입의 일부이므로 함수 본문을 쉽게 변경할 수 있습니다.
function challenge(input){
eval(input.toUpperCase())
}
String.prototype.toUpperCase = () => alert(1);
challenge('alert(1)');
이 경우 toUpperCase
가 input
에서 호출되면 문자열을 파이프 및 구문 분석하지 않고 대신 경고를 실행합니다. 호출된 함수는 대상 동작으로 덮어씁니다.
ALERT 기능 추가
다른 방향으로 가서 누락된 함수ALERT
를 전역 객체에 추가할 수도 있습니다.
function challenge(input){
eval(input.toUpperCase())
}
window.ALERT = input => alert(input);
challenge('alert(1)');
그 접근 방식은 간단합니다. 올바른 이름으로 다른 기능을 추가합니다. alert
를 호출하는 대신 ALERT
를 호출하면 인수가 alert
에 전달됩니다.
객체 전달
처음 두 가지 솔루션은 실제로 불법이었습니다. 저자는 입력을 전달하여 문제를 해결한다고 명시적으로 명시했습니다. 이것이 우리가 그 접근 방식에서 하는 일입니다. toUpperCase
함수로 객체를 전달합니다.
function challenge(input){
eval(input.toUpperCase())
}
challenge({ toUpperCase: () => 'alert(1)' });
String의 프로토타입에서 구현을 사용하는 대신 자체 버전의 toUpperCase
개체를 전달합니다.
스니펫 요약
eval('alert(1)');
function challenge(input){
eval(input.toUpperCase())
}
String.prototype.toUpperCase = () => alert(1);
challenge('alert(1)');
function challenge(input){
eval(input.toUpperCase())
}
window.ALERT = input => alert(input);
challenge('alert(1)');
function challenge(input){
eval(input.toUpperCase())
}
challenge({ toUpperCase: () => 'alert(1)' });
속임수: 기존 함수 호출을 조작하는 방법
주요 학습: JavaScript는 대소문자를 구분하며
eval
문자열에서 코드를 실행합니다(사용해서는 안 됩니다!), 프로토타이핑 및 전역 범위추가 읽기:
경고: 문자열에서 JavaScript를 실행하는 것은 엄청난 보안 위험입니다. eval()을 사용할 때 나쁜 행위자가 임의의 코드를 실행하는 것은 너무 쉽습니다. MDN ↩에서 자세히 읽어보세요.
Reference
이 문제에 관하여(Destructuring Tweets - 에피소드 7 - 훨씬 더 사악한 평가), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/odddev/destructuring-tweets-episode-7-even-more-evil-eval-52nh텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)