Skip to content

graphite.composer.views.send_email vulnerable to SSRF #2008

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
alex opened this issue Jul 28, 2017 · 25 comments
Closed

graphite.composer.views.send_email vulnerable to SSRF #2008

alex opened this issue Jul 28, 2017 · 25 comments

Comments

@alex
Copy link

alex commented Jul 28, 2017

(I didn't discover this, it was publicly described here: http://blog.orange.tw/2017/07/how-i-chained-4-vulnerabilities-on.html)

https://github.com/graphite-project/graphite-web/blob/master/webapp/graphite/composer/views.py#L95-L102

Some sort of validation should be performed on the server component of the URL (possibly a whitelist in settings? I'm not overly familiar with the design of this module). Currently it's possible to use this view to make HTTP requests to services visible from the server.

@JLLeitschuh
Copy link

JLLeitschuh commented Oct 1, 2019

Hi,

So this vulnerability is still live, and this could 100% be abused to exploit the servers publicly exposing the Graphite server here:

https://www.shodan.io/search?query=Graphite+Browser

Here are the vulnerable lines:

def send_email(request):
try:
recipients = request.GET['to'].split(',')
url = request.GET['url']
proto, server, path, query, frag = urlsplit(url)
if query: path += '?' + query
conn = HTTPConnection(server)
conn.request('GET',path)
try: # Python 2.7+, use buffering of HTTP responses
resp = conn.getresponse(buffering=True)
except TypeError: # Python 2.6 and older
resp = conn.getresponse()
assert resp.status == 200, "Failed HTTP response %s %s" % (resp.status, resp.reason)
rawData = resp.read()
conn.close()
message = MIMEMultipart()
message['Subject'] = "Graphite Image"
message['To'] = ', '.join(recipients)
message['From'] = 'composer@%s' % gethostname()
text = MIMEText( "Image generated by the following graphite URL at %s\r\n\r\n%s" % (ctime(),url) )
image = MIMEImage( rawData )
image.add_header('Content-Disposition', 'attachment', filename="composer_" + strftime("%b%d_%I%M%p.png"))
message.attach(text)
message.attach(image)
s = SMTP(settings.SMTP_SERVER)
s.sendmail('composer@%s' % gethostname(),recipients,message.as_string())
s.quit()
return HttpResponse( "OK" )
except:
return HttpResponse( format_exc() )

A simple version of this exploit would be to chain this together with an SSRF attack against AWS to steal very valuable information and rack up a very sizable AWS bill. Given the code paths that I've seen, I know that this is most likely possible.

This should 100% have a CVE number assigned to it.


@orangetw: Can you please make sure you sweep up after yourself when you disclose vulnerability at large hacker conferences like Defcon? ❤️

@deniszh
Copy link
Member

deniszh commented Oct 1, 2019 via email

@JLLeitschuh
Copy link

One way to fix this issue would be to convert that endpoint from accepting HTTP GET requests to accepting only Cross Site Requset Forgery (CSRF) protected POST requests that require a user to be logged in.

Part of the problem with this though is that Graphina ships with the default credentials of root root. I'd advise also preventing the use of this endpoint (at minimum) if the user is detected to still have the default credentials.

@JLLeitschuh
Copy link

JLLeitschuh commented Oct 2, 2019

Also, I'd recommend limiting the outgoing request so that it can only be made against known safe/trusted endpoints.

Also, I stand by this needing a CVE.
If you want to use the GitHub process to get this, consider moving this discussion to a security advisory (and including all of us in it).

https://github.com/graphite-project/graphite-web/security/advisories

@JLLeitschuh
Copy link

@deniszh Can you also create another security advisory for something else I need to report.

@deniszh
Copy link
Member

deniszh commented Oct 3, 2019

Hi @JLLeitschuh ,

Sorry, I'm not really aware of Github security advisores and how it works. Created for both issues, added you to collaborators.

@orangetw
Copy link

orangetw commented Oct 4, 2019

Oops, I only reported to GitHub at that time. Sorry for that :(

@deniszh
Copy link
Member

deniszh commented Oct 11, 2019

OK, I checked this send_email function and didn't find any good use for it in the code. It was imported during initial import 12 years ago and also not documented in API docs.

I think we just need to remove it.

Opinions? @DanCech @iksaif @piotr1212 @cbowman0 ?

@alex
Copy link
Author

alex commented Oct 11, 2019

I haven't used graphite in several years, and just filed this since I care about the security and health of the internet. From my perspective, deleting code is a great solution to security issues!

@DanCech
Copy link
Member

DanCech commented Oct 11, 2019

+1 for just removing it. I don't see anywhere in the code that uses it.

@deniszh
Copy link
Member

deniszh commented Oct 11, 2019

Please also note that sending email from Dashboard is implemented in completely different commit e2a70d8 and not use send_email function at all.

@carnil
Copy link

carnil commented Oct 12, 2019

This issue was assigned CVE-2017-18638.

@JLLeitschuh
Copy link

@deniszh
Copy link
Member

deniszh commented Oct 13, 2019

Fix merged into master, and 0.9.x and 1.0.x branches. I'm preparing backport to current 1.1.x branch and going to release Graphite 1.1.6 shortly

@deniszh
Copy link
Member

deniszh commented Oct 24, 2019

OK, advisory is published - GHSA-vfj6-275q-4pvm

@stale
Copy link

stale bot commented Apr 13, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Apr 13, 2020
@stale stale bot closed this as completed Apr 20, 2020
@JLLeitschuh
Copy link

JLLeitschuh commented Jun 1, 2020

@deniszh Would you be so kind as to put credit on that report for @orangetw, @alex and me?

@alex
Copy link
Author

alex commented Jun 1, 2020

FWIW, I don't feel I need credit (though I don't object either :-)). I just took a report from one place and made sure it was filed where the maintainers would see it.

@deniszh
Copy link
Member

deniszh commented Jun 1, 2020 via email

@JLLeitschuh
Copy link

JLLeitschuh commented Jun 2, 2020

@deniszh
Copy link
Member

deniszh commented Jun 2, 2020

@JLLeitschuh : cool, but it's not allowing me to do so.
Screenshot 2020-06-02 at 16 35 29
Same for @orangetw or @alex - "isn't a Githuib member" 🤷

@alex
Copy link
Author

alex commented Jun 2, 2020 via email

@deniszh
Copy link
Member

deniszh commented Jun 2, 2020

Ah, @ was not needed. 🤦
Fixed.

@JLLeitschuh
Copy link

Thanks @deniszh!

@orangetw
Copy link

orangetw commented Jun 2, 2020

Thank you all and @JLLeitschuh ! :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants