1. 注入攻击类
1.1 SQL注入
漏洞描述 :
所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。
漏洞原因:
- 没有对输入的数据进行过滤。
- 没有对发送到数据库的数据进行转义。
检测条件:
- Web业务运行正常。
- 被测网站具有交互功能模块,涉及到参数提交等。
检测方法 :
莫慌建议在黑盒测试中,先猜测整个站点的技术架构,再根据功能合理猜测哪个页面哪个功能后台需要访问存储数据库(而不是缓存数据库),然后手工判断注入点的可能性,然后通过sqlmap进一步验证证实漏洞的存在。在实战中,大多数时候手工都比工具效果好,但是sql注入例外,sqlmap的效果要好于手工(难道我手工不行?)。下面简单介绍常见手工的测试方法,关于sql注入还是建议单独进行系统学习:
- 1、 数字型。测试方法:
shell
http://host/test.php?id=100 and 1=1 返回成功
http://host/test.php?id=100 and 1=2 返回失败
- 2、 字符型。测试方法:
shell
http://host/test.php?name=rainman ' and '1'='1 返回成功
http://host/test.php?name=rainman ' and '1'='2 返回失败
and ord(0x1)返回成功, and ord(0x0) 返回失败
- 3、 搜索型。搜索型注入:简单的判断搜索型注入漏洞存在不存在的办法是:
- 先搜索('),如果出错,说明90%存在这个漏洞。
- 然后搜索(%),如果正常返回,说明95%有洞了。
- 然后再搜索一个关键字,比如(aaa)吧,正常返回所有aaa相关的信息。
- 再搜索(aaa%'and 1=1 and '%'=')正常返回
- 再再(aaa%'and 1=2 and '%'=')返回错误,则99%概率存在sql注入
- 4、 绕过验证(常见的为管理登陆)也称万能密码,这种漏洞只可能存在一些老旧系统中,或者小白开发的系统中
- 用户名输入: ' or 1=1 or ' 密码:任意
- Admin' - -(或' or 1=1 or ' - -)(admin or 1=1 --) (MS SQL)(直接输入用户名,不进行密码验证)
- 用户名输入:admin 密码输入:' or '1'='1 也可以
- 用户名输入:admin' or 'a'='a 密码输入:任意
- 用户名输入:' or 1=1 - -
- 用户名输入:admin' or 1=1 - - 密码输入:任意
- 用户名输入:1'or'1'='1'or'1'='1 密码输入:任意
- 5、 不同的SQL服务器连结字符串的语法不同,比如MS SQL Server使用符号+来连结字符串,而Oracle使用符号||来连结:
shell
http://host/test.jsp?ProdName=Book' 返回错误
http://host/test.jsp?ProdName=B'+'ook 返回正常
http://host/test.jsp?ProdName=B'||'ook 返回正常说明有SQL注入
-
6、 如果应用程序已经过滤了'和+等特殊字符,我们仍然可以在输入时过把字符转换成URL编码(即字符ASCII码的16进制)来绕过检查。
-
7、Mysql如果=号被过滤,可以尝试用like替代,and可以用&&替代
-
8、最后提供一个SQL注入备忘录(https://www.cnblogs.com/yunen/p/10660226.html)是一个博主总结的。
修复方案:
- 解决方案很多,过滤,orm,安全sdk,安全狗等等,完整的修复方案可以很容易搜索到
1.2 XML注入
漏洞描述 :
可扩展标记语言 (Extensible Markup Language, XML) ,用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。 XML是标准通用标记语言 (SGML) 的子集,非常适合 Web 传输。XML 提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据。发现目前一些普遍使用xml的场景中都存在一种古老的XML实体注入漏洞,这可能导致较为严重的安全问题,使得攻击者可能可以任意访问服务器以及应用所在网络的任何资源;这种漏洞多见于老外开发的企业软件中,技术其实比较落后,国内大多数场景都被Json替代。倒是很少遇到。
检测条件:
-
- 被测网站使用可扩展标记语言。
检测方法:
- 通过手工篡改网站中xml实体中的头部,加入相关的读取文件或者是链接,或者是命令执行等。如file:///path/to/file.ext;http://url/file.ext(更多的语法,搜索xxe漏洞挖掘);看如下的例子:
python
<?xml version="1.0" encoding="utf-8"?> #XML声明部分
<!DOCTYPE nsfocus-sec [ #DTD部分
<!ELEMENT methodname ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<methodcall> #XML部分
<methodname>&xxe;</methodname>
</methodcall>
篡改以后,如果可读取file文件或者达到植入的命令效果,则说明存在该漏洞。
评价
这个漏洞现在在国内出现的概率不高,挖掘过程还比较复杂,不同的开发语言对xml语法支持的协议还不一样,xxe的payload主要在DTD部分进行漏洞挖掘,XML部分适合进行sql注入等漏洞挖掘(注意sql漏洞的本质)
修复方案:
- 在XML保存和展示前,对数据部分,单独做xml escape。
1.3 XPATH注入
漏洞描述 :
XPath注入攻击通过构建特殊的输入,这些输入往往是XPath语法中的一些组合,这些输入将作为参数传入Web应用程序,通过执行XPath查询而执行入侵者想要的操作。
漏洞等级:高危
检测条件:
- web服务器开启。
检测方法 :
XPath是W3C的一个标准。它最主要的目的是为了在XML1.0或XML1.1文档节点树中定位节点所设计。也是一种查询语言,描述了如何在XML文档中查找特定元素(包括属性、处理指令等)。
XPath在一些方面与SQL相似。但是在SQL语言中,一个用户的权限被限制在一个特定的数据库、表、列、行中。而XPath的不同之处在于,它可以用来引用XML文档的几乎任何部分而且不受访问控制限制。
下面以登录验证中的模块为例,说明XPath注入攻击的实现原理和检测方法,在Web应用程序的登录验证程序中,一般有用户名(username)和密码(password)两个参数,程序会通过用户所提交输入的用户名和密码来执行授权操作。若验证数据存放在XML文件中,其原理是通过查找user表中的用户名(username)和密码(password)的结果来进行授权访问,例存在user.xml文件如下:
xml
<users>
<user>
<firstname>Ben</firstname>
<lastname>Elmore</lastname>
<loginID>abc</loginID>
<password>test123</password>
</user>
<user>
<firstname>Shlomy</firstname>
<lastname>Gantz</lastname>
<loginID>xyz</loginID>
<password>123test</password>
</user>
则在XPath中其典型的查询语句如下:
//users/user[loginID/text()='xyz' and password/text()='123test']
发现和sql注入很类似。采用经典的sql注入语法,例如loginID = 'xyz' 和password = '123test',则该查询语句将返回true。但如果用户传入类似' or 1=1 or ''=' 的值,那么该查询语句也会得到true返回值,因为XPath查询语句最终会变成如下代码:
//users/user[loginID/text()='' or 1=1 or ''='' and password/text()='' or 1=1 or ''='']
这个字符串会在逻辑上使查询一直返回true并将一直允许攻击者访问系统。攻击者可以利用XPath在应用程序中动态地操作XML文档。攻击完成登录可以再通过XPath盲入技术获取最高权限帐号和其它重要文档信息。这个过程和sql注入高度类似。
Xpath 的基本语法
标识符
标识符 | 描述 |
---|---|
/ | 表示从根节点的子节点开始选取 |
// | 表示从当前节点的所有子节点以及子节点的分支中选取 |
. | 表示当前节点 |
... | 表示当前节点的父节点 |
@xxx | 表示所有名为xxx的属性 |
* | 表示任意元素节点 |
@* | 表示的是任意属性节点 |
node() | 表示的是任意节点 |
函数 | 描述 |
---|---|
name() | 返回节点的名称 |
root() | 返回根节点 |
contains(a,b) | 如果a包含b,则返回true |
starts-with(a,b) | 如果a以b开始,则返回true |
ends-with(a,b) | 如果a以b结束,则返回true |
substring(a,1,1) | 从a的第一个位置截取一个字符 |
string-length() | 计算字符串长度 |
count() | 返回节点的数量 |
max()/min() | 返回最大值/最小值 |
Xpath注入例子
xpath这种xml的存储方式,我是没有见过这种站,这种技术感觉真的不常见,我写的web反正是不用,所以也没有实际的经验,我截取其他的文章的经验来总结。原文传送门
先模拟一个xml的存储文件
xml
<?xml version="1.0" encoding="utf-8"?>
<root1>
<user>
<username name='user1'>user1</username>
<key>KEY:1</key>
</user>
<user>
<username name='user2'>user2</username>
<key>KEY:2</key>
</user>
<user>
<username name='user3'>user3hhh</username>
<key>KEY:3</key>
</user>
<user>
<username name='user4'>user4</username>
<key>KEY:4</key>
</user>
<user>
<username name='user5'>user5</username>
<key>KEY:5</key>
</user>
<hctfadmin>
<username name='hctf1'>hctf</username>
<key>flag:hctf{233333}</key>
</hctfadmin>
</root1>
使用Xpath查询user3节点信息:
xpath
//user/username[3]/text() #像不像操作系统文件路径?
返回的内容就是user3hhh。
Xpath注入根据回显类型的不同,分为有回显的'明注'和基于布尔型的盲注。
明注
主要利用连接符和//*打印所有节点信息。示例代码:
php
<?php
if(file_exists('test.xml')) {
$xml = simplexml_load_string(file_get_contents("test.xml"));
$user=$_GET['user'];
$query="user/username[@name='".$user."']";
echo $query;
echo "<br />";
$ans = $xml->xpath($query);
foreach($ans as $x => $x_value){
echo $x.": " . $x_value;
echo "<br />";
}
}
?>
payload:
plaintext
http://127.0.0.1/xpath.php?user=user1']|//*|//*['
最终效果user1被闭合后,//*打印所有节点信息。
盲注
思路与SQL盲注的基本相同,只是函数有所不同。示例代码:
php
<?php
if(file_exists('test.xml')) {
$xml = simplexml_load_string(file_get_contents("test.xml"));
$user=$_GET['user'];
$query="user/username[@name='".$user."']";
$ans = $xml->xpath($query);
if (sizeof($ans)>0){
echo 'yes';
}else{
echo 'wrong';
}
}
?>
payload:
plaintext
#查询节点数量
user=sss' or count(/*)=1 or '2'='1 True
user=sss' or count(/*)=2 or '2'='1 False
#查询节点名称
user=sss' or substring(name(/*),1,1)='r' or '2'='1 True
user=sss' or substring(name(/*),1,1)='k' or '2'='1 False
根据回显不同,根据Xpath的字符比较函数爆破字符即可,注入过程中用到的函数对比关系如下表:
Sql函数 | Xpath函数 |
---|---|
count() | count() |
length() | string-length() |
substr() | substring() |
concat() | concat() |
min() | min() |
max() | max() |
修复方案:
- 在服务端正式处理这批数据之前,对提交数据的合法性进行验证。
1.4 命令注入
漏洞描述 :
命令注入攻击是指由于Web应用程序对用户提交的数据过滤不严格,导致黑客可以通过构造特殊命令字符串的方式,将数据提交至Web应用程序中,并利用该方式执行外部程序或系统命令实施攻击。早年多见于php的web站中,java站也存在这种情况,最近几年很少见。体验可以在DVWA靶站进行测试。
上述漏洞的代码文件如下,可以看到cmd=shell_exec是造成漏洞的关键,后端如果存在拼接的第三方调用,则需要格外注意这种漏洞的发生,我曾经写过一个漏扫前端调用的第三方可执行程序就存在这种漏洞,o(╥﹏╥)o。
检测条件:
- 没有过滤
&&
或者||
这样的链接符。
检测方法 :
在数据传入数据库时使用链接符加入一些命令执行的函数,如system("ipconfig")
, exec("ipconfig")
。这里要根据web后端语言来定,如果是系统调用,这直接键入系统命令即可
*
常用符号
分号(;)
用于多条语句顺序执行时的分割。
管道符(|)
将一个命令的输出作为另一个命令的输入。
and(&&)
当第一个命令成功时执行第二个命令。
or(||)
当第一个命令失败时执行第二个命令。
反引号(`````)和 $()
用于执行命令,其中包含的字符串将被执行。
绕过方式总结
空格绕过
在过滤空格的系统中,使用以下方法绕过:
- 使用
${IFS}
代替空格。 - 使用重定向符
<
绕过。 - 在PHP环境下,使用
%09
替代空格。
黑名单绕过
- 拼接:使用Shell变量拼接受限关键词。
- Base64:使用反引号包含Base64解码后的命令。
- 引号:使用单引号和双引号的组合。
- 反斜杠:使用
\
作为命令的一部分。 $1
:使用变量引用。
读文件绕过
使用不同的命令来查看文件内容,例如more
,less
,head
,tac
,tail
,nl
,od
,vi
,vim
,sort
,uniq
,file -f
。
通配符绕过
使用/???
和其他通配符匹配命令和文件名,例如/???/?[a][t]
匹配/bin/cat
。
命令嵌套
使用反引号和$()
执行嵌套命令。
长度绕过- 使用
>>
绕过长度限制,逐步添加命令到文件中。 - 使用换行和
ls -t
执行命令,ls -t
可以逆序输出文件名。
修复方案:
- 在开发时尽量不要调用其他程序处理,少用命令执行的函数,对于php来说可在
disable_functions
中禁用。 - 在进入命令执行的函数或方法之前,对参数进行过滤。
- 如果是拼接的系统调用,注意过滤,尽量不使用拼接的方式
1.5 服务器模板注入(SSTI)
漏洞描述 :
模板引擎支持静态模板文件在运行的时候,用HTML页面中的实际值替换变量/占位符。攻击者可以把模板指令作为用户输入进行注入,这些指令可以在服务器上执行任意代码。漏洞常见于python的web框架和一些低代码平台的框架
检测条件:
- 服务器开启。
检测方法:
- 模版引擎的语法并不相同,因此没有固定的检测方法,普遍支持的模版是python的jinja2模版语法,测试的时候尝试在URL后面增加
{``{7+7}}
,看看会不会出现14,如果出现则代表漏洞了。 - 实际测试的时候如果确定服务器使用模版,则建议先进行谷歌搜索查看模版的语法和经典漏洞利用方式,然后逐一进行测试
修复方案:
- 尽可能的加载静态模板。
- 需要将动态数据传递给模板,不要直接在模板文件中执行。
- 使用第三方模版引擎要充分认知
1.6 CRLF注入
漏洞描述 :
HTTP响应头拆分漏洞(CRLF)"是一种新型的web攻击方案,它重新产生了很多安全漏洞包括:web缓存感染、用户信息涂改、窃取敏感用户页面、跨站脚本漏洞。这项攻击方案,包括其衍生的一系列技术产生,是由于web应用程序没有对用户的提交进行严格过滤,导致非法用户可以提交一些恶意字符,更具体来说,是对用户输入的CR 和LF字符没有进行严格的过滤。CRLF是"回车 + 换行"(\r\n)的简称。在HTTP协议中,HTTP Header与HTTP Body是用两个CRLF分隔的,浏览器就是根据这两个CRLF来取出HTTP 内容并显示出来。所以,一旦我们能够控制HTTP 消息头中的字符,注入一些恶意的换行,这样我们就能注入一些会话Cookie或者HTML代码,所以CRLF Injection又叫HTTP Response Splitting(HRS)。是应用程序没有正确的过滤用户提供的输入。远程攻击者可以利用这个漏洞影响或错误的显示Web内容服务,缓存或解释的方式,这可能帮助诱骗客户端用户,导致跨站脚本,缓存破坏或页面劫持等漏洞。
漏洞等级:中危
检测条件:
- Web业务运行正常。
- HTTP Header可进行篡改。
检测方法 :
1、 通过web扫描工具进行扫描检测,或者手工去判断,手工判断举例:一般网站会在HTTP头中用Location: http://baidu.com这种方式来进行302跳转,所以我们能控制的内容就是Location:后面的XXX某个网址,实际测试建议直接使用工具进行测试CRLFsuite。如下所示为抓包得到的相关数据包:
html
HTTP/1.1 302 Moved Temporarily
Date: Fri, 27 Jun 2014 17:52:17 GMT
Content-Type: text/html
Content-Length: 154
Connection: close
Location: http://www.sina.com.cn
然后手工输入链接:
http://www.sina.com.cn%0d%0aSet-cookie:JSPSESSID%3test%0d%0aLocation:%20example.com%0d%0aX-XSS-Protection:0后,再次抓包得到如下
html
HTTP/1.1 302 Moved Temporarily
Date: Fri, 27 Jun 2014 17:52:17 GMT
Content-Type: text/html
Content-Length: 154
Connection: close
Location: http://www.sina.com.cn
Set-cookie: JSPSESSID=test
Location: example.com
X-XSS-Protection:0
这个请求包中展示了两个可能的CRLF注入漏洞:
Set-Cookie注入:在GET请求行中插入了%0d%0a,然后在该注入点下一行添加了Set-Cookie:头部,将CRLF注入到了Set-Cookie的内容之前。
Location注入:类似地,在%0d%0a之后添加了Location:头部,将CRLF注入到了Location的内容之前。
修复方案:
- 建议过滤
\r
、\n
之类的换行符,避免输入的数据污染到其他HTTP头。
1.7 XFF注入
漏洞描述 :
XFF注入是SQL注入的一种,该注入原理是通过修改X-Forwarded-for头对带入系统的dns进行sql注入,从而得到网站的数据库内容。XFF除了SQL注入直接进行敏感数据泄露之外,还有绕过IP限制访问后台等功效
检测条件:
- Web业务运行正常。
- HTTP Header中存在X-Forwarded-for参数的调用。
检测方法:
- 手工修改或者添加X-Forwarded-for字段,验证sql漏洞,后面则接相关sql注入语法,绕过IP限制则把ip换成127.0.0.1等,这个检测手段并没有神奇之处,还有一个小技巧可以通过写多过X-Forwarded-for 尝试绕过一些设备,还可以直接使用xff插件手动嫌麻烦的话。
修复方案:
- 过滤http头中的X-Forwarded-for header中的内容,不允许其插入敏感字符。
4.8 链接或框架注入
漏洞描述 :
网站涉及到GET,POST等提交等,攻击者可注入含有恶意内容的frame或者iframe标记。
检测条件:
- 被测试网站具有交互功能模块,可以通过插入数据改变前端html页面内容的地方
检测方法 :
如果应用程序使用框架,检查主要浏览器窗口的HTML源代码,其中应包含框架标记(frameset)的代码。通过对网站中的get提交的url中的参数进行框架或者链接注入,注入到参数id后的效果:
http://www2.xxx.com/a/index.php?id=Fiframe><IFRAME+SRC%3D"http%3A%2F%2Fwww.baidu.com">:
得到的效果如下:
修复方案:
- 过滤出所有以下字符:
|
,&
,;
,$
,%
,@
,'
,"
,\'
,\"
,<
,>
,(
,)
,+
,CR
,LF
,,
,\
。
1.9 Json hijacking/Json劫持注入
漏洞描述 :
JSONP 全称是 JSON with Padding ,是基于 JSON 格式的为解决跨域请求资源而产生的解决方案。他实现的基本原理是利用了 HTML 里 元素标签,远程调用 JSON 文件来实现数据传递
JSON 劫持又为" JSON Hijacking ",最开始提出这个概念大概是在 2008 年国外有安全研究人员提到这个 JSONP 带来的风险。其实这个问题属于 CSRF( Cross-site request forgery 跨站请求伪造)攻击范畴。当某网站通过 JSONP 的方式来跨域(一般为子域)传递用户认证后的敏感信息时,攻击者可以构造恶意的 JSONP 调用页面,诱导被攻击者访问来达到截取用户敏感信息的目的。
检测条件:
- 已知Web网站应用交互采用json的数据交换或者传输。
检测方法 :
通过抓包分析应用里的数据交互,我们经常可以发现敏感信息泄露的情况发生。通常的方式包括,抓取应用的交互,查看里面敏感的数据,如果在传输的时候没有安全控制,就可以发现此类漏洞了。主要的危害是对于一些数据敏感的应用会造成较严重的攻击,对于数据不敏感甚至是对第三方公开的应用来说,这类问题基本不算是安全问题,通过在第三方域使用javascript hijacking的方式我们就可以窃取到敏感数据了。一般的exploit代码形式如下:
shell
<script> function wooyun_callback(a){ alert(a); } </script>
<script src="http://www.xxx.com/userdata.php?callback=wooyun_callback">
</script>
所以利用方式简单来说:
1.url中有callback这种类型的函数
2.网站需要跨域传输数据
3.类似CSRF的攻击手法,没错就是需要本地点击页面
比如构造一个本地的页面:
html
<html>
<head>
<meta charset="utf-8">
<title>JSONP劫持测试</title>
</head>
<body>
<script type="text/javascript">
function vulkey(data){alert(JSON.stringify(data));}
</script>
<script src="http://xx.xx.xx.xx:8000/csrf/jsonp.php?callback=vulkey"></script>
</body>
</html>
刚好用户浏览器访问这个站或者session没掉,在他电脑点击本地页面,则出现类似如下页面
修复方案 :
尽量避免跨域的数据传输,对于同域的数据传输使用xmlhttp的方式作为数据获取的方式,依赖于javascript在浏览器域里的安全性保护数据。如果是跨域的数据传输,必须要对敏感的数据获取做权限认证,具体的方式可以包括:
1、 referer的来源限制,利用前端referer的不可伪造性来保障请求数据的应用来源于可信的地方,此种方式力度较稀,完全依赖于referer,某些情况下(如存在xss)可能导致被绕过。
2、 token的加入,严格来说,这种利用javascript hijacking的方式获取数据是CSRF的一种,不过较之传统的CSRF不能获取数据只能提交而言,这种方式利用javascript可以获取一些敏感信息而已。如果我们能让攻击者对接口未知,就可以实现json hijacking的防御了。利用token对调用者的身份进行认证,这种方式对于调用者的身份会要求力度较细,但是一旦出现xss也可能导致前端Token的泄露,从而导致保护失效。
3、 对于同域的json使用情况下,可以在数据的输出头部加入while(1);的方式避免数据被script。