JavaScript: Equality 광기 또는 x=1 및 x=2

17107 단어 challengejavascript
JavaScript는 현재 벌어지고 있는 일을 가장 잘 의심할 수 있도록 합니다.
본고에서 다음 문장을true로 되돌릴 수 있는 다른 방법을 보여 드리겠습니다.
x === 1 && x === 2
당신들 중 먼저 해보고 싶은 사람들에게는 도전부터 시작하겠습니다.
만약 당신이 답만 원한다면, writeup 부분으로 넘어가세요!

도전하다


이 도전은 세 가지 난이도 등급과 많은 사용 가능한 해결 방안이 있다!
목표는 X에 인쇄 Flag! 에 필요한 값을 제공하는 것입니다.
인쇄하기 위해 다음 코드 세그먼트를 어디에 두십시오Flag!

1급


// Your code here

if(x == 1 && x == 2 && x == 3) {
    console.log('Flag!');
} else {
    console.log('Wrong flag!');
}

// Your code here

2급


엄격한 상등 연산자를 사용하여 일을 더욱 어렵게 합시다!
// Your code here

if(x === 1 && x === 2 && x === 3) {
    console.log('Flag!');
} else {
    console.log('Wrong flag!');
}

// Your code here

3급


마지막으로 현재 범위 내에서 로고를 인쇄합시다!
이것은 이 문장이 클래스나 함수에 있지 않고 스크립트에 있어야 한다는 것을 의미한다.
// Your code here

if(x === 1 && x === 2 && x === 3) {
    console.log('Flag!');
} else {
    console.log('Wrong flag!');
}

쓰다


당신은 인쇄 Flag! 를 하려고 했습니까?

섹션 1


