Skip to content

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

Closed

Description

@alex

(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.

Activity

  1. JLLeitschuh commented on Oct 1, 2019

    @JLLeitschuh

    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? ❤️

  2. deniszh commented on Oct 1, 2019

    @deniszh
    Member
  3. JLLeitschuh commented on Oct 2, 2019

    @JLLeitschuh

    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.

  4. JLLeitschuh commented on Oct 2, 2019

    @JLLeitschuh

    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

  5. JLLeitschuh commented on Oct 3, 2019

    @JLLeitschuh

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

  6. deniszh commented on Oct 3, 2019

    @deniszh
    Member

    Hi @JLLeitschuh ,

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

  7. orangetw commented on Oct 4, 2019

    @orangetw

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

  8. deniszh commented on Oct 11, 2019

    @deniszh
    Member

    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 ?

  9. alex commented on Oct 11, 2019

    @alex
    Author

    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!

  10. DanCech commented on Oct 11, 2019

    @DanCech
    Member

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

  11. deniszh commented on Oct 11, 2019

    @deniszh
    Member

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

  12. carnil commented on Oct 12, 2019

    @carnil

    This issue was assigned CVE-2017-18638.

  13. JLLeitschuh commented on Oct 12, 2019

    @JLLeitschuh
  14. 1 remaining item

  15. deniszh commented on Oct 13, 2019

    @deniszh
    Member

    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

  16. added a commit that references this issue on Oct 13, 2019
  17. deniszh commented on Oct 24, 2019

    @deniszh
    Member

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

  18. stale commented on Apr 13, 2020

    @stale

    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.

  19. JLLeitschuh commented on Jun 1, 2020

    @JLLeitschuh

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

  20. alex commented on Jun 1, 2020

    @alex
    Author

    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.

  21. deniszh commented on Jun 1, 2020

    @deniszh
    Member
  22. JLLeitschuh commented on Jun 2, 2020

    @JLLeitschuh
  23. deniszh commented on Jun 2, 2020

    @deniszh
    Member

    @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" 🤷

  24. alex commented on Jun 2, 2020

    @alex
    Author
  25. deniszh commented on Jun 2, 2020

    @deniszh
    Member

    Ah, @ was not needed. 🤦
    Fixed.

  26. JLLeitschuh commented on Jun 2, 2020

    @JLLeitschuh

    Thanks @deniszh!

  27. orangetw commented on Jun 2, 2020

    @orangetw

    Thank you all and @JLLeitschuh ! :D

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions