Server side request forgery in different manner

Hello friends

This is going to be my first post so I welcome you and introduce myself briefly. You can call me apocalyptik. I work as security specialist in big, e-commerce company in Poland. I am also a software engineer so I can code :) For about a year I do bug hunting on hackerone and bugcrowd with main interest in web applications, mobile applications, api, code review. Summing it up — I know how to hack things, I know how to fix things and I’m going to share my stories and knowledge with you.

Today I’ll show you SSRF vector which is a little bit different than common ssrf. I once found it in bug bounty program and actually noticed it by accident.

The application
It was some kind of community based application where users could comment things. In comment it was possible to insert images both by uploading them to a server or from external location by url. External location is always interesting and almost always a place for security bugs differing only in severity. Do you want to know my approach of testing it? Anyway, this url was inserted into img tag.

The vector
I inserted a lot of links — to valid images, to other file types, broken links, links that returned different status codes. Everything was inserted into the DOM. Only valid jpg and png files were displayed, all others were “broken images”. It was expected. Also all files were requested client side so where is this SSRF? Well, I visited this same page after few minutes and…it was different. Valid images were served from CDN and “broken images” were turned into some default image placeholder. Crawler! I checked my access logs and indeed, images were requested from IP address that belonged to tested company.

The attack
If you have a potential SSRF vulnerability there are two addresses worth checking first. Loopback which means 127.0.0.1 and link local address which means 169.254.169.254 and is used as cloud metadata address with various endpoints. After few attempts I found out that address http://0 works and is reachable by crawler. 0 is 127.0.0.1 after some encoding :) There was one more thing to do. Crawler only accepted jpg and png files and endpoint that I was trying to read was just text. Bypass for file type was like this ?a=b.jpg which you should remember because it is useful. So the final payload…I can’t show you :P but was looking similar to: http://0/{endpoint}?a=b.jpg. Crawler read its content, uploaded into cdn and then I could download this file and check it. This way I was able to launch SSRF attack.

The fix
To fix this kind of bug http client should be configured in a safe way. What does this mean? Two things. Resolve domain into ip address and normalize that ip address in case you get http://0 in a request. Then check if address is from any private IP range. If yes then request should be rejected. Second thing is to disable redirects. Otherwise validation that was done in first step would be bypassed. Attacker can put his domain http://example.com which has public ip address and when crawler requests it, it will be redirected into ip from private range again. Validation won’t work after redirect.

SSRF itself is very wide attack vector. However this kind I found only once so far, it is rare case. So this is it for now. Hope you enjoy and see you soon.