Bypassing SSRF protections in project imports using octal and other representations of 127.0.0.1
Title: SSRF vulnerability in gitlab.com via project import.
Weakness: Server-Side Request Forgery (SSRF)
Severity: Medium (5.4)
Link: https://hackerone.com/reports/215105
Date: 2017-03-21 14:12:33 +0000
By: @Edio
Details: Dear GitLab bug bounty team,
Summary
It appears as though the fix to !17286 can be easily bypassed. You have blocked the usage of http://127.0.0.1
, http://localhost/
, etc., but http://0177.1/
and http://0x7f.1/
, for instance, can still be used to scan internal ports.
Error importing repository http://0177.1:22/ into {username}/{project} - Cloning into bare repository '[REPOS PATH]/{username}/{project}.git'...
fatal: unable to access 'http://0177.1:22/': Recv failure: Connection reset by peer
Admittedly, you have restricted the use of certain ports, but I still believe this needs to be fixed.
Fix
Block decimal, octal and hex localhost notation.
Best regards, Ed
Timeline:
2017-03-21 16:54:00 +0000: @Edio (comment)
The issue lies in lib/gitlab/url_blocker.rb
:
def blocked_url?(url)
return false if url.nil?
blocked_ips = ["127.0.0.1", "::1", "0.0.0.0"]
blocked_ips.concat(Socket.ip_address_list.map(&:ip_address))
Link to source code: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/url_blocker.rb#L10-14
The reporter goes on to suggest a fix of adding these values to the IP block list. This will not work, however, as the destination hostname is resolved prior to being run through the blocklist.
What's happening is that some hosts/libraries resolve 0177.1
and 0x7f.1
to 127.0.0.1
while others return nil
. For hosts that resolve properly the attack is blocked, but for those that return nil
the request is allowed to proceed.
Blocking on hostnames that exist but resolve to nil
may be the obvious solution, however this would block project saves on hosts that have temporarily lost DNS. Another option would be to block imports from nil
only in the service and not for project saves. You could still save the project but the import would fail... as it would fail anyways if the hostname does not resolve.