SQL注入基础
本文最后更新于1 天前,其中的信息可能已经过时,如有错误请发送邮件到1603445435@qq.com

SQL注入漏洞

1.MYSQL

1)MYSQL——一个数据库

2)SQL(结构化查询语言)——用于存取数据以及查询、更新和管理关系数据库系统

php连接数据库:

$connect = mysqli_connect($servername, $username, $password);

3)操作数据库:

(1)增:insert into 表名(字段1,字段2,.......)values(值1,值2,.......);

插入多条数据:

insert into 表名
(字段1,字段2,.......)
values
(值1,值2,.......),
(值11,值12,.......),
(值21,值22,.......);

(2)改:update 表名 set 字段名="值" [where条件];

注:使用where条件,只会修改满足条件的行(记录);不使用where条件,会把字段的所有的值 进行修改。

*(3)查

select * from 表名;
select */字段 from 表名 [where条件];

星号( * )为通配符,表示所有 ;where条件可选

(4)删:delete from 表名 where 条件;

(5)order by语句:对查询返回的结果排序

SELECT * FROM 表名 ORDER BY 列名(字段名);

注:当order by 后的数字大于当前列数(字段数)时会报错。

(6)LIMIT限制:用于限制SELECT语句返回指定的记录数,接受一个或两个数字参数。

SELECT * FROM 表名 LIMIT 偏移量,限制条数;

4)information_schema数据库

mysql数据库5.0以上自带information_schema数据库

schema表:存储所有数据库信息

schema_name列:存储所有数据库名。

tables表:提供了关于数据库中的表的信息

table_name列:存储所有列名

table_schema列:来自哪个数据库

columns表:提供了表中的列信息

column_name列:存储所有列名

table_name列:来自哪个数据表

table_schema:来自哪个数据库

2.sql注入

分类:

  1. 根据注入位置分类:GET注入、POST注入、Head头注入。
  2. 根据结果反馈分类:有回显注入(显错注入)、无回显注入(盲注)
  3. 根据数据类型分类: a. 字符型注入:当输入参数为字符串时,称为字符型。数字型与字符型注入最大的区别在于:数字型 不需要单引号闭合,而字符串类型一般要使用单引号来闭合。 b. 数字型注入:当输入的参数为整型时,如ID、年龄、页码等,如果存在注入漏洞,则可以认为是数 字型注入。

注入点:

1. URL 参数 (GET 请求)

这是最常见、最容易发现的注入点。参数直接显示在浏览器的地址栏中。

  • 位置: URL 问号 ? 后面的键值对。
  • 示例
    • http://example.com/product.php?id=10 (注入点: id)
    • http://example.com/search?q=iphone&sort=price (注入点: q, sort)
    • http://example.com/user.php?name=admin'--
  • 常见参数名: id, page, sort, order, keyword, search, cat, uid 等。

2. 表单数据 (POST 请求)

用户通过网页表单提交的数据,虽然不在 URL 中显示,但同样会被后端接收并处理。需要使用抓包工具(如 Burp Suite)查看。

  • 位置: HTTP 请求体 (Request Body) 中。
  • 场景
    • 登录框: 用户名 (username)、密码 (password)。
      • Payload: admin' OR '1'='1
    • 搜索框: 搜索关键词。
    • 注册/修改资料: 邮箱、昵称、地址等字段。
    • 评论/留言: 评论内容。
  • 隐藏注入点: 有时表单中包含隐藏的 input type="hidden" 字段,攻击者修改这些值也可能触发注入。

3. HTTP 请求头 (Headers)

很多开发者只过滤了 URL 和 POST 数据,却忽略了 HTTP 头部信息。如果后端代码将头部信息记录到数据库(如日志表、访问统计)或用于查询,这里就是注入点。

  • User-Agent: 浏览器标识。很多网站会记录访问者的 UA 到数据库。
    • Payload: Mozilla/5.0 ...' AND SLEEP(5)--
  • Referer: 来源页面地址。
  • X-Forwarded-For / Client-IP: 用户真实 IP 地址。常用于记录日志或反欺诈查询。
    • Payload: 127.0.0.1' UNION SELECT version()--
  • Cookie: 会话标识或个性化设置。
    • 场景:登录后,服务器可能将 Cookie 中的用户 ID 或权限信息解密后直接用于 SQL 查询。
    • Payload: session_id=abc' OR 1=1--

