so I was testing out a proxy provider and I found what I think is genuinely the funniest vulnerability. they tried to block requests to private ips but like... i think they didn't really think it through.
they blocked all the very obvious ones (due to multiple botnets abusing it, they didnt even know about it before, lmao):
127.0.0.110.0.0.0/8172.16.0.0/12192.168.0.0/16
i assumed they'd do dns resolution on their gateway server, check if the ip was private (or well, blacklisted in general), and then actually make the connection with the resolved ip but they did something way weirder
wha!? how are they doing it then?
i created my own authoritative dns server to see what was actually happening:
ns.rain.red-> my name serverpwn.rain.red-> pointing to ns.rain.red with a NS record
this meant I had complete control over dns responses for pwn.rain.red
now I sent a request through their proxy:
curl -x user:[email protected]:1337 pwn.rain.red
and immediately got:
[2026-06-02 00:00:22] 160.20.x.x ASN=266188 -> pwn.rain.red (A)
[2026-06-02 00:00:23] 162.158.224.75 ASN=13335 -> pwn.rain.red (AAAA)
[2026-06-02 00:00:23] 162.158.224.75 ASN=13335 -> pwn.rain.red (A)
multiple dns queries from different servers each request? one from the exit peer and then some from Cloudflare (AS13335)
the "validation"
when I made my dns server return a private IP address, they blocked it:
invalid destination after resolution: access to private IP address forbidden: 192.168.1.1
so they ARE validating. but.. what if the gateway and the actual peer see different dns answers?
abusing the amazing world of dns (and 192.168.1.1)
since I control the dns server, I could return different IPs depending on who asked. Cloudflare always queries from ASN 13335, so I could just say:
| who askin? :3c | what i return |
|---|---|
| Cloudflare (AS13335) | 1.3.3.7 |
| Everything else | 192.168.1.1 |
the gateway would see 1.3.3.7 and is like "yass, this is finee" but the actual peer would see 192.168.1.1 and tries to connect to that instead.
it...worked?
after deploying the new dns server, I repeated the curl command:
curl -x user:[email protected]:1337 pwn.rain.red
and... it didn't block it. instead I got back the ZTE router session timeout page. i actually connected to 192.168.1.1 despite them blocking it.
<html>
<head>
<title>400 Bad Request</title>
</head>
<body bgcolor="#FFFFFF" text="#000000" link="#2020ff" vlink="#4040cc">
<h2>400 Bad Request</h2>
Your request has bad syntax or is inherently impossible to satisfy.
<div style="display:none">
<ajax_response_xml_root>
<IF_ERRORSTR>SessionTimeout</IF_ERRORSTR>
<IF_ERRORPARAM>SUCC</IF_ERRORPARAM>
<IF_ERRORTYPE>SUCC</IF_ERRORTYPE>
</ajax_response_xml_root>
<span
>Padding so that MSIE deigns to show this error instead of its own
canned one.</span
>
<span
>Padding so that MSIE deigns to show this error instead of its own
canned one.</span
>
<span
>Padding so that MSIE deigns to show this error instead of its own
canned one.</span
>
<span
>Padding so that MSIE deigns to show this error instead of its own
canned one.</span
>
<span
>Padding so that MSIE deigns to show this error instead of its own
canned one.</span
>
<span
>Padding so that MSIE deigns to show this error instead of its own
canned one.</span
>
</div>
<hr />
</body>
</html>
why dis broken?
they tried to prevent ssrf but they did it wrong. the whole point is: the ip address you validate has to be the same one you actually connect to but they validated dns on one machine and resolved it again on a different machine. so if you control dns, you can make them see different answers.
how 2 actually fix
literally just do this:
- resolve the hostname once
- check if the ip is private / blacklisted
- give that validated IP to the peer
- make the peer connect to that exact IP, not resolve it again
for example:
Gateway
|
| Resolve once
| Validate
v
Peer
|
| Connect to the validated IP
v
Destination
now dns can't trick you because you're not resolving again.
thanks for reading this very shitty (and my first) blog