본문 바로가기

Wargame(hacking)/webhacking.kr

Webhacking.kr : old-05

Write-Up

 

처음 페이지를 보면, Login 과 join 버튼이 있다. 하지만 join 버튼 클릭 시, 엑세스가 거부된다. Login 버튼 클릭 시, 

 

challenge/web-05/mem/login.php

 

위 URL로 이동되며, 로그인 페이지를 볼 수 있다. 

 

그림 1

 

위 그림 1과 같이 다양한 SQL Injection 시도를 했는데, 먹지 않았다. 아래 같은 Time based 도 안된다. 

 

'or 1=1 AND if(1=1,sleep(10),false)#

'or 1=1 AND if (1=1) waitfor delay '0:0:10'#

'or 1=1 AND if 1=1 then BEGIN dbms_lock.sleep(10); END; end if--+

 

현재 challenge/web-05/mem/login.php 의 URL인데,  /mem/ 디렉터리로 디렉터리 인덱싱 취약점이 있는지 확인해본다. 

 

그림 2

 

위 그림 2와 같이 디렉터리 인덱싱 취약점이 있어, 디렉터리 내 파일구조를 확인할 수 있다. join.php에 접근해 보았다. 

 

"bye" 라는 alert() 가 발생한다. <script> 태그가 있는 곳을 가보았고, 복잡한 코드들이 존재했다. 해당 코드를 아래와 같이 코드 뷰티(?)를 이용해 보기 좋게 만들어줬다. 

 

l = 'a';
ll = 'b';
lll = 'c';
llll = 'd';
lllll = 'e';
llllll = 'f';
lllllll = 'g';
llllllll = 'h';
lllllllll = 'i';
llllllllll = 'j';
lllllllllll = 'k';
llllllllllll = 'l';
lllllllllllll = 'm';
llllllllllllll = 'n';
lllllllllllllll = 'o';
llllllllllllllll = 'p';
lllllllllllllllll = 'q';
llllllllllllllllll = 'r';
lllllllllllllllllll = 's';
llllllllllllllllllll = 't';
lllllllllllllllllllll = 'u';
llllllllllllllllllllll = 'v';
lllllllllllllllllllllll = 'w';
llllllllllllllllllllllll = 'x';
lllllllllllllllllllllllll = 'y';
llllllllllllllllllllllllll = 'z';
I = '1';
II = '2';
III = '3';
IIII = '4';
IIIII = '5';
IIIIII = '6';
IIIIIII = '7';
IIIIIIII = '8';
IIIIIIIII = '9';
IIIIIIIIII = '0';
li = '.';
ii = '<';
iii = '>';
lIllIllIllIllIllIllIllIllIllIl = lllllllllllllll + llllllllllll + llll + llllllllllllllllllllllllll + lllllllllllllll + lllllllllllll + ll + lllllllll + lllll;
lIIIIIIIIIIIIIIIIIIl = llll + lllllllllllllll + lll + lllllllllllllllllllll + lllllllllllll + lllll + llllllllllllll + llllllllllllllllllll + li + lll + lllllllllllllll + lllllllllllllll + lllllllllll + lllllllll + lllll;
if (eval(lIIIIIIIIIIIIIIIIIIl).indexOf(lIllIllIllIllIllIllIllIllIllIl) == -1) {
    alert('bye');
    throw "stop";
}
if (eval(llll + lllllllllllllll + lll + lllllllllllllllllllll + lllllllllllll + lllll + llllllllllllll + llllllllllllllllllll + li + 'U' + 'R' + 'L').indexOf(lllllllllllll + lllllllllllllll + llll + lllll + '=' + I) == -1) {
    alert('access_denied');
    throw "stop";
} else {
    document.write('<font size=2 color=white>Join</font><p>');
    document.write('.<p>.<p>.<p>.<p>.<p>');
    document.write('<form method=post action=' + llllllllll + lllllllllllllll + lllllllll + llllllllllllll + li + llllllllllllllll + llllllll + llllllllllllllll +
        '>');
    document.write('<table border=1><tr><td><font color=gray>id</font></td><td><input type=text name=' + lllllllll + llll + ' maxlength=20></td></tr>');
    document.write('<tr><td><font color=gray>pass</font></td><td><input type=text name=' + llllllllllllllll + lllllllllllllllllllllll + '></td></tr>');
    document.write('<tr align=center><td colspan=2><input type=submit></td></tr></form></table>');
}

 