4. 特殊输入位置

  • 文件上传文件名: 如果文件名被存入数据库,且未过滤。
  • JSON/XML 数据体: 现代 API (RESTful/GraphQL) 常使用 JSON 格式传输数据。
    • 示例: {"user_id": "1' OR 1=1--", "action": "delete"}
  • HTTP Method 本身: 极少见,但如果后端解析逻辑有误,可能利用。

5. 二次注入 (Second-Order Injection)

这是一种隐蔽的注入点。

  • 原理: 用户输入的数据第一次被存入数据库时是安全的(因为只是插入),但当这些数据被再次读取并用于构建新的 SQL 语句时(且未过滤),就会触发注入。
  • 场景
    1. 注册时,用户名为 admin' -- (存入数据库)。
    2. 管理员后台查看用户列表时,执行 SELECT * FROM users WHERE name = '$username'
    3. 此时 $username 取自数据库中的恶意数据,导致注入发生。

测试漏洞:

A. 基于错误的注入 (Error-Based)

这是最直接的判断方式。通过在输入框、URL 参数或 Cookie 中提交语法错误的 SQL 语句,观察页面是否返回数据库错误信息。

  • 测试 Payload 示例
    • 在参数后添加单引号:id=1'
    • 添加数学运算:id=1-1 (正常应返回 id=0 的数据) vs id=1'-1 (可能报错)
    • 常见报错字符:', ", ;, --, /*, )
  • 判断依据
    • 如果页面返回类似 SQL syntax error, MySQL server version, ORA-01756, Unclosed quotation mark 等详细的数据库错误堆栈信息,则极大概率存在漏洞
    • 现代应用通常会隐藏错误信息,如果页面直接崩溃(500 Error)或行为异常,也值得怀疑。

B. 布尔盲注 (Boolean-Based Blind)

当数据库错误被隐藏时,可以通过构造逻辑判断语句,观察页面内容的变化(真/假)。

  • 测试逻辑
    • 请求 A (真): id=1 AND 1=1 -> 页面应正常显示内容。
    • 请求 B (假): id=1 AND 1=2 -> 页面应显示“无结果”、内容缺失或布局错乱。
  • 判断依据
    • 如果两个请求返回的页面内容(HTML 长度、特定文本)有明显差异,说明后端执行了 SQL 逻辑判断,可能存在盲注漏洞

C. 时间盲注 (Time-Based Blind)

当页面无内容变化且无报错时,可以让数据库执行休眠命令,通过响应时间的延迟来判断。

  • 测试 Payload 示例
    • MySQL: id=1' AND SLEEP(5)--
    • SQL Server: id=1'; WAITFOR DELAY '0:0:5'--
    • PostgreSQL: id=1' AND PG_SLEEP(5)--
  • 判断依据
    • 如果正常请求响应时间为 0.5 秒,而注入 Payload 的响应时间变成了 5.5 秒左右,说明数据库执行了休眠命令,存在漏洞

D. 联合查询注入 (Union-Based)

尝试使用 UNION SELECT 语句将恶意查询的结果合并到原查询结果中。

  • 测试 Payload
    • id=1' UNION SELECT NULL, NULL, NULL-- (先测试列数)
    • id=1' UNION SELECT 1, 2, 3-- (观察页面上是否显示了数字 1, 2, 3)
  • 判断依据
    • 如果页面上直接显示了注入的数字或数据库版本信息(如 version()),则确认存在漏洞

3.联合查询注入

1.判断是否存在注入

利用'(单引号)或者"(双引号)来判断是否存在漏洞,如果出现SQL语句错误说明有很大的可能会 存在漏洞。

