cors漏洞之123

cors漏洞相信大家已经很熟悉了,一般会用于配合csrf漏洞对用户进行攻击。这里就遇到的一些case,简单讲讲可能漏报误报的点,以及相应的修复方案。

cors漏洞要素

cors漏洞成功主要需要两个点,

在Html Response头部里面:

Access-Control-Allow-Origin: http://www.whitedomain.com
Access-Control-Allow-Origin: true or false

或者同时具备:

Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: false

Credentials这里是比较容易被忽略的,Credentials为false的话,数据包是不会带上传统的认证信息,你获取到的敏感内容也是相对有限的。

另外,cors漏洞也需要注意一点,你在构造测试点的时候,需要得到:

Origin: http://www.whitedomain.com

这里的域名是不能带上目录的,因为你实际上构造钓鱼页面的时候,是无法构造畸形Origin的。

为啥呢,因为你从页面发送给后端的请求,浏览器会主动去解析过滤,如果在这里去构造畸形的域名,他会只取到host部分,不会处理目录,然后拿去给后端解析。

比如说,浏览器会像下面这样处理去取host,由于需要配合通用后端过滤设置,需要www.whitedomain.com结尾的绕过尝试:

http://www.evil.com/whitedomain.com ===> 
www.evil.com
http://www.evil.com\.whitedomain.com ===> 
www.evil.com
http://www.evil.com#www.whitedomain.com ===> 
www.evil.com
http://www.evil.com?www.whitedomain.com ===> 
www.evil.com 

大概举几个例子就行,反正我这边暂时没找到可以绕过的尝试,后缀whitedomain.com,搞出来基本上取出来的真正host,也只能是whitedomain.com。

这是啥意思呢?意思是你去构造畸形的域名,浏览器可能就直接过滤拦截了。 传到后端的,基本就是你想要构造的恶意目的域名。这时候,后端做好相应的防跨域配置和服务器配置,基本就可以稳定拦截了。

修复方法

java后端配置举例(jetty版本):

public FilterRegistrationBean crossFilter()
{
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new org.eclipse.jetty.servlets.CrossOriginFilter() );
registration.addInitParameter(name: "allowOrigins", value: "*.whitedomain.com");
registration.addInitParameter(name: "allowMethods", value: "GET,POST,HEAD");
registration.addInitParameter(name: "allowHeaders", value: "X-Requested-With,Content-Type,Accept,Origin");
registration.addUrlPatterns("/*");
registration.setName("cross-origin");
return registration;
}

需要在pom.xml里配置的话:

<web-app>

    <filter>
        <filter-name>cross-origin</filter-name>
        <filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>cross-origin</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

</web-app>

当然,如果遇到特殊情况,需要在前端直接配置,nodejs配置举例:

// 判断origin是否在域名白名单列表中

function isOriginAllowed(origin, allowedOrigin) {

if (_.isArray(allowedOrigin)) {

for(let i = 0; i < allowedOrigin.length; i++) {

if(isOriginAllowed(origin, allowedOrigin[i])) {

return true;

}

}

return false;

} else if (_.isString(allowedOrigin)) {

return origin === allowedOrigin;

} else if (allowedOrigin instanceof RegExp) {

return allowedOrigin.test(origin);

} else {

return !!allowedOrigin;

}

}

const ALLOW_ORIGIN = [ // 域名白名单

'*.whitedomain.com',

];

app.post('/formdata', function (req, res, next) {

let reqOrigin = req.headers.origin; // request响应头的origin属性

// 判断请求是否在域名白名单内

if(isOriginAllowed(reqOrigin, ALLOW_ORIGIN)) {

// 设置CORS为请求的Origin值

res.header("Access-Control-Allow-Origin", reqOrigin);

//个人觉得下面一句根据业务而定,可设定可不设定。
res.header('Access-Control-Allow-Credentials', 'true');

// 你的业务代码逻辑代码 ...

// ...

} else {

res.send({ code: -2, msg: '非法请求' });

}

});