发布于15小时前15小时 本文以一个经过授权的内网 CTF 场景为例,讨论如何把社会工程获得的低权限线索、密码学实现缺陷和权限边界验证串成一条可审计的测试链路。所有操作仅适用于自建靶场、CTF 环境或已取得书面授权的测试范围。一、背景:低权限账号并不等于低风险测试目标是一套内部工单系统,入口为 Unix 时间戳,后半部分长度固定且字符集单一。这个现象值得重点验证,因为重置令牌如果可预测,可能造成账户接管,并进一步暴露管理员权限边界。二、问题定位:先确认令牌是否具备不可预测性在授权环境中连续申请两次重置链接,记录申请时间、响应时间和令牌内容。不要直接对线上真实用户发起测试,也不要批量触发邮件。重点检查以下特征:令牌是否包含明文用户 ID、时间戳或自增序列。相同用户在短时间内申请时,令牌是否只改变少数字节。服务端是否只校验令牌格式,而没有绑定用户、过期时间和使用次数。令牌校验失败、重复使用和过期使用是否写入审计日志。如果令牌由时间戳加固定密钥哈希生成,应进一步在本地复现算法。测试时只使用自己创建的测试账号,并设置明确的停止条件。三、技术分析:错误的令牌设计方式靶场后端示例代码如下。这里的问题不是使用哈希本身,而是把可预测的时间戳作为主要输入,并使用全局固定密钥生成令牌;同时,服务端没有保存一次性随机值,导致令牌缺少服务端状态约束。def make_reset_token(uid, now): raw = f'{uid}:{now}:reset-key' return f'{now}-{md5(raw.encode()).hexdigest()}' def verify_reset_token(uid, token, now): ts, digest = token.split('-', 1) raw = f'{uid}:{ts}:reset-key' return md5(raw.encode()).hexdigest() == digest and int(now) - int(ts) < 3600该实现存在几个边界问题:reset-key 是全局固定值,一旦源码、配置或日志泄露,所有用户都受影响。令牌只与用户 ID 和时间相关,攻击者可以在小范围时间窗口内验证候选值。没有服务端保存令牌状态,成功使用后仍可能被重复使用。校验逻辑没有明确处理时钟回拨、异常时间戳和用户状态变化。四、授权验证步骤1. 采集自己的测试样本使用测试账号申请两次令牌,并将请求时间精确到秒。可以通过浏览器开发者工具或代理记录请求,但不要修改他人账号参数。curl -sk -X POST ' \ -H 'Content-Type: application/json' \ --data '{ 代码审计、调用链与关键函数定位示意 日志证据、时间线与事件还原示意
13小时前13小时 这类验证建议把“社工取证”和“令牌权限”分成两条证据链,避免把拿到的身份信息误当成可以重置账号的授权。 先固定授权边界:明确测试账号、目标租户、允许的社工话术、可收集字段和停止条件。不要接收真实密码、长期令牌或与范围无关的个人信息;尽量让被测人员操作专用测试账号,并保留工单、授权人、时间戳和操作记录。 验证身份与权限是否被混淆:分别准备普通用户 A、普通用户 B 和授权的管理测试账号。检查重置流程是否只依据邮箱、员工号、手机号等可通过社工获得的属性,而没有额外验证当前登录身份、MFA 或管理员权限。 验证令牌本身:重点看是否可预测、是否绑定账号和用途、是否过期、是否一次性、是否能跨租户使用,以及修改密码后旧令牌和旧会话是否立即失效。不要对真实用户做枚举或批量尝试,只在测试账号上做有限次数的重放和边界验证。 例如,可以在代理中记录两组专用账号的请求,检查令牌是否被绑定到请求中的用户标识: curl -i -X POST \ -H 'Content-Type: application/json' \ --data '{"token":"TEST_TOKEN_A","new_password":"Test-Only-Password-42"}' curl -i -X POST \ -H 'Content-Type: application/json' \ --data '{"token":"TEST_TOKEN_A","user":"test-user-b","new_password":"Test-Only-Password-42"}' 第二个请求在授权测试中应明确失败,而且不能因为响应状态码相同就认为安全;还要确认 B 的密码、会话和 MFA 状态没有发生变化。令牌的熵和生成方式也应由代码或配置核实,而不是只观察几条样本。实现上可采用 CSPRNG 生成至少 128 位随机值,数据库只保存其哈希,并设置短 TTL 和一次性消费: const crypto = require('crypto'); const rawToken = crypto.randomBytes(32).toString('base64url'); const tokenHash = crypto .createHash('sha256') .update(rawToken) .digest('hex'); // 保存 tokenHash、accountId、purpose、expiresAt、used=false // 校验时按哈希查找,并在同一事务中检查并标记 used 报告里最好把结果分成三层:社工能获得了什么、这些信息是否足以触发重置、令牌成功后实际能越过哪一道权限边界。这样能区分“信息暴露”“弱令牌设计”和“账号接管/跨账号重置”,也便于给出针对性的修复建议。修复后应覆盖日志脱敏、重置接口限速、统一错误响应、MFA 重置保护和跨租户隔离的回归测试。
创建帐户或登录后发表意见