int $0x80

Attacking Javascript Engines - Introduction to Overview 본문

해킹공부/브라우져를 털자

Attacking Javascript Engines - Introduction to Overview

cd80 cd80 2017.01.03 18:19

스터디 내부용으로만 공유하려고 작성한 글이기 때문에 그런것같이 보이는 문장들이 많습니다

이 글에서 공부하는 문서는 http://phrack.org/papers/attacking_javascript_engines.html 입니다


우리가 보는 문서의 CVE 넘버는 CVE-2016-4622 입니다

트렌드마이크로의 Samuel Gross가 올해 초에 발견한 취약점이라고합니다


이 취약점으로 메모리릭도 되고 페이크객체 삽입도 가능해서 이거 취약점 하나만 갖고도 익스플로잇이 가능하다고 하네요

버그가 커밋 650552a에서 수정됐고 우리가 지금 다운받아서 테스트하는 커밋인 320b1fc가 마지막으로 취약한 버젼이라고 합니다

커밋 2fa4973에서 처음 발생한 취약점인데, 2015년 초에 처음 취약코드가 커밋되고 1년동안 안발견되다가 올해 초에 발견된 취약점이라고 합니다


커밋 2fa4973를 보면 "splice에 있는 것처럼 빠르게 memcpy로 딱 처리하고 끝내는 조건이 필요할 것 같아서 커밋했다" 라고 주석을 달아 커밋했습니다

그래서 취약점 패치 커밋인 650552a를 보면 splice와 slice가 모두 같은방식으로 패치됐습니다



프랙에 나와있는 모든 내용을 사파리 9.1.1에서 다 테스트를 완료 하고 문서를 쓴거라고 하니 문서를 다 이해하고 직접 취약버젼 다운받아서 웹 브라우져상에서 쉘 따는것도 해보면 재밌을 것 같아요 (아직 사파리 옛날버젼 다운받는법은 못찾았습니다)



이 취약점을 제대로 이해하기 위해선 자바스크립트 엔진의 인터널을 잘 이해하고 있어야 하기 때문에 처음에 기본지식들을 다룹니다



Javascript envine overview


자바스크립트 엔진은 대체로

1. 하나 이상의 JIT Compiler를 포함한 컴파일러 아키텍쳐

2. 자바스크립트 VM

3. eval, slice같은 빌트인 함수들의 구현체

이렇게 세가지를 기본적으로 포함하고 있다고 합니다


이 문서에서는 1번은 제외하고 2번과 3번에 대한 이해가 필요하다고 하네요




The VM, Values, and NaN-boxing

먼저 자바스크립트 VM은 그냥 우리가 아는 VM입니다

컴파일러에서 유저 코드를 분석해서 바이트코드를 생성하면, 그 바이트코드를 실행시켜주는 역할을 합니다


문서에서는 VM에 대해서는 딱 이만큼만 설명하고 넘어갑니다


NaN-boxing도 지금 오버뷰를 보는 순간에는 자세하게 알 필요는 없고 그냥 나중에 디버거로 메모리를 봤을 때 원하는 값을 찾을 수 있을 정도로만 알면 될 듯 합니다

JSC에서는 값을 Pointer, Double, Integer로 나눠서 저장 한다고 하고

Pointer의 최상위 2바이트는 0

Double의 최상위 2바이트는 1~65534(0x1 ~ 0xfffe)

Integer의 최상위 2바이트는 65535(0xffff)

라고 합니다

그래서 어떤 변수에 0xcd80cd80을 할당해주고 메모리에서 보면

0xffff0000cd80cd80 으로 보인다는 얘기죠


[False, True, Undefined, Null] 이 네가지는 포인터로 저장된다고 하고 enum을 하나씩 할당 받았습니다

False는 0x0000000000000006

True는 0x0000000000000007

Undefined는 0x000000000000000a

Null은 0x0000000000000002

각각 메모리에서 이렇게 보일 겁니다

꼭 중요하게 여기고 정확히 이해하고 넘어갈 필요는 없어보이고 이런게 있다 정도만 알면 될 것 같습니다



Objects and Arrays

이 장에서는 비교적 중요해보이는 Butterfly 라는 구조를 다룹니다

문서를 중반정도 읽다가 자꾸 butterfly butterfly 해서 이해를 못했었는데 Overview에서 처음에 설명이 돼있더라구요


butterfly는 오브젝트 포인터를 기준으로, 오브젝트의 프로퍼티와 엘레먼트가 양옆으로 날개처럼 퍼져있는 형상이라 해서 붙여진 이름입니다



사진은 프랙에서 가져왔습니다


이런식으로 어떤 오브젝트 포인터가 있으면 선형으로 멤버가 쭉 있는게 아니라

좌속성 우요소로 날개처럼 퍼져있는 형태를 갖습니다

그래서 나중에 디버깅할때 나는 이 오브젝트의 프로퍼티에 0x41414141을 넣었는데 왜 보이질 않아! 할때 이걸 기억해서 아 오브젝트 포인터 말고 오브젝트 포인터-100정도에서 100바이트를 읽어보자 하면 찾을 수 있습니다



그뒤에 인덱싱관련해서 얘기가 나오는데

a = [];

a[0] = 42;

a[10000] = 42;

라는 코드가 있을 때 이 어레이는 10001개짜리 int형 어레이가 아니라

10000번째 인덱스 부터 저장한다는 의미의 영역을 새로 하나를 매핑을 해서 효율적으로 관리를 한다고는 하는데 문서에서도 너무 간단히 설명하고 넘어가는 내용이라 아직 중요한지는 잘 모르겠습니다


그리고 이거는 좀 중요할 수 있어 보이는데

숫자 배열이 있을 때 모든 숫자 하나하나에 NaN-boxing을 적용 시키면 

[1, 2, 3, 4, 5] 가 있을 때

[0xffff000000000001, 0xffff000000000002, 0xffff000000000003, 0xffff000000000004, 0xffff000000000005]; 이렇게 적용되기 때문에 이 값을 저장하고 가져오는데 의미없는 Nan-Boxing, NaN-Unboxing 과정을 거치게 되고, 또 공간도 불필요하게 많이 사용하게 됩니다

따라서 네이티브 타입을 지원하는 배열 형태도 있다고 합니다




Functions

문서는 함수를 엄청 장황하게 길게 설명 해놨는데, 그냥 함수들이 가질 수 있는 예약어가 있다는걸 설명하는 것 같습니다.

이 파트는 뒤에를 안읽어봐서 그런건진 모르겠는데 딱히 볼 필요 없는 섹션같습니다

그냥 오디팅 할 때 함수 구현체에서 볼 수 있는 특징? 을 아주 간단히 정리해둔 것 같습니다


신고
0 Comments
댓글쓰기 폼