목표
admin / admin1234 로 로그인한 뒤, 미사일 발사를 눌러라! :D
공격
공격순서
admin으로 로그인하고 발사버튼을 눌러본다. 그리고 내부코드를 확인해본다
HTTP/1.1 200 OK
Date: Tue, 20 Jun 2023 22:03:57 GMT
Server: Apache/2.4.18 (Ubuntu)
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 1516
Connection: close
Content-Type: text/html; charset=UTF-8
<!-- Show password protected content down here -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="css/stylesheet.css">
<title>Auth System</title>
</head>
<body>
<script type="text/javascript" src="./js/user.js"></script>
<script type="text/javascript" src="./js/game.js"></script>
<div class="container">
<div class="header clearfix">
<nav>
<ul class="nav nav-pills pull-right">
<li role="presentation" class="active"><a href="#">Home</a></li>
<li role="presentation"><a href="#">About</a></li>
<li role="presentation"><a href="#" onclick="goMenu('0417','')">LogOut</a></li>
</ul>
</nav>
<h3 class="text-muted">Segfault</h3>
</div>
<div class="jumbotron">
<h1>핵미사일 시스템</h1>
<p class="lead">DANGER</p>
<p>발사 버튼은 관리자만 이용 가능합니다.</p>
</br></br>
<p><a class="btn btn-lg btn-danger" href="#" role="button" onclick="goMenu('9999','')">Fire</a></p>
</div>
<div class="row marketing">
</div>
<footer class="footer">
<p>© Segfault</p>
</footer>
</div>
<script src="../../assets/js/ie10-viewport-bug-workaround.js"></script>
</body>
</html>
버튼을 자세히 확인
onclick을 보면 goMenu라는 함수를 사용하는것을 볼수 있다.
이 함수는 피라미터를 두개 밭는다.
<div class="jumbotron">
<h1>핵미사일 시스템</h1>
<p class="lead">DANGER</p>
<p>발사 버튼은 관리자만 이용 가능합니다.</p>
</br></br>
<p><a class="btn btn-lg btn-danger" href="#" role="button" onclick="goMenu('9999','')">Fire</a></p>
</div>
<a class="btn btn-lg btn-danger" href="#" role="button" onclick="goMenu('9999','')">Fire</a>
burp suite으로 함수 찾기
이제 goMenu라는 함수를 사용하는것을 알수 있다. 이제 goMenu함수가 어떤식으로 작동하는지 찾아봐야 하는데, 방법은 여러가지가 있다.
코드 분석
위 페이지의 body 시작점을 보면, 아래 자바스크립트 파일을 가져오는것을 볼수 있다.
<script type="text/javascript" src="./js/user.js"></script>
<script type="text/javascript" src="./js/game.js"></script>
즉, goMenu함수는 저 두 자바스트립트중 하나에 있다고 추측할수 있다.
burp suite의 응답섹션의 가장 아래쪽에서는 서치가 가능하다. 여기에 찾고 싶은 것= 함수이름을 넣고. 화살표키를 이용해서 이동하며 확인한다. 매치하는 단어가 있다면 아래와 같이 노란색으로 잠깐 노티스를 준다.
burp suite에서 자바스크립트 파일(.js)을 찾을수 없다면
이미 예전에 다운받은 캐시를 사용한 경우 다시 받는 방법
- 크롬 개발자도구 (f12) 혹은 오른쪽 위에 점세개-more tools-개발자 도구를 연다.
- 연 상태에서 새로고침 버튼 위을 오론쪽 버튼 누른다
- 캐시 비우기 및 강력 새로고침을 누른다
이후 다시 확인해보면 찾을수 있다.
goMenu 함수 분석
자바 스크립트 코드가 난독화 되어 있는것을 볼수 있다.
난독화 되어 있는 코드는 정적분석과 동적분석이 가능하다.
HTTP/1.1 200 OK
Date: Tue, 20 Jun 2023 22:03:58 GMT
Server: Apache/2.4.18 (Ubuntu)
Last-Modified: Thu, 15 Jun 2023 01:52:14 GMT
ETag: "77d-5fe215140bafa-gzip"
Accept-Ranges: bytes
Vary: Accept-Encoding
Content-Length: 1917
Connection: close
Content-Type: application/javascript
function user_auth_check(needLevel, userLevel){
if(needLevel == userLevel){
return true;
}else{
return false;
}
}
function goMenu(code, userLevel){
switch (code){
case '9999':
if(user_auth_check('admin',userLevel)){
location.href=(function(){var J=Array.prototype.slice.call(arguments),C=J.shift();return J.reverse().map(function(N,Q){return String.fromCharCode(N-C-14-Q)}).join('')})(20,150,140,136)+(14).toString(36).toLowerCase()+(21).toString(36).toLowerCase().split('').map(function(I){return String.fromCharCode(I.charCodeAt()+(-13))}).join('')+(27610734146).toString(36).toLowerCase()+(function(){var H=Array.prototype.slice.call(arguments),z=H.shift();return H.reverse().map(function(d,J){return String.fromCharCode(d-z-22-J)}).join('')})(32,167,172,168,175,150,168)+(13).toString(36).toLowerCase()+(function(){var h=Array.prototype.slice.call(arguments),c=h.shift();return h.reverse().map(function(D,U){return String.fromCharCode(D-c-24-U)}).join('')})(22,159,92)+(17).toString(36).toLowerCase()+(function(){var f=Array.prototype.slice.call(arguments),M=f.shift();return f.reverse().map(function(n,S){return String.fromCharCode(n-M-50-S)}).join('')})(49,211);
break;
}else{
alert('권한이 없습니다.');
break;
}
case '0417':
location.href=(1111).toString(36).toLowerCase().split('').map(function(r){return String.fromCharCode(r.charCodeAt()+(-71))}).join('')+(21).toString(36).toLowerCase()+(function(){var g=Array.prototype.slice.call(arguments),b=g.shift();return g.reverse().map(function(l,p){return String.fromCharCode(l-b-38-p)}).join('')})(61,212,203,210)+(1109).toString(36).toLowerCase()+(function(){var U=Array.prototype.slice.call(arguments),C=U.shift();return U.reverse().map(function(b,K){return String.fromCharCode(b-C-11-K)}).join('')})(52,176,109)+(637).toString(36).toLowerCase();
break;
default:
alert('없는 메뉴입니다.');
}
}
함수가 실행되면 어떤일이 일어나는지 알수 없지만, 여전히 if문은 알수 있으므로, 해결방법은 여러가지가 있다.
- 응답변조를 하여, 위 함수의 if문을 제거
- 요청을 보낼때, goMenu(’9999’,’admin’)으로 요청
- 자바 스크립트 난독화 해제
응답변조를 하여, 위 함수의 if문을 제거
if(user_auth_check('admin',userLevel)){→if(true){
요청을 보낼때, goMenu(’9999’,’admin’);으로 요청
자바 스크립트 난독화 해제
JavaScript Deobfuscator라고 부름. 난독화는 obfuscation
구글에 검색하면 많이 뜸. 아래 싸이트를 사용.
function goMenu(code, userLevel) {
switch (code) {
case "9999":
if (user_auth_check("admin", userLevel)) {
location.href = function () {
var J = Array.prototype.slice.call(arguments), C = J.shift();
return J.reverse().map(function (N, Q) {
return String.fromCharCode(N - C - 14 - Q);
}).join("");
}(20, 150, 140, 136) + 14..toString(36).toLowerCase() + 21..toString(36).toLowerCase().split("").map(function (I) {
return String.fromCharCode(I.charCodeAt() + -13);
}).join("") + 27610734146..toString(36).toLowerCase() + function () {
var H = Array.prototype.slice.call(arguments), z = H.shift();
return H.reverse().map(function (d, J) {
return String.fromCharCode(d - z - 22 - J);
}).join("");
}(32, 167, 172, 168, 175, 150, 168) + 13..toString(36).toLowerCase() + function () {
var h = Array.prototype.slice.call(arguments), c = h.shift();
return h.reverse().map(function (D, U) {
return String.fromCharCode(D - c - 24 - U);
}).join("");
}(22, 159, 92) + 17..toString(36).toLowerCase() + function () {
var f = Array.prototype.slice.call(arguments), M = f.shift();
return f.reverse().map(function (n, S) {
return String.fromCharCode(n - M - 50 - S);
}).join("");
}(49, 211);
break;
} else {
alert("권한이 없습니다.");
break;
}
case "0417":
location.href = 1111..toString(36).toLowerCase().split("").map(function (r) {
return String.fromCharCode(r.charCodeAt() + -71);
}).join("") + 21..toString(36).toLowerCase() + function () {
var g = Array.prototype.slice.call(arguments), b = g.shift();
return g.reverse().map(function (l, p) {
return String.fromCharCode(l - b - 38 - p);
}).join("");
}(61, 212, 203, 210) + 1109..toString(36).toLowerCase() + function () {
var U = Array.prototype.slice.call(arguments), C = U.shift();
return U.reverse().map(function (b, K) {
return String.fromCharCode(b - C - 11 - K);
}).join("");
}(52, 176, 109) + 637..toString(36).toLowerCase();
break;
default:
alert("없는 메뉴입니다.");
}
}
이제 코드분석을 한다면, 리디렉틴 주소를 알수 있습니다.
정리
이 문제는 자바 스크립트에 함수가 노출되어 일어나는 취약점중 하나입니다. 여기에 더해서 자바스크립트가 난독화 되어 있습니다.
'old > Cyber Security' 카테고리의 다른 글
웹 해킹 예제: 인증과 인가 취약점_CTF: 미사일 날리기 (0) | 2023.08.05 |
---|---|
웹 해킹 예제: 인증과 인가 취약점_CTF: 권한 체크 피하기 (0) | 2023.08.05 |
웹 해킹 예제: 인증과 인가 취약점_CTF: Read (0) | 2023.08.05 |
웹 해킹 예제: 인증과 인가 취약점_CTF: 마이페이지 훔쳐보기 (0) | 2023.08.05 |
웹 해킹 예제: 인증과 인가 취약점_CTF: 달콤한 마이페이지 훔쳐보기 (0) | 2023.08.05 |