课前准备¶
- 准备一个自己喜欢的笔记软件,记录自己学习知识
- 学习和了解基本Linux命令,准备好一个linux环境
- 学习基础的PHP语法和PHP环境
- 了解Base64、url编码
基础学习¶
说明和介绍:
一些对RCE的介绍
https://www.cloudflare.com/zh-cn/learning/security/what-is-remote-code-execution/
简单介绍¶
RCE 指的是 远程代码执行(Remote Code Execution)
CTF中RCE主要的几种类型
- 任意代码执行
- 无字母RCE
- 无参数RCE
- 无回显命令执行
Linux¶
这是一个很丰富的研究,三眼两语难以讲述,需要我们不断持续的学习和实践,也许有一天会爱上Linux
一切皆文件
初步了解¶
什么是 Linux?
简单来说,Linux 是一种开源的操作系统。它就像电脑的“灵魂”,控制着硬件并运行各种软件。更准确地说,Linux 最初指的是操作系统的内核(Kernel),是核心部分。但我们常说的“Linux”,通常指的是基于 Linux 内核构建的完整操作系统,它包含各种工具、应用程序和图形界面等。
Linux 的应用场景:
- 服务器: 网站、应用程序、数据库等。
- 嵌入式系统: 路由器、智能电视、安卓手机等。
- 个人电脑: 一些用户选择 Linux 桌面操作系统。
- 超级计算机: 几乎所有超级计算机都运行 Linux。
Linux发行版本
- Ubuntu-以其用户友好性、强大的社区支持和丰富的软件库而闻名 https://ubuntu.com/
- Kail linux --专门为 渗透测试、安全审计和数字取证 而设计。它预装了大量的安全工具,涵盖了信息安全领域的各种任务,因此也被称为“黑客操作系统”。
- https://www.kali.org/
环境配置
- VMware虚拟机
- WSL
WSL(Windows Subsystem for Linux,Windows 下的 Linux 子系统)是 Microsoft 提供的一种功能,允许用户在不使用虚拟机或双系统的情况下,在 Windows 上运行原生的 Linux 环境。它使开发者可以直接在 Windows 中运行 Linux 命令行工具、脚本和程序,同时与 Windows 文件系统无缝集成。
- 或者是服务器平台
文件目录结构¶
树状目录结构:
在 Linux 或 Unix 操作系统中,所有的文件和目录都被组织成以一个根节点开始的倒置的树状结构。
文件系统的最顶层是由根目录开始的,系统使用 / 来表示根目录。在根目录之下的既可以是目录,也可以是文件,而每一个目录中又可以包含子目录文件。如此反复就可以构成一个庞大的文件系统。
Windows 的文件结构以 层级目录树 的形式组织,根目录通常为一个盘符(例如
C:\
)
根目录 /
: 它是整个文件系统的顶层目录,所有其他目录都挂载在这个目录下。
目录(Directory): 类似于 Windows 的文件夹,用于组织和存储文件。
文件(File): 存储实际数据的地方,可以是文本文件、程序文件、图像文件等等。
路径(Path): 用于定位文件或目录的字符串,例如 /home/user/documents/file.txt
。
- 绝对路径: 从根目录
/
开始的完整路径,例如/etc/passwd
。 - 相对路径: 相对于当前目录的路径,例如
documents/file.txt
(如果当前目录是/home/user
)。
基础命令¶
学习 Linux 离不开命令行(终端),以下是一些最常用的命令:
ls
:列出目录内容ls
:列出当前目录的文件和文件夹。ls -l
:以详细列表形式显示。ls -a
:显示所有文件,包括隐藏文件。cd
:切换目录cd 目录名
:进入指定目录。cd ..
:返回上一级目录。cd ~
:回到用户的主目录。pwd
:显示当前所在目录mkdir
:创建目录mkdir 目录名
:创建一个新的目录。rmdir
:删除空目录rmdir 目录名
:删除一个空的目录。rm
:删除文件或目录rm 文件名
:删除文件。rm -r 目录名
:递归删除目录及其内容(谨慎使用)。cp
:复制文件或目录cp 源文件 目标文件
:复制文件。cp -r 源目录 目标目录
:复制目录。mv
:移动或重命名文件或目录mv 源文件 目标文件
:重命名文件。mv 源文件 目标目录
:移动文件到目标目录。cat
:查看文件内容man
:查看命令帮助man 命令名
:查看该命令的详细使用手册。
PHP中危险函数¶
evel()函数¶
eval()
函数是 PHP 中一个非常特殊的函数,它可以将一个字符串当作 PHP 代码来执行。这个功能非常强大,但也非常危险,如果使用不当,可能会导致严重的安全问题。
eval()
函数的语法:
1 |
|
$code
:要执行的 PHP 代码字符串。
eval()
函数的作用:
eval()
函数会将 $code
字符串中的内容解析为 PHP 代码,并执行它。执行的代码会继承 eval()
函数所在行的变量作用域。也就是说,在 eval()
中可以访问和修改 eval()
函数外部的变量。
eval()
函数的返回值:
- 如果没有在代码字符串中使用
return
语句,则eval()
返回NULL
。 - 如果在代码字符串中使用了
return
语句,则eval()
返回传递给return
语句的值。 - 从 PHP 7 开始,如果执行的代码中存在解析错误,
eval()
会抛出ParseError
异常。
回显型¶
system()¶
https://www.php.net/manual/zh/function.system.php
System
(PHP 4, PHP 5, PHP 7, PHP 8)
system — 执行外部程序,并且显示输出
1 |
|
实例代码:
1 2 3 4 5 |
|
Passthru¶
https://www.php.net/manual/zh/function.passthru.php
(PHP 4, PHP 5, PHP 7, PHP 8)
passthru — 执行外部程序并且显示原始输出
1 |
|
实例代码:
1 2 3 |
|
pcntl_exec()¶
pcntl_exec()
是 PHP 的一个函数,用于在 当前进程空间 执行指定的程序。它属于 PHP 的 Process Control 扩展(pcntl),主要用于处理 Unix/Linux 系统中的进程管理。与之前提到的system()
、exec()
、shell_exec()
等函数不同,pcntl_exec()
不会创建新的子进程,而是 替换 当前进程。这意味着调用pcntl_exec()
之后,原来的 PHP 脚本将停止执行,取而代之的是执行指定的程序。
函数原型:
$path
: 要执行的程序的路径。可以是绝对路径或相对路径。
$args
: (可选)传递给程序的参数数组。
$envs
: (可选)传递给程序的环境变量数组。
1 |
|
几个简单的例子:
1 2 3 4 5 6 7 8 9 |
|
正常情况下:不会输出回显
可以采用:
无回显¶
exec()¶
基本语法:
1 |
|
$command
: 要执行的命令,可以是任何有效的系统命令。$output
: 可选参数,用于存储命令执行的输出结果。每行输出将作为数组的一个元素。$return_var
: 可选参数,用于存储命令执行后的返回状态码。通常,状态码 0 表示命令成功执行。
函数特性:
返回最后一行输出: exec()
函数只返回命令输出的最后一行。
不显示输出: exec()
本身不会将命令输出打印到屏幕上。如果需要显示输出,可以使用 echo
或 print_r
等函数处理 $output
数组。
例子:
正常情况下:不会输出回显
可以采用:
- 保存变量
1 2 3 |
|
- var_dump
var_dump()
是 PHP 中一个非常有用的内置函数,主要用于输出变量的详细信息,包括变量的类型和值。它在调试代码和分析变量状态时非常有用。
var_dump()
的作用:
- 显示变量的类型: 例如,
int
(整型)、string
(字符串)、bool
(布尔型)、array
(数组)、object
(对象)等。- 显示变量的值: 输出变量的具体内容。
- 递归展开数组和对象: 对于数组和对象,
var_dump()
会递归地显示其内部的元素和属性,并使用缩进清晰地展示其结构。- 显示字符串的长度: 如果变量是字符串,还会显示字符串的长度。
执行命令
code .
在vscode中打开当前目录
calc
召唤计算器
执行运算符¶
官方解释:
PHP 支持一个执行运算符:反引号。注意这不是单引号!PHP 将尝试将反引号中的内容作为 shell 命令来执行,并将其输出信息返回(即,可以赋给一个变量而不是简单地丢弃到标准输出)。使用反引号运算符“`”的效果与函数 shell_exec() 相同。
1 |
|
注意:
关闭了 shell_exec() 时反引号运算符是无效的。
注意:
与其它某些语言不同,反引号不能在双引号字符串中使用。
使用例子:
- 列出当前目录文件
1 2 3 4 |
|
- 获取系统时间
1 2 3 |
|
- 检测ping
1 2 3 4 5 |
|
技巧¶
文件读取¶
cat:连接文件并打印到标准输出。这是最常用的查看文件内容的命令,会将整个文件内容一次性显示出来。
cat filename
:显示文件内容。cat -n filename
:显示文件内容并显示行号。cat file1 file2
:连接 file1 和 file2 并显示。
more:分页显示文件内容。按空格键向下翻页,按 q 键退出。
less:与 more 类似,但功能更强大,支持上下翻页(使用 Page Up 和 Page Down 键),搜索等功能。推荐使用 less 代替 more。
head:显示文件的前几行,默认显示前 10 行。
head filename
:显示文件前 10 行。head -n 20 filename
:显示文件前 20 行。
tail:显示文件的后几行,默认显示后 10 行。
tail filename
:显示文件后 10 行。tail -n 20 filename
:显示文件后 20 行。tail -f filename
:实时跟踪文件尾部的更新,常用于查看日志文件。
tac:反向显示文件内容,从最后一行开始显示,是 cat 的反向操作。
nl:显示文件内容并显示行号,类似于 cat -n
。
od:以不同的格式(如八进制、十六进制、二进制等)显示文件内容,常用于查看二进制文件。
od -x filename
:以十六进制显示文件内容。od -b filename
:以八进制显示文件内容。
vi/vim:文本编辑器,也可以用来查看文件内容。使用 vi/vim 打开文件后,可以使用各种命令进行浏览和编辑。
vi filename
或vim filename
:打开文件。- 在 vi/vim 中,可以使用
/keyword
进行搜索,按 n 查找下一个匹配项。
sort:对文件内容进行排序后输出。
sort filename
:按字母顺序排序。
uniq:去除文件中的重复行,通常与 sort 结合使用。
sort filename | uniq
:先排序再去重。
file:确定文件类型。
file filename
:显示文件类型。file -f filelist
:从文件中读取文件名列表并逐个检查文件类型。如果遇到错误,会给出具体的错误信息,这印证了你提到的“报错出具体内容”。
命令拼接符¶
;
(分号): 顺序执行多个命令,彼此之间没有依赖关系。无论前面的命令是否成功执行,后面的命令都会执行。
Linux 独有的
1 2 3 4 |
|
&&
(逻辑与): 只有前面的命令执行成功(返回状态码为 0),后面的命令才会执行。如果前面的命令执行失败(返回状态码非 0),则后面的命令不会执行
1 2 3 |
|
||
(逻辑或): 只有前面的命令执行失败(返回状态码非 0),后面的命令才会执行。如果前面的命令执行成功(返回状态码为 0),则后面的命令不会执行。
1 2 3 4 |
|
|
(管道符): 将前一个命令的输出作为后一个命令的输入。这用于将多个命令连接起来,形成一个处理数据的流水线。
1 2 3 4 |
|
实战一下:
一个最简单的示例¶
1 2 3 4 5 6 7 8 9 10 |
|
常规解法
进一步学习:
一句话木马¶
一句话木马 是一种简短的恶意代码,通常用于在目标服务器上创建一个后门,以便攻击者远程控制该服务器或执行其他恶意操作。它主要出现在 Web 安全领域,特别是涉及 PHP、ASP、JSP 等动态语言的 Web 应用程序中。
1 2 3 |
|
对于PHP中的解释:
$_POST['cmd']
:从 HTTP POST 请求中获取参数值。eval()
:将获取的参数作为代码执行。@
:隐藏错误信息,增加隐蔽性
然后利用中国蚁剑这种连接shell的平台连接
https://github.com/AntSwordProject/ (具体安装自行搜索了)
连接配置
网站目录结构
虚拟shell终端
Bypass¶
空格Bypass¶
在过滤了空格的系统中,以cat flag.txt为例,系统不允许我们输入空格或输入后被过滤。
${IFS}
$IFS$9
(可以是别的)
$IFS
:$IFS
是 "Internal Field Separator"(内部字段分隔符)的缩写。它是一个环境变量,用于定义 shell 在解释命令行参数或输入时如何分割字段(单词)。默认情况下,$IFS
包含空格、制表符和换行符。简单来说,它告诉 shell 如何区分不同的参数。$9
:$9
代表 shell 脚本的第九个命令行参数。如果在执行脚本时提供了九个或更多个参数,$9
就会包含第九个参数的值。如果没有提供第九个参数,$9
的值为空字符串。现在我们来看
$IFS$9
。它的作用是将$IFS
和$9
连接在一起。由于$9
通常为空字符串,所以 IF9
实际上就等同于$IFS
。这个技巧的关键在于如何使用它来绕过空格过滤
可使用${IFS}代替空格。
1 2 3 |
|
- 重定向符绕过(<>)
1 2 |
|
- %09(需要php环境)
php环境下web输入%09等效于空格
1 |
|
%0a
换行符
编码绕过¶
Base64¶
什么是 Base64 编码?
Base64 编码是一种基于 64 个可打印字符来表示二进制数据的编码方式。它常用于在需要以文本形式传输或存储二进制数据的场景中,比如电子邮件、URL 参数、网络传输等。
Base64 编码的特点
- 字符集: Base64 使用以下 64 个字符作为编码表:
- 字母:
A-Z
、a-z
(共 52 个字符)- 数字:
0-9
(共 10 个字符)- 两个符号:
+
和/
(共 2 个字符)- 填充符:
=
(用于填充不足 3 字节的数据)- 数据块划分:
- Base64 将输入数据按 3 字节(24 位)为一组处理,每组被分成 4 个 6 位的块。
- 每个 6 位的块被映射到 Base64 的编码字符集中。
- 数据增长:
- Base64 编码会使数据膨胀,编码后的数据长度约为原始数据的 4/3。
- 如果原始数据长度不是 3 的倍数,Base64 会使用填充符
=
补齐。
1 |
|
使用反引号包含base64解码后的命令
1 |
|
将base64解码后的命令通过管道符传递给bash
1 |
|
HEX编码¶
HEX 编码(十六进制编码)是一种使用十六进制数字(
0-9
和A-F
)来表示数据的编码方式。它将二进制数据转化为十六进制字符串,以方便存储、传输和显示。
在 Bash 中,可以使用 xxd
和 printf
等工具来对十六进制(hex)进行编码和解码。
1. 将字符串编码为十六进制¶
使用 xxd
将字符串转换为十六进制:
1 |
|
- 示例:
1 |
|
输出:
1 |
|
2. 将十六进制解码为字符串¶
使用 xxd
将十六进制解码回字符串:
1 |
|
- 示例:
1 |
|
输出:
1 |
|
3. 使用 printf
进行十六进制解码¶
如果没有 xxd
,也可以使用 printf
解码十六进制:
1 |
|
- 示例:
1 |
|
输出:
1 |
|
变量拼接¶
使用shell变量拼接被黑名单限制的关键词
1 |
|
单双引号¶
- 单引号----
''
- 双引号---
""
- 反斜杠---
\
我们可以通过ca''t ca""t c"a"t ca\t
这样来bypass’
一道比较综合的例题¶
[GXYCTF2019]Ping Ping Ping
之前让大家做过一下
https://buuoj.cn/challenges#[GXYCTF2019]Ping%20Ping%20Ping
进入题目发现提示我们传入ip
1 2 3 4 |
|
我们简单地传入127.0.0.1,测试一下发现是可以ping的
尝试命令执行
1 |
|
过滤空格
1 |
|
过滤一些符号---{}
1 |
|
过滤flag
1 2 3 |
|
查看一下index
1 |
|
看回显得到
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
可以看到过滤规则
1 2 |
|
bash
和 sh
是 Unix/Linux 系统中常见的 Shell 类型。Shell 是一种命令行解释器,它提供用户与操作系统之间交互的接口。通过 Shell,你可以运行命令、编写脚本来自动化任务、管理文件系统等。
其他¶
- * 星号
通配符 (Wildcard)
这是星号最常见的用法。在文件名扩展 (Filename expansion) 中,它可以代表任何字符,包括空字符。例如:
ls *.txt
会列出当前目录下所有以.txt
结尾的文件。rm -rf *
会删除当前目录下的所有文件和目录 (请谨慎使用!)
示例:
preg_match
函数- 示例:
- 成功匹配返回
1
。 - 如果没有匹配到内容,返回
0
。 - 如果发生错误,返回
false
。
1 2 3 4 5 6 7 8 9 |
|
- 简单检测脚本
对于单个过滤字符进行检测,输出可以使用的字符
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
- PHP代码内容不能明文显示
!!!! 这是一个比较重要的细节
例子:
1 2 |
|
展示视图里面什么也没有
查看网站源代码,才能看到内容
- hackbar使用
单引号字符和双引号字符
在 PHP 中,双引号 (" "
) 和单引号 (' '
) 都可以用来表示字符串,但它们有一些关键区别:
-
双引号 (
**" "**
) -
双引号字符串会解析特殊字符和变量。
- 可以在双引号中直接使用变量,PHP 会将变量替换为其值。
- 支持转义字符,例如
\n
(换行符)、\t
(制表符)、\\
(反斜杠)等。
示例:
1 2 |
|
在这里,$name
会被解析为变量的值,\n
也会被解析为换行符。
-
单引号 (
**' '**
) -
单引号字符串不会解析变量或特殊字符(除了少数几个转义字符)。
- 在单引号字符串中,变量会被当作普通文本处理。
- 唯一支持的转义字符是
\'
(单引号)和\\
(反斜杠)。
示例:
1 2 |
|
在这里,$name
不会被解析为变量,而是直接作为字符串输出,\n
也不会被解释为换行符。
总结:
- 双引号:用于需要解析变量或转义字符的字符串。
- 单引号:用于纯文本字符串,不需要解析任何变量或转义字符。
示范-WP¶
第一题¶
1 2 3 4 5 |
|
ban了"flag"这个字符利用匹配
1 2 3 |
|
第二题¶
相比于上一题多ban了php
, system
1 |
|
第三题¶
1 2 3 4 5 |
|
又是多ban了几个东西
1 2 3 4 |
|
简单的解释一下这个
show_source(next(array_reverse(scandir(pos(localeconv())))));
localeconv()
返回当前地区设置的一个关联数组。
pos(localeconv())
获取该数组中的第一个元素。
将该元素作为目录路径,调用 scandir()
获取该目录中的文件列表。
反转文件列表(array_reverse()
)。
返回反转后的文件列表中的下一个元素(next()
)。
最后,调用 show_source()
尝试显示该文件的内容。
提升学习¶
学有余力的话可以继续学习下面几个方向
- 反弹shell
- 无字母RCE
- 无参数RCE
- 无回显命令执行
- 文件包含,各种协议的了解
作业¶
!重要要求
学习并写完题目后,编写学习笔记和解题Wp(需含图片),
按照要求提交PR至 https://github.com/natro92/2025WinTraining 处。
要求记录你的学习历程和知识点
- Ctfhub-RCE模块----命令注入
地址:https://www.ctfhub.com/#/skilltree
- 完成RCE-labs[0-8]题(写wp和学习笔记)
- 学习Linux基本命令和操作,自己搭建一个Linux环境(Vmware或者wsl都可以)记录并写下笔记
- 学习PHP基本语法
- 学有余力可以继续学习其他内容和知识,一样的要求记录笔记提交
一些资料¶
更多的面对自己的困惑利用搜索引擎去搜索和查询,同时可以借助大模型提高我们的效率
- Linux命令手册
https://www.freecodecamp.org/chinese/news/the-linux-commands-handbook/
- linux深入,一篇文章
https://medium.com/@gzanan/%E5%BC%80%E7%AF%87-69b29a11f71d
- PHP官方文档
https://www.php.net/manual/zh/index.php
- CTFSHWOW-命令执行题解
- 正则表达式学习
https://regexlearn.com/zh-cn/learn
- 正则表达式在线
- Linux特殊字符
https://www.cnblogs.com/balaamwe/archive/2012/03/15/2397998.html
- 不同shell脚本类型
https://juejin.cn/post/7382892409815859209