"bye" 가 나온 부분을 보도록 한다. name이 oldzombie 이던, value가 oldzombie이던 상관 없이 쿠키를 추가해준다. oldzombie라는 문자열이 쿠키 값내에 존재하면 된다. 

 

eval('document.cookie')
'oldzombie=oldzombie; PHPSESSID=1234455555324234234'

eval('document.cookie').indexOf('oldzombie')
0

<<< 아래는 oldzombie 쿠키 삭제 후 >>>

eval('document.cookie').indexOf('oldzombie')
-1

<<< 쿠키 생성하는데, name=1234, value=oldzombie >>>

eval('document.cookie')
'PHPSESSID=1234455555324234234; 1234=oldzombie'

eval('document.cookie').indexOf('oldzombie')
36

 

쿠키 값이 해결되니, 이제 "bye" 대신에 access denied 가 출력된다. document.URL 시, mode=1 부분이 있어야 해당 부분을 통과할 수 있으므로, /?mode=1 과 같이 요청해준다. 

 

그럼 아래 그림 3과 같은 join page가 나오고, join을 진행할 수 있다. 필자는 처음에 'happy'로 가입을 진행했는데, 로그인 시, 아래와 같은 메시지가 발생했다. 

 

Hello happy
You have to login as admin .

 

그래서 admin으로 가입을 진행하려했으나, 이미 존재하는 id라고 하였다. 그래서 앞에 공백을 추가하여, (공백)admin / 1234 와 같이 가입을 진행했다. 

 

그림 3

 

가입에 성공할 수 있었고, login 페이지에서 login을 그대로 진행 시 문제를 해결할 수 있다. 

 

아래와 같이 공백 및 %00을 사용해 문제를 해결할 수도 있다. 문제 해결을 위해서 admin이라는 keyword만 들어가있으면 되는 것 같다. mysql 상에서 '(공백)admin' 과 'admin' 비교 시, false 값이 나오기 때문이다. ( 'admin' = 'admin(공백)' 은 true. 아래 기술 블로그 참조 ) 

 

[버프슈트 사용]
id=admin%20%00&pw=1
id=%20%20%20admin&pw=1

 

 

 

참고 

 

https://techblog.woowahan.com/2559/

 

MySQL에서 ‘a’ = ‘a ‘가 true로 평가된다? | 우아한형제들 기술블로그

{{item.name}} DB 알못의 어떤 리서치 개요 안녕하세요 기계인간 이종립입니다. FC플랫폼개발팀에서 배민찬 백엔드를 개발하고 있습니다. DB알못인 저는 업무 중에 우연히 MySQL에서 'a' = 'a '의 결과가

techblog.woowahan.com

 

https://ko.javascript.info/cookie

 

쿠키와 document.cookie

 

ko.javascript.info

 

https://ko.w3hmong.com/mysql/func_mysql_trim.htm

 

MySQL TRIM() 함수

MySQL TRIM() 함수 ❮ MySQL 기능 예시 문자열에서 선행 및 후행 공백 제거: SELECT TRIM('    SQL Tutorial    ') AS TrimmedString; 정의 및 사용 TRIM() 함수는 문자열에서 선행 및 후행 공백을 제거합니다. 통사

ko.w3hmong.com

그림 4

 

https://codingeverybody.kr/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%B0%B0%EC%97%B4-indexof-%ED%95%A8%EC%88%98/

 

자바스크립트 배열 indexOf() 함수 – 배열에서 요소의 위치 찾기 - 코딩에브리바디

자바스크립트 배열 indexOf() 함수는 배열과 관련된 프로토타입 메서드(Array 인스턴스)로, 배열에서 인수로 전달된 요소를 찾아 첫 번째로 검색된(등장한) 요소의 인덱스를 반환합니다. 인수로 전

codingeverybody.kr