GHSA-XQ32-9G7Q-7297

Vulnerability from github – Published: 2026-05-21 20:42 – Updated: 2026-05-21 20:42
VLAI
Summary
FlaskBB: SSRF in get_image_info() via unrestricted avatar URL
Details

Summary

A Server-Side Request Forgery (SSRF) vulnerability in get_image_info() allows any authenticated user to force the server to send HTTP requests to arbitrary internal endpoints, including cloud metadata services (e.g., AWS 169.254.169.254). This is a blind SSRF with confirmed internal port scanning and internal API triggering capabilities. CVSS 6.5 Medium.

Details

In flaskbb/utils/helpers.py (line 571), the url parameter is passed directly to requests.get(url, stream=True) without any validation of scheme, host, or IP address.

python# flaskbb/utils/helpers.py:571
def get_image_info(url: str):
    r = requests.get(url, timeout=(3.05, 27), stream=True)

Attack chain:

POST /user/settings/user-details (avatar URL)
→ ValidateAvatarURL.validate()    # validators.py:103
→ check_image(avatar)             # helpers.py:628
→ get_image_info(url)             # helpers.py:571
→ requests.get(url)               # No domain/IP restriction
Entry points:

/user/settings/user-details (any authenticated user)
/admin/users/<id>/edit (admin only)

PoC

submit.zip

Log in to FlaskBB as any user Navigate to Settings → User Details Enter http://169.254.169.254/latest/meta-data/ as the avatar URL Submit the form The server sends a GET request to the internal metadata endpoint

Three exploitation channels confirmed:

Server-side request: Captured on mock metadata server Internal port scan: check_image() returns distinct errors (CONN_REFUSED, NO_CONTENT_LENGTH, TYPE_NOT_ALLOWED, SUCCESS) that map internal network topology Internal API triggering: Mock APIs on 127.0.0.1:9200 triggered via SSRF (deploy, shutdown, key dump endpoints)

Impact

Any authenticated user is impacted. Attackers can force the server to request internal services, cloud metadata endpoints, or private network resources. On cloud deployments (AWS/GCP/Azure), IAM credentials can be leaked. In production, any GET-triggered internal service is reachable: CI/CD webhooks, Elasticsearch, etcd, Consul, etc.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "flaskbb"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "last_affected": "2.2.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-46556"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-918"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-05-21T20:42:09Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "###Summary\nA Server-Side Request Forgery (SSRF) vulnerability in get_image_info() allows any authenticated user to force the server to send HTTP requests to arbitrary internal endpoints, including cloud metadata services (e.g., AWS 169.254.169.254). This is a blind SSRF with confirmed internal port scanning and internal API triggering capabilities. CVSS 6.5 Medium.\n\n###Details\nIn flaskbb/utils/helpers.py (line 571), the url parameter is passed directly to requests.get(url, stream=True) without any validation of scheme, host, or IP address.\n```\npython# flaskbb/utils/helpers.py:571\ndef get_image_info(url: str):\n    r = requests.get(url, timeout=(3.05, 27), stream=True)\n```\n\nAttack chain:\n\n```\nPOST /user/settings/user-details (avatar URL)\n\u2192 ValidateAvatarURL.validate()    # validators.py:103\n\u2192 check_image(avatar)             # helpers.py:628\n\u2192 get_image_info(url)             # helpers.py:571\n\u2192 requests.get(url)               # No domain/IP restriction\nEntry points:\n\n/user/settings/user-details (any authenticated user)\n/admin/users/\u003cid\u003e/edit (admin only)\n\n```\n\n###PoC\n[submit.zip](https://github.com/user-attachments/files/26301527/submit.zip)\n\nLog in to FlaskBB as any user\nNavigate to Settings \u2192 User Details\nEnter http://169.254.169.254/latest/meta-data/ as the avatar URL\nSubmit the form\nThe server sends a GET request to the internal metadata endpoint\n\nThree exploitation channels confirmed:\n\nServer-side request: Captured on mock metadata server\nInternal port scan: check_image() returns distinct errors (CONN_REFUSED, NO_CONTENT_LENGTH, TYPE_NOT_ALLOWED, SUCCESS) that map internal network topology\nInternal API triggering: Mock APIs on 127.0.0.1:9200 triggered via SSRF (deploy, shutdown, key dump endpoints)\n\n###Impact\nAny authenticated user is impacted. Attackers can force the server to request internal services, cloud metadata endpoints, or private network resources. On cloud deployments (AWS/GCP/Azure), IAM credentials can be leaked. In production, any GET-triggered internal service is reachable: CI/CD webhooks, Elasticsearch, etcd, Consul, etc.",
  "id": "GHSA-xq32-9g7q-7297",
  "modified": "2026-05-21T20:42:09Z",
  "published": "2026-05-21T20:42:09Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/flaskbb/flaskbb/security/advisories/GHSA-xq32-9g7q-7297"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/flaskbb/flaskbb"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "FlaskBB: SSRF in get_image_info() via unrestricted avatar URL"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…