Coordinated Disclosure Timeline

Summary

Whoogle-search is vulnerable to Server-Side Request Forgery (SSRFs), Cross-Site Scripting (XSS) and a limited file write vulnerability.

Project

whoogle-search

Tested Version

0.8.3

Details

Issue 1: SSRF in the element endpoint (GHSL-2023-186)

The element method in app/routes.py does not validate the user-controlled src_type and element_url variables and passes them to the send method which sends a GET request on lines 339-343 in request.py, which leads to a server-side request forgery.

routes.py snippet from the element method

def element():
    element_url = src_url = request.args.get('url')

    #code cut out for readability
    src_type = request.args.get('type')

    try:
        file_data = g.user_request.send(base_url=src_url).content

request.py snippet from the send method

response = requests.get(
    (base_url or self.search_url) + query,
    proxies=self.proxies,
    headers=headers,
    cookies=cookies)

This issue was found with the CodeQL query Full server-side request forgery.

Impact

This issue allows for crafting GET requests to internal and external resources on behalf of the server. For example, this issue would allow for accessing resources on the internal network that the server has access to, even though these resources may not be accessible on the internet.

Resources

Issue 2: SSRF in the window endpoint (GHSL-2023-187)

In a similar way as with the element endpoint, the window endpoint does not sanitize user-supplied input from the location variable and passes it to the send method which sends a GET request on lines 339-343 in request.py, which leads to a server-side request forgery.

routes.py snippet from the window method

def window():
    target_url = request.args.get('location')

    #code cut out for readability

    get_body = g.user_request.send(base_url=target_url).text

request.py—snippet from the send method

response = requests.get(
    (base_url or self.search_url) + query,
    proxies=self.proxies,
    headers=headers,
    cookies=cookies)

This issue was found with the CodeQL query Full server-side request forgery.

Impact

This issue allows for crafting GET requests to internal and external resources on behalf of the server. For example, this issue would allow for accessing resources on the internal network that the server has access to, even though these resources may not be accessible on the internet.

Resources

Issue 3: XSS in the element endpoint (GHSL-2023-188)

This issue is tightly related to the vulnerability in issue 1: SSRF in the element endpoint (GHSL-2023-186).

The element method in app/routes.py does not validate the user-controlled src_type and element_url variables and passes them to the send method which sends a GET request on lines 339-343 in requests.py.

The returned contents of the URL are then passed to and reflected back to the user in the send_file function on line 484, together with the user-controlled src_type, which allows the attacker to control the HTTP response content type leading to a cross-site scripting vulnerability.

routes.py snippet from the element method

def element():
    element_url = src_url = request.args.get('url')

    #code cut out for readability
    src_type = request.args.get('type')

    try:
        file_data = g.user_request.send(base_url=src_url).content
        tmp_mem = io.BytesIO()
        tmp_mem.write(file_data)
        tmp_mem.seek(0)

        return send_file(tmp_mem, mimetype=src_type)
    except exceptions.RequestException:
        pass

Impact

An attacker could craft a special URL to point to a malicious website and send the link to a victim. The fact that the link would contain a trusted domain (e.g. from one of public Whoogle instances) could be used to trick the user into clicking the link.The malicious website could, for example, be a copy of a real website, meant to steal a person’s credentials to the website, or trick that person in another way.

Issue 4: Limited file write in the config endpoint (GHSL-2023-189)

This issue exists only if the configuration options in Whoogle are enabled.

The config function in app/routes.py does not validate the user-controlled name variable on line 447 and config_data variable on line 437. The name variable is insecurely concatenated in os.path.join, leading to path manipulation. The POST data from the config_data variable is saved with pickle.dump which leads to a limited file write. However, the data that is saved is earlier transformed into a dictionary and the url key value pair is added before the file is saved on the system. All in all, the issue allows us to save and overwrite files on the system that the application has permissions to, with a dictionary containing arbitrary data and the url key value, which is a limited file write.

This issue was found with the CodeQL query Uncontrolled data used in path expression.

Impact

This issue may lead to limited file write.

CVE

Credit

These issues were discovered and reported by GHSL team member @sylwia-budzynska (Sylwia Budzynska).

Contact

You can contact the GHSL team at securitylab@github.com, please include a reference to GHSL-2023-186, GHSL-2023-187, GHSL-2023-188, or GHSL-2023-189 in any communication regarding these issues.