이번문제. 재밌습니다. 점수도 꽤 짭짤합니다.
- JavaScript Unpacking 문제 -
소스보기
<!DOCTYPE html>
<html>
<head>
<title>Game 05</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="shortcut icon" href="/static/img/game.ico" />
</head>
<body onload="init();">
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<form name="frm" method="post" action="./web05.asp">
<table width="250" cellpadding="0" cellspacing="0" align="center">
<tr height="30">
<td colspan="2" width="100%" class="table_top" align="right">
<input type="button" name="main_btn" value="main" style="width: 60" onclick="location.href = '/'"> <input type="button" name="main_btn" value="Back" style="width: 60" onclick="history.back()"></td>
</tr>
<tr height="30" class="table_main">
<td width="200" align="center" bgcolor="cccccc"><font size="2"><input name="password" value="" style="width:180"></td>
<td width="50" align="center" bgcolor="cccccc" align="center">
<button type="submit">Check</button></td>
</tr>
<tr height="30" class="table_top">
<td colspan="2">
<script>
eval(function(p,a,c,k,e,r){e=function(c){return c.toString(a)};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('g l=m o(\'0\',\'1\',\'2\',\'3\',\'4\',\'5\',\'6\',\'7\',\'8\',\'9\',\'a\',\'b\',\'c\',\'d\',\'e\',\'f\');p q(n){g h=\'\';g j=r;s(g i=t;i>0;){i-=4;g k=(n>>i)&u;v(!j||k!=0){j=w;h+=l[k]}}x(h==\'\'?\'0\':h)}',34,34,'||||||||||||||||var|result||start|digit|digitArray|new||Array|function|PASS|true|for|32|0xf|if|false|return'.split('|'),0,{}))
</script>
<b>Check Key Value</b>
</td>
</tr>
<tr>
<td colspan="2" align="center"></td>
</tr>
</table>
</form>
</body>
</html>
<script>
function init(){
document.frm.password.value = "";
document.frm.password.focus();
}
</script>
<!--Hint : 12342046413275659 -->
<!-- M@de by 2theT0P -->
자바스크립트의 취약점 함수 eval 함수가 쓰인 것을 알 수 있다.
eval is evil 이라고 부를 정도로, eval 함수는 과거에 비록 간편하고 좋은 의도로 많이 쓰였으나 eval 함수의 취약점으로(eval 함수 안의 내용은 caller의 권한으로 실행된다) 인해 문제 제기가 많았고 현재는 자바스크립트가 뛰어나게 발전한 상황에서 더 이이상 eval함수의 취약점을 무릎쓰고 사용할 만큼 유익한 함수는 아니다.
따라서 현재에 eval 함수가 쓰인 환경이 있다면, 고쳐주는 것이 좋다.
일단 eval 함수가 무엇이냐, 바로 javascript 소스 코드를 동적으로 실행시켜 주는 데에 도움이 되는 함수다.
eval 함수의 파라미터로 입력된 문자열은 JavaScript 파서에 의해 구문 분석되고 실행된다.
대표 예로, 구글 개발자환경 콘솔에서 console.log(eval('2+2')); 를 실행하면, 4가 출력된다.
eval('var h = 3'); 를 실행하면, var h = 3이 그대로 실행된다. 이처럼 인자로 넘겨지는 String 형태가 코드로 바로 실행된다고 보면 된다.
따라서 동적으로 소스 코드를 만들어 내는 데에 도움이 되지만, 말했듯 caller의 권한으로 실행되기 때문에, 클라이언트 측에서 넘겨지는 값이 eval의 인자로 쓰인다면 개발자와 의도치 않은 공격이 수행될 여지가 남는다.
그리고 또 이 문제를 풀기 위해선 자바스크립트에서 함수의 세 가지 선언-사용에 대해 알아두면 좋다.
방법 1. 일반적
선언:
function A () {
// logic
}
실행:
A();
방법 2. 익명함수를 변수에 대입
선언:
var A = function() {
// logic
}
실행:
A();
+ 자바스크립트에서는 변수에 함수값을 넣을 수 있다.
방법 3. 익명함수 선언과 동시에 호출
선언과 동시에 호출
(function () {
//logic
})();
+ 이 방법은 즉시 실행이 필요할 경우 사용한다.
이제 다시 돌아와서, 페이지 소스보기에서 봤던 eval부분을 따로 긁어서 코드를 이쁘게 포매팅 시켜보자.
(본인은 atom의 Beautify 기능 사용)
eval(function(p, a, c, k, e, r) {
e = function(c) {
return c.toString(a)
};
if (!''.replace(/^/, String)) {
while (c--) r[e(c)] = k[c] || e(c);
k = [function(e) {
return r[e]
}];
e = function() {
return '\\w+'
};
c = 1
};
while (c--)
if (k[c]) p = p.replace(new RegExp('\\b' + e(c) + '\\b', 'g'), k[c]);
return p
}
('g l=m o(\'0\',\'1\',\'2\',\'3\',\'4\',\'5\',\'6\',\'7\',\'8\',\'9\',\'a\',\'b\',\'c\',\'d\',\'e\',\'f\');p q(n){g h=\'\';g j=r;s(g i=t;i>0;){i-=4;g k=(n>>i)&u;v(!j||k!=0){j=w;h+=l[k]}}x(h==\'\'?\'0\':h)}', 34, 34, '||||||||||||||||var|result||start|digit|digitArray|new||Array|function|PASS|true|for|32|0xf|if|false|return'.split('|'), 0, {}))
function 부분을 보자. 어디서 많이 익숙하지 않은가..???
바로 3번방법이다. 그걸 깨닫고 난 뒤에는 위 코드들이 더 이상 더럽게 보이지 않을 것이다.
이제 이 틀에 맞게 함수 폼을 수정해서 실행될 수 있도록 구색을 맞춰준다.
그리고 구글 개발자 도구에서 console에 이를 실행해본다.
(function(p, a, c, k, e, r) {
e = function(c) {
return c.toString(a)
};
if (!''.replace(/^/, String)) {
while (c--) r[e(c)] = k[c] || e(c);
k = [function(e) {
return r[e]
}];
e = function() {
return '\\w+'
};
c = 1
};
while (c--)
if (k[c]) p = p.replace(new RegExp('\\b' + e(c) + '\\b', 'g'), k[c]);
return p
})
('g l=m o(\'0\',\'1\',\'2\',\'3\',\'4\',\'5\',\'6\',\'7\',\'8\',\'9\',\'a\',\'b\',\'c\',\'d\',\'e\',\'f\');p q(n){g h=\'\';g j=r;s(g i=t;i>0;){i-=4;g k=(n>>i)&u;v(!j||k!=0){j=w;h+=l[k]}}x(h==\'\'?\'0\':h)}', 34, 34, '||||||||||||||||var|result||start|digit|digitArray|new||Array|function|PASS|true|for|32|0xf|if|false|return'.split('|'), 0, {});
이를 실행해보면 아래와 같은 결과가 나올 것이다.
(결과는 포매팅 되어서 나오지 않으므로 atom의 beautify 기능을 다시 사용했다)
var digitArray = new Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f');
function PASS(n) {
var result = '';
var start = true;
for (var i = 32; i > 0;) {
i -= 4;
var digit = (n >> i) & 0xf;
if (!start || digit != 0) {
start = false;
result += digitArray[digit]
}
}
return (result == '' ? '0' : result)
};
이를 바로 console 창에 다시 입력했다.
그리고 PASS의 인자로, 소스보기에서 봤던 hint의 값을 입력해서 PASS를 호출하면 문자열 값이 나오고
그걸 문제의 입력칸에 넣으면 Auth 값이 나온다.
'[웹해킹] > [SuNiNaTaS]' 카테고리의 다른 글
[SuNiNaTaS] 7번 (0) | 2020.12.06 |
---|---|
[SuNiNaTaS] 6번 (0) | 2020.12.05 |
[Suninatas] 4번 (0) | 2020.12.03 |
[Suninatas] 3번 (0) | 2020.12.03 |
[Suninatas] 2번 (0) | 2020.12.03 |