Open hyperreality opened 4 weeks ago
I'm looking into this. Might be a complex fix.
I think I fixed it in my latest PR. It's now spitting out some vulns like this in Ninja:
scratchpad:
1.Analyzed start_campaign.py for LFI vulnerabilities. 2.Identified two critical vulnerabilities in update_template() and get_ssl() functions. 3.In update_template(), 'name' variable is user-controlled and used in mkdir() and open() without sanitization.
4.In get_ssl(), user input for certificate and key paths is used without validation. 5.Both vulnerabilities allow for directory traversal and unauthorized file access. 6.Traced input from campaign_name() to update_template(), confirming the vulnerability.
7.Examined input handling in get_ssl(), confirming lack of input validation. 8.Considered potential for chained attacks due to C2 server setup context. 9.Developed PoC exploits for both vulnerabilities. 10.Evaluated impact considering the C2 server
context, noting high severity.
----------------------------------------
analysis:
The start_campaign.py script contains two critical LFI vulnerabilities that could lead to unauthorized file access and potential remote code execution. The first vulnerability is in the update_template() function, where the 'name' variable, derived from
user input via campaign_name(), is used directly in mkdir() and open() calls without proper sanitization. This allows for directory traversal attacks. The second vulnerability is in the get_ssl() function, which accepts user input for SSL certificate and
key file paths without validation. Both vulnerabilities could allow an attacker to read sensitive files, write malicious files, or potentially execute arbitrary code. The script's role in setting up a C2 server amplifies the risk, as exploiting these
vulnerabilities could compromise the entire C2 infrastructure.
----------------------------------------
poc:
For update_template() vulnerability: 1. Input campaign name as '../../../etc/passwd' 2. This will attempt to create a directory named '../../../etc/passwd-campaign' and write to a file within it, potentially exposing sensitive information. For get_ssl()
vulnerability: 1. When prompted for SSL certificate path, input '/etc/passwd' 2. When prompted for private key path, input another sensitive file like '/etc/shadow' 3. This will attempt to read these files as SSL certificate and key, potentially exposing
their contents.
----------------------------------------
confidence_score:
8
----------------------------------------
vulnerability_types:
- LFI
It is still have some trouble getting stuff like cmds.COMMANDS that I have to look into.
Is this the AFO?
scratchpad:
1.Analyze upload_url route: The function accepts filename and file content from user input. 2.Examine file_path construction: filename is taken directly from user input without proper sanitization. 3.Check file writing process: decrypted file content is
written to the constructed file path. 4.Identify potential AFO vulnerability: Lack of proper input validation allows for directory traversal. 5.Construct PoC: Craft a POST request to upload_url with a malicious filename. 6.Verify vulnerability: Confirm
that the PoC can write files outside the intended directory. 7.Assess impact: potential to overwrite critical system files or create malicious files in sensitive locations. 8.Review confidence: High confidence due to clear code path from user input to
file writing.
----------------------------------------
analysis:
The upload function in webserver.py contains a critical Arbitrary File Overwrite (AFO) vulnerability. The function accepts a filename directly from user input without adequate sanitization, allowing for directory traversal attacks. While there's an
attempt to remove null bytes and split on backslashes, it's insufficient to prevent all forms of path traversal. An attacker can use '../' sequences to write files outside the intended directory. The file content is decrypted and written to the file path
constructed using the user-supplied filename. This vulnerability could allow an attacker to overwrite critical system files or create malicious files in sensitive locations. The lack of file extension validation further exacerbates the issue. The
vulnerability is highly exploitable due to the direct path from user input to file writing operations.
----------------------------------------
poc:
POST /upload_url HTTP/1.1
Host: target.com
Content-Type: multipart/form-data; boundary=---------------------------1234567890
---------------------------1234567890
Content-Disposition: form-data; name="file"
../../../etc/passwd
---------------------------1234567890
Content-Disposition: form-data; name="d"
---------------------------1234567890
Content-Disposition: form-data; name="resource"
malicious_id
---------------------------1234567890--
----------------------------------------
confidence_score:
9
----------------------------------------
vulnerability_types:
- AFO
----------------------------------------
It is still have some trouble getting stuff like cmds.COMMANDS that I have to look into.
Yeah I wonder if part of the confusion came from the questionable coding style of the Ninja repo where cmds
was used as a local variable, a module name, and a class name.
Is this the AFO?
The AFO is in the download_url
route, whereas upload_url
has a path traversal (because it's from the perspective of the C2 server rather than the client).
OK, I'll keep this open to remind me to look into Ninja's cmd.COMMANDS symbol lookup. Should be able to parse it although symbol parsing is by far the most complicated technical hurdle and getting it parse one edge case sometimes causes other edge case lookups to then fail. It's annoying.
I ran vulnhuntr on https://github.com/ahmedkhlief/Ninja to see its analysis of a known AFO there:
poetry run vulnhuntr -l claude -r /home/abc/Downloads/Ninja/ -v
I get the following traceback after some number of rounds of results:
The exception seems to be triggered by the first line of the
context_code
:A small reproduction:
The problem seems to be that the modules code in
symbol_finder.py
doesn't handle that style of import. If the first argument toextract()
is changed to the full module pathcore.cmd
then the code doesn't crash, but theif
statement doesn't trigger so Jedi doesn't goto the relevant source module file.