2.判断注入类型:

算数运算判断(推荐):

1.首先观察页面正常回显内容,输入,例id=1

2.然后,修改为一个减法运算,如id=2-1

3.观察结果:

数字型:页面回显内容与访问id=1时一致,说明数据库执行了运算,将结果1作为参数进行查询

字符型:页面回显内容与访问id=2时一致,或报错,说明数据库将2-1当作一个字符串整体去查询

逻辑判断:

(1)数字型:当1 and 1=1成功,1 and 1=2失败,是数字型

(2)字符型:当1' and '1'='1成功,1' and '1'='2失败,可判断为字符型

注:以字符型为例
a. 当用户输入1 and 1=1时,SQL语句变成了:
SELECT first_name, last_name FROM users WHERE user_id ='1 and 1=1' ,实际上最
终查询的还是'1'。
b. 当用户输入1 and 1=2时,SQL语句变成了:
SELECT first_name, last_name FROM users WHERE user_id ='1 and 1=2' ,实际上最
终查询的还是'1'。
c. 当用户输入1' and '1'='1时,SQL语句变成了:
SELECT first_name, last_name FROM users WHERE user_id ='1' and '1'='1' ,实际
上最终查询的是user_id ='1'并且'1'='1'。
d. 当用户输入1' and '1'='2时,SQL语句变成了:
SELECT first_name, last_name FROM users WHERE user_id ='1' and '1'='2' ,实际
上最终查询的是user_id ='1'并且'1'='2'。因为1=2不成立,所以整条语句也都不成立,因
此可以知道页面返回为空是由于sql语句不成立导致的。

3.判断表中列数

为了方便后续获取数据,需要先知道查询的表中显示的字段数,可以使用order by(用于根据指定 的列对结果集进行排序。当order by的数字大于当前的列数时候就会报错,SQL注入利用这个特性来判 断列数)来进行判断。

例:1' order by 1%23(%23是#的url编码,注释掉后面的单引号)

如果当order by 2%23时成功,而order by 3%23时失败,则列数为2

4.确定显示位(回显位)

在一个网站的正常页面,服务端执行SQL语句查询数据库中的数据,客户端将数据展示在页面中,这个展示数据的位置就叫显示位UNION操作符用于合并两个或多个SELECT 语句的结果集,UNION结果集中的列名总是等于UNION中第一个SELECT语句中的列名,并且UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条SELECT语句中的列的顺序必须相同

例:输入1' union select 1,2%23时,可以发现1和2都回显到页面中了,说明这两个位置都可以显示 数据。

一般不查询union左边的内容,这是因为程序在展示数据的时候通常只会取结果集的第 一行数据,所以只要让第一行查询的结果是空集,即union左边的select子句查询结果为空,那么 union右边的查询结果自然就成为了第一行,打印在网页上了。所以让union左边查询不到,可以 将其改为负数或者改为比较大的数字

例:得知列数为3,则输入-1' union select 1,2,3%23,如果页面显示了2和3,那么第2列和第3列就是显示位

找到显示位后,就可以将数字替换为我们想要查询的数据。

5.获取数据

1.获取数据库名
-1' union select 1,database()%23

database():查库名

2.获取数据库中表名
-1' union select 1,table_name from information_schema.tables where
table_schema='dvwa'%23

table_name :表名

information_schema.tables:information_schema数据库中存放表名的表

table_schema='dvwa':库名为dvwa

3.获取表中字段名
-1' union select 1,column_name from information_schema.columns where
table_name='guestbook' and table_schema='dvwa'%23

column_name:字段名

information_schema.columns:information_schema数据库中存放字段名的表

4.获取表中记录

使用group_concat()(将多行合并成一行)

-1' union select 1,group_concat(comment_id,comment,name) from guestbook%23

文末附加内容

评论

  1. 博主 置顶
    Windows Edge
    2 天前
    2026-4-19 17:22:08

    一次小尝试୧(๑•̀⌄•́๑)૭

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
下一篇