Sql注入
原理
Sql注入是通过拼接sql查询语句,使Sql查询的时候发生歧义,导致攻击者可以查询数据库的全部信息
攻击对象是数据库。
存在威胁:
-
SQL注入漏洞对于数据安全的影响:
数据库信息泄漏:数据库中存放的用户的隐私信息的泄露。 网页篡改:通过操作数据库对特定网页进行篡改。 网站被挂马,传播恶意软件:修改数据库一些字段的值,嵌入网马链接,进行挂马攻击。 数据库被恶意操作:数据库服务器被攻击,数据库的系统管理员帐户被窜改。 服务器被远程控制,被安装后门:经由数据库服务器提供的操作系统支持,让黑客得以修改或控制操作系统。 破坏硬盘数据,瘫痪全系统。
sql注入防范
解决SQL注入问题的关键是对所有可能来自用户输入的数据进行严格的检查、对数据库配置使用最小权限原则。通常修复使用的方案有:
代码层面:
1.对输入进行严格的转义和过滤
2.使用参数化(Parameterized):目前有很多ORM框架会自动使用参数化解决注入问题,但其也提供了"拼接"的方式,所以使用时需要慎重!
3.PDO预处理 (Java、PHP防范推荐方法:)
没有进行PDO预处理的SQL,在输入SQL语句进行执行的时候,web服务器自己拼凑SQL的时候有可能会把危险的SQL语句拼凑进去。但如果进行了PDO预处理的SQL,会让MYSQL自己进行拼凑,就算夹带了危险的SQL语句,也不会进行处理只会当成参数传进去,而不是以拼接进SQL语句传进去,从而防止了SQL注入
网络层面:
通过WAF设备启用防SQL Inject注入策略(或类似防护系统)
云端防护(如阿里云盾)
如何发现sql注入漏洞
1.发现存在注入的地方,比如url的GET或者POST传参,亦或者是Http请求头部字段如Cookie注入
2.加入单双引号,如果出现报错,这证明该地方存在前端页面与数据库交互,可以试着发现有没有sql漏洞
常见的注入手法
注入的时候存在数字类型和字符类型,他俩的区别是有没有引号去闭合sql语句。
联合注入
通过union进行连接,使得前面的查询出现问题,而执行后面的语句。
?id=-1' union select 1,2,3 --+
报错注入
如果联合查询不能使用,首选报错注入。
1. group by 重复键冲
2. extractvalue() 函数
3. updatexml() 函数
布尔注入
所以,我们构造判断语句,根据页面是否回显证实猜想。一般用到的函数ascii() 、substr() 、length(),exists()、concat()等。
步骤:
1. 判断数据库类型
//判断是否是 Mysql数据库
http://127.0.0.1/sqli/Less-5/?id=1' and exists(select*from information_schema.tables) --+
//判断是否是 access数据库
http://127.0.0.1/sqli/Less-5/?id=1' and exists(select*from msysobjects) --+
//判断是否是 Sqlserver数据库
http://127.0.0.1/sqli/Less-5/?id=1' and exists(select*from sysobjects) --+
2. 判断当前数据库名
基于时间的盲注
一般配合if条件句使用,作为判断的依据。通过时间差,来进行判断。通过观察页面,既没有回显数据库内容,又没有报错信息也没有布尔类型状态,那么我们可以考虑用“绝招”–延时注入
?id=1' and if(ascii(substr(database(),1,1))= 115,sleep(5),0) --+
可以绕waf的payload
and(select*from(select+sleep(4))a/**/union/**/select+1)='
HTTP头注入
HTTP头部注入是通过HTTP协议头部字段值进行注入。http头注入常存在于以下地方
产生注入的条件:
- 能够对请求头消息进行修改
- 修改的请求头信息能够带入数据库进行查询
- 数据库没有对输入的请求信息做过滤
1. User-Agent注入
2. cookie注入
3. Referer注入
4. X-Forwarded-For 注入
宽字节注入
宽字节是指多个字节宽度的编码,GB2312、GBK、GB18030、BIG5、Shift_JIS等这些都是常说的宽字节,实际上只有两字节。转义函数在对这些编码进行转义时会将转义字符 ‘\’ 转为 %5c ,于是我们在他前面输入一个单字符编码与它组成一个新的多字符编码,使得原本的转义字符没有发生作用。
由于在数据库查询前使用了GBK多字节编码,即在汉字编码范围内使用两个字节会被编码为一个汉字(前一个ascii码要大于128,才到汉字的范围)。然后mysql服务器会对查询语句进行GBK编码,即下面所说的
我们在前面加上 %df’ ,转义函数会将%df’改成%df\’ , 而\ 就是%5c ,即最后变成了%df%5c’,而%df%5c在GBK中这两个字节对应着一个汉字 “運” ,就是说 \ 已经失去了作用,%df ’ ,被认为運’ ,成功消除了转义函数的影响。
’ %27
\ %5c
%df’ %df%5c’ =》 運’
只要低位的范围中含有0x5c的编码,就可以进行宽字符注入。
宽字节注入注入方法
- 黑盒
就是上面所述的,在注入点后面加%df,然后按照正常的注入流程开始注入即可。如果我们需要使用sqlmap进行检测注入的话也需要在注入点后面加%df然后再用sqlmap跑,否则是注入不出来的,如
sqlmap.py -u "http://localhost/sqli-labs-master/Less-32/?id=1%df%27"
- 白盒
查看mysql是否为GBK编码,且是否使用preg_replace()把单引号转换成’或自带函数addslashes()进行转义
宽字节注入修复
-
mysql_real_escape_string
-
设置参数,character_set_client=binary
-
使用utf-8编码
堆叠查询
堆叠查询也叫堆叠注入,在SQL中,分号(;)是用来表示一条sql语句的结束。
二阶注入
将未经过滤的数据存数据库,使得第二次提交请求时与第一次数据库中的字符发挥了作用形成了一条新的sql语句
Sql注入获取webshell
一. into outfile
利用条件
- 此方法利用的先决条件
web目录具有写权限,能够使用单引号
知道网站绝对路径(根目录,或则是根目录往下的目录都行)
secure_file_priv没有具体值(在mysql/my.ini中查看)
- secure_file_priv
secure_file_priv是用来限制load dumpfile、into outfile、load_file()函数在哪个目录下拥有上传和读取文件的权限。在mysql 5.6.34版本以后 secure_file_priv的值默认为NULL。如下关于secure_file_priv的配置介绍
secure_file_priv的值为null ,表示限制mysqld 不允许导入|导出
当secure_file_priv的值为/tmp/ ,表示限制mysqld 的导入|导出只能发生在/tmp/目录下
当secure_file_priv的值没有具体值时,表示不对mysqld 的导入|导出做限制
二. --os-shell
–os-shell就是使用udf提权获取WebShell。也是通过into oufile向服务器写入两个文件,一个可以直接执行系统命令,一个进行上传文件
此为sqlmap的一个命令,利用这条命令的先决条件:
- 要求为DBA,–is-dba(phpstudy搭建的一般为DBA)
- secure_file_priv没有具体值
- 知道网站的绝对路径
- GPC为off,php主动转义的功能关闭
Sql注入
原理
Sql注入是通过拼接sql查询语句,使Sql查询的时候发生歧义,导致攻击者可以查询数据库的全部信息
攻击对象是数据库。
存在威胁:
-
SQL注入漏洞对于数据安全的影响:
数据库信息泄漏:数据库中存放的用户的隐私信息的泄露。 网页篡改:通过操作数据库对特定网页进行篡改。 网站被挂马,传播恶意软件:修改数据库一些字段的值,嵌入网马链接,进行挂马攻击。 数据库被恶意操作:数据库服务器被攻击,数据库的系统管理员帐户被窜改。 服务器被远程控制,被安装后门:经由数据库服务器提供的操作系统支持,让黑客得以修改或控制操作系统。 破坏硬盘数据,瘫痪全系统。
sql注入防范
解决SQL注入问题的关键是对所有可能来自用户输入的数据进行严格的检查、对数据库配置使用最小权限原则。通常修复使用的方案有:
代码层面:
1.对输入进行严格的转义和过滤
2.使用参数化(Parameterized):目前有很多ORM框架会自动使用参数化解决注入问题,但其也提供了"拼接"的方式,所以使用时需要慎重!
3.PDO预处理 (Java、PHP防范推荐方法:)
没有进行PDO预处理的SQL,在输入SQL语句进行执行的时候,web服务器自己拼凑SQL的时候有可能会把危险的SQL语句拼凑进去。但如果进行了PDO预处理的SQL,会让MYSQL自己进行拼凑,就算夹带了危险的SQL语句,也不会进行处理只会当成参数传进去,而不是以拼接进SQL语句传进去,从而防止了SQL注入
网络层面:
通过WAF设备启用防SQL Inject注入策略(或类似防护系统)
云端防护(如阿里云盾)
如何发现sql注入漏洞
1.发现存在注入的地方,比如url的GET或者POST传参,亦或者是Http请求头部字段如Cookie注入
2.加入单双引号,如果出现报错,这证明该地方存在前端页面与数据库交互,可以试着发现有没有sql漏洞
常见的注入手法
注入的时候存在数字类型和字符类型,他俩的区别是有没有引号去闭合sql语句。
联合注入
通过union进行连接,使得前面的查询出现问题,而执行后面的语句。
?id=-1' union select 1,2,3 --+
报错注入
如果联合查询不能使用,首选报错注入。
1. group by 重复键冲
2. extractvalue() 函数
3. updatexml() 函数
布尔注入
所以,我们构造判断语句,根据页面是否回显证实猜想。一般用到的函数ascii() 、substr() 、length(),exists()、concat()等。
步骤:
1. 判断数据库类型
//判断是否是 Mysql数据库
http://127.0.0.1/sqli/Less-5/?id=1' and exists(select*from information_schema.tables) --+
//判断是否是 access数据库
http://127.0.0.1/sqli/Less-5/?id=1' and exists(select*from msysobjects) --+
//判断是否是 Sqlserver数据库
http://127.0.0.1/sqli/Less-5/?id=1' and exists(select*from sysobjects) --+
2. 判断当前数据库名
基于时间的盲注
一般配合if条件句使用,作为判断的依据。通过时间差,来进行判断。通过观察页面,既没有回显数据库内容,又没有报错信息也没有布尔类型状态,那么我们可以考虑用“绝招”–延时注入
?id=1' and if(ascii(substr(database(),1,1))= 115,sleep(5),0) --+
可以绕waf的payload
and(select*from(select+sleep(4))a/**/union/**/select+1)='
HTTP头注入
HTTP头部注入是通过HTTP协议头部字段值进行注入。http头注入常存在于以下地方
产生注入的条件:
- 能够对请求头消息进行修改
- 修改的请求头信息能够带入数据库进行查询
- 数据库没有对输入的请求信息做过滤
1. User-Agent注入
2. cookie注入
3. Referer注入
4. X-Forwarded-For 注入
宽字节注入
宽字节是指多个字节宽度的编码,GB2312、GBK、GB18030、BIG5、Shift_JIS等这些都是常说的宽字节,实际上只有两字节。转义函数在对这些编码进行转义时会将转义字符 ‘\’ 转为 %5c ,于是我们在他前面输入一个单字符编码与它组成一个新的多字符编码,使得原本的转义字符没有发生作用。
由于在数据库查询前使用了GBK多字节编码,即在汉字编码范围内使用两个字节会被编码为一个汉字(前一个ascii码要大于128,才到汉字的范围)。然后mysql服务器会对查询语句进行GBK编码,即下面所说的
我们在前面加上 %df’ ,转义函数会将%df’改成%df\’ , 而\ 就是%5c ,即最后变成了%df%5c’,而%df%5c在GBK中这两个字节对应着一个汉字 “運” ,就是说 \ 已经失去了作用,%df ’ ,被认为運’ ,成功消除了转义函数的影响。
’ %27
\ %5c
%df’ %df%5c’ =》 運’
只要低位的范围中含有0x5c的编码,就可以进行宽字符注入。
宽字节注入注入方法
- 黑盒
就是上面所述的,在注入点后面加%df,然后按照正常的注入流程开始注入即可。如果我们需要使用sqlmap进行检测注入的话也需要在注入点后面加%df然后再用sqlmap跑,否则是注入不出来的,如
sqlmap.py -u "http://localhost/sqli-labs-master/Less-32/?id=1%df%27"
- 白盒
查看mysql是否为GBK编码,且是否使用preg_replace()把单引号转换成’或自带函数addslashes()进行转义
宽字节注入修复
-
mysql_real_escape_string
-
设置参数,character_set_client=binary
-
使用utf-8编码
堆叠查询
堆叠查询也叫堆叠注入,在SQL中,分号(;)是用来表示一条sql语句的结束。
二阶注入
将未经过滤的数据存数据库,使得第二次提交请求时与第一次数据库中的字符发挥了作用形成了一条新的sql语句
Sql注入获取webshell
一. into outfile
利用条件
- 此方法利用的先决条件
web目录具有写权限,能够使用单引号
知道网站绝对路径(根目录,或则是根目录往下的目录都行)
secure_file_priv没有具体值(在mysql/my.ini中查看)
- secure_file_priv
secure_file_priv是用来限制load dumpfile、into outfile、load_file()函数在哪个目录下拥有上传和读取文件的权限。在mysql 5.6.34版本以后 secure_file_priv的值默认为NULL。如下关于secure_file_priv的配置介绍
secure_file_priv的值为null ,表示限制mysqld 不允许导入|导出
当secure_file_priv的值为/tmp/ ,表示限制mysqld 的导入|导出只能发生在/tmp/目录下
当secure_file_priv的值没有具体值时,表示不对mysqld 的导入|导出做限制
二. --os-shell
–os-shell就是使用udf提权获取WebShell。也是通过into oufile向服务器写入两个文件,一个可以直接执行系统命令,一个进行上传文件
此为sqlmap的一个命令,利用这条命令的先决条件:
- 要求为DBA,–is-dba(phpstudy搭建的一般为DBA)
- secure_file_priv没有具体值
- 知道网站的绝对路径
- GPC为off,php主动转义的功能关闭
本文为作者原创,转载请标明出处!