이것은 이전 도전의 첫 번째 부분이다.
if(x == 1 && x == 2 && x == 3) {
이 부분의 문제를 해결하는 관건은 자바스크립트가 두 객체를 어떻게 비교하는지 이해하는 것이다.
엄격한 상등 연산자 == 가 아니라 상등 연산자 === 를 사용하면 엔진이 비교하기 전에 두 대상을 기본체로 전환할 것을 의미한다.
DNComparison Operators 페이지에서 비교에 대한 자세한 내용을 확인할 수 있습니다.
이것은 만약에 우리가 하나의 대상을 문자열과 비교한다면 실패가 아니라 myObject.toString()의 결과를 사용하여 비교할 것이라는 것을 의미한다.
예:
const myObject = {
    toString() {
        return 'My Object!';
    }
}
console.log(myObject == 'My Object!');
반품true우리의 장면에서 x와 기원 유형Number을 비교할 때 백그라운드에서 다음과 같은 절차를 수행한다.

If Type(x) is Object and Type(y) is either String or Number,

return the result of the comparison ToPrimitive(x) == y.


이 비헤이비어는 Ecmascript에 기록됩니다.The Abstract Equality Comparison Algorithm
대상을 호출하는 toString 또는 valueOf 방법을 통해 대상을 원어로 바꾸는 것을 실현한다. 본고에서 말한 바와 같이: Object [[DefaultValue]]
ES6에서는 사용자 정의 값을 반환하기 위해 직접 다시 쓰기Symbol.toPrimitive도 할 수 있습니다.
따라서 우리는 toString 또는 valueOf 함수를 사용하여 증가 숫자를 되돌려 주는 대상을 만들 수 있습니다!

솔루션


let i = 1,
  x = {
    valueOf() { // Default conversion for numbers
      return i++;
    },
    toString() { // Default conversion for strings
      return i++;
    },
    [Symbol.toPrimitive]() { // toPrimitive override
        return i++;
    }
  }

if(x == 1 && x == 2 && x == 3) {
    console.log('Flag!');
} else {
    console.log('Wrong flag!');
}
기호를 주의하십시오.Primitive는 첫 번째 호출을 시도합니다. 그 다음에 valueOf, 마지막에 toString 순서가 미래의 도전에서 중요하다면.

섹션 2


이 도전의 첫 번째 부분은 대상과 비엄격한 비교를 통해 해결할 수 있지만 여기에서는 통하지 않는다.
우리가 엄격한 상등 연산자를 사용할 때 x1, 그 다음은 2, 마지막은 3 이 필요하다.
이 문제를 해결하는 데는 두 가지 기교가 필요하다.
Getters와 모호한with 진술.
이 해결 방안의 첫 번째 부분은 대상myObject을 만들어야 합니다. 대상의 x 속성은 getter 함수로 설정됩니다.

let i = 1,
  myObject = {
    get x() {
        return i++;
    }
 }
우리는 지금 방문할 수 있습니다 myObject.x. 이것은 점차적인 부가가치로 돌아갈 것입니다!
이것은 여전히 도전을 해결하기에는 부족하다. 왜냐하면 if문장은 비교에서 우리의 myObject 접두사가 없기 때문이다.
고맙습니다. JavaScript에는 역할 영역을 객체의 속성으로 설정할 수 있는 모호한 문구가 있습니다. with운영자의 MDN 페이지가 이 큰 경고로 시작되었을 때, 당신은 좋아하지 않습니까?

DNdocumentation은 다음과 같이 설명합니다.

The 'with' statement adds the given object to the head of this scope chain during the evaluation of its statement body. If an unqualified name used in the body matches a property in the scope chain, then the name is bound to the property and the object containing the property.


따라서 이 해결 방안의 두 번째 부분은 with 문장에 비교적 봉인되고, 이 문장은 x 본체 속성처럼 접근할 것이다.

솔루션


let i = 1,
  myObject = {
    get x() {
        return i++;
    }
 }

with(myObject) {

  if(x === 1 && x === 2 && x === 3) {
    console.log('Flag!');
  } else {
    console.log('Wrong flag!');
  }

}

제3부분


이전의 해결 방안은 if문장의 상하문을 제어할 수 있을 때만 유효하였으며, XSS를 찾을 때 이런 상황은 매우 드물었다.
따라서 if문장 이전에 입구점을 인쇄해야 하는 해결 방안을 조정할 수 있습니다 Flag!.
주의: 만약 당신이 아래에 입구점이 하나밖에 없다면, 당신은 아마도 나의 이전 게시물을 보고 싶을 것이다:!
우리는 여전히 엄격한 등식 검사를 사용하기 때문에, 우리는 여전히 getter를 사용하여 X를 만들어야 한다.
이 솔루션의 차이점은 현재 역할 영역this 객체에 직접 액세스를 추가하는 것입니다.
브라우저에서 this 는 DOM 모델이 정의한 window 객체를 참조합니다.
NodeJS에서는 this 객체가 지정됩니다.
현재 개체 속성의 속성을 수정하려면 Object.defineProperty 을 사용합니다.

솔루션


let a = 1;
Object.defineProperty(
  window, // Object to assign the new property to: this, window, or global depending on the context 
  'x', // Name of the property to assign
  {  // Properties of the object, the getter function in our case
    get: function() { 
      return a++; 
    } 
  }
);

if(x === 1 && x === 2 && x === 3) {
  console.log('Flag!');
} else {
  console.log('Wrong flag!');
}

결론


동적 특성 때문에 JavaScript는 이성적인 개발자에게 global가 일하는 이유를 이해할 수 있습니다!
실제 코드에서 이러한 특성에 의존하는 사람이 없기를 바라지만, 나는 이러한 특성의 실제 용례를 보고 싶다.
다른 한편, 이것은 나로 하여금 자바스크립트에서 잘못된 비교만 있을 수 있다는 것을 생각하게 했다.
알다시피, x === 1 && x === 2 && x !== x 비교에서 항상false를 되돌려줍니다. 자신과의 비교를 포함합니다.
내가 아는 바에 의하면, 유일한 다른 것은 진짜 값일 수 있다. 왜냐하면 모든 기호가 유일하기 때문이다.
현재, 우리는 NaN 을 위한 동적 값을 만들 수 있는데, 그 중에서 Symbol() 은 확실히 사실이다.
JS의 다른 재미있는 특성을 아십니까? 이런 특성들이 붙을 만하다고 생각합니까?
댓글이나 연락주세요!

공구서류


MDN:Comparison Operators
EcmaScript:The Abstract Equality Comparison Algorithm
EcmaScript:Object [[DefaultValue]]
MDN:Getters
MDN:With
MDN:Object.defineProperty

좋은 웹페이지 즐겨찾기