11import os
22import pytest
3+
34from aikido_zen .context import Context , current_context
45from aikido_zen .thread .thread_cache import ThreadCache , get_cache
56from aikido_zen .errors import AikidoSSRF
67from aikido_zen .background_process .comms import reset_comms
78import aikido_zen .sinks .socket
89import aikido_zen .sinks .http_client
910import requests
11+ import urllib3
1012
1113
1214@pytest .fixture (autouse = True )
@@ -19,7 +21,7 @@ def run_around_tests():
1921 get_cache ().reset ()
2022
2123
22- def set_context_and_lifecycle (url ):
24+ def set_context_and_lifecycle (url , host = None ):
2325 wsgi_request = {
2426 "REQUEST_METHOD" : "GET" ,
2527 "HTTP_HEADER_1" : "header 1 value" ,
@@ -33,6 +35,8 @@ def set_context_and_lifecycle(url):
3335 "CONTENT_TYPE" : "application/json" ,
3436 "REMOTE_ADDR" : "198.51.100.23" ,
3537 }
38+ if host is not None :
39+ wsgi_request ["HTTP_HOST" ] = host
3640 context = Context (
3741 req = wsgi_request ,
3842 body = {
@@ -49,6 +53,9 @@ def ssrf_check(monkeypatch, url):
4953 monkeypatch .setenv ("AIKIDO_BLOCK" , "1" )
5054 with pytest .raises (AikidoSSRF ):
5155 requests .get (url )
56+ with pytest .raises (AikidoSSRF ):
57+ http = urllib3 .PoolManager ()
58+ http .request ("GET" , url )
5259
5360
5461@pytest .mark .parametrize (
@@ -102,6 +109,18 @@ def test_no_raises_if_diff_url(monkeypatch):
102109 requests .get ("http://ssrf-redirects.testssandbox.com/ssrf-test-domain-twice" )
103110
104111
112+ def test_no_raises_if_diff_url_urllib3 (monkeypatch ):
113+ http = urllib3 .PoolManager ()
114+ set_context_and_lifecycle (
115+ "http://firewallssrfredirects-env-2.eba-7ifve22q.eu-north-1.elasticbeanstalk.com/ssrf-test-domain-twice"
116+ )
117+ monkeypatch .setenv ("AIKIDO_BLOCK" , "1" )
118+ with pytest .raises (urllib3 .exceptions .MaxRetryError ):
119+ http .request (
120+ "GET" , "http://ssrf-redirects.testssandbox.com/ssrf-test-domain-twice"
121+ )
122+
123+
105124def test_localhost_is_same_as_context (monkeypatch ):
106125 set_context_and_lifecycle ("http://localhost:8080" )
107126 monkeypatch .setenv ("AIKIDO_BLOCK" , "1" )
@@ -138,3 +157,31 @@ def test_different_capitalization_raises_ssrf(monkeypatch):
138157 requests .get ("http://Localhost:8081/" )
139158 with pytest .raises (AikidoSSRF ):
140159 requests .get ("http://localHost:8081/test" )
160+
161+
162+ def test_srrf_with_request_to_itself_urllib3 (monkeypatch ):
163+ http = urllib3 .PoolManager ()
164+ reset_comms ()
165+
166+ set_context_and_lifecycle ("http://localhost:5000/test/1" , host = "localhost:5000" )
167+ monkeypatch .setenv ("AIKIDO_BLOCK" , "1" )
168+ with pytest .raises (urllib3 .exceptions .MaxRetryError ):
169+ http .request ("GET" , "http://localhost:5000/test/1" )
170+
171+ # Now test with no port match
172+ set_context_and_lifecycle ("http://localhost:5000/test/2" , host = "localhost:4999" )
173+ monkeypatch .setenv ("AIKIDO_BLOCK" , "1" )
174+ with pytest .raises (AikidoSSRF ):
175+ http .request ("GET" , "http://localhost:5000/test/2" )
176+
177+ # Test with http app requesting to https
178+ set_context_and_lifecycle ("https://localhost/test/3" , host = "localhost:80" )
179+ monkeypatch .setenv ("AIKIDO_BLOCK" , "1" )
180+ with pytest .raises (urllib3 .exceptions .MaxRetryError ):
181+ http .request ("GET" , "https://localhost/test/3" )
182+
183+ # Test with https app requesting to http
184+ set_context_and_lifecycle ("http://localhost/test/4" , host = "localhost:443" )
185+ monkeypatch .setenv ("AIKIDO_BLOCK" , "1" )
186+ with pytest .raises (urllib3 .exceptions .MaxRetryError ):
187+ http .request ("GET" , "https://localhost/test/4" )
0 commit comments