• altzin
    开放登录
    ID open_login版本 1.0.8插件制作者 altzin免费423 行 / 17.8 KBHook / 路由 / 后台页
    让其他网站通过授权码快速登录本站账号。
    app/plugins/open_login/plugin.php
    开发日志已有 1 条

    个人独立维护项目。

    • altzin
      altzin
      版本 1.0.8 ef97994772b7 更新:旧格式迁移:已将插件代码转存到开发日志,主题正文改为基础介绍。release
    主楼
  • 质量报告

    插件质量报告

    插件:open_login

    Hook功能范围循环使用频率文件读写修改系统表读写系统表读写自己的表
    site.closed_allow站点关闭访问豁免检查否2----
    admin.tabs后台管理页标签栏否1----

    颜色说明:黄色表示有数据读写,红色表示 Hook 在系统循环中执行,浅蓝色表示有文件写入。“列表跳过”表示回调在列表路径会提前返回,“回调内”表示操作位于回调自身或其帮助函数的循环体内。“文件批处理”表示逐个处理用户一次提交的文件,属于必要操作,不标记修正。只有操作实际处于需要优化的循环路径时,才会标记“修正❗️”。

    数据字典

    plugin_open_login_codes

    字段类型可空默认值约束
    idid否-主键、自增
    codekey否-唯一
    user_iduint否--
    callback_urlstring否''-
    created_atuint否--
    expires_atuint否--
    used_atuint否0-
    #1
  • altzin

    开放登录 - 一个用于向其它网站授权你的论坛登录的插件
    接入流程
    将用户引导至授权页,用户在本站登录并确认授权后,会跳转到回调地址,并在 URL 中附带 code 参数
    回调方服务端请求兑换地址,将 [code] 替换为实际授权码,换取本站用户 ID
    成功响应:{"ok":1,"user_id":123};失败响应:{"ok":0,"message":"..."}
    授权码一次性有效,兑换成功后不可重复使用;未兑换的授权码不会过期
    Base64URL 与普通 Base64 的区别
    两者都是把回调地址转成一段文本,便于放进 URL;解码后都能还原成原始回调地址
    普通 Base64 结果里可能出现 +、/、=;纯英文 URL 不一定含有 /,但中文等非 ASCII 字符更容易编出 /
    Base64URL 会把 + 换成 -,把 / 换成 _,并去掉末尾的 = 填充,因此更适合直接放在路径里
    伪静态授权页请使用 Base64URL;未开启伪静态时,直接把完整回调地址做 URL 编码即可,不需要 Base64
    PHP 示例:$encoded = rtrim(strtr(base64_encode($callback), '+\/', '-_'), '=');
    原始回调地址https://example.com/回调?from=论坛
    普通 Base64(不要用于路径)aHR0cHM6Ly9leGFtcGxlLmNvbS/lm57osIM/ZnJvbT3orrrlnZs=其中 / 会被当成 URL 路径分隔符,例如上例里的 ...comS/lm57...
    Base64URL(伪静态路径请用这个)aHR0cHM6Ly9leGFtcGxlLmNvbS_lm57osIM_ZnJvbT3orrrlnZs不含 +、/、末尾 =,可安全放在 /auth/... 路径中
    伪静态已开启
    授权页:/auth/[callback],其中 [callback] 为回调地址的 Base64URL 编码(不是普通 Base64)
    兑换地址:/auth2/[code]
    示例:/auth/aHR0cHM6Ly9leGFtcGxlLmNvbS_lm57osIM_ZnJvbT3orrrlnZs
    伪静态未开启
    授权页:/index.php?a=auth&callback=%5Bcallback%5D,其中 [callback] 为完整回调地址(做 URL 编码,不需要 Base64)
    兑换地址:/index.php?a=auth2&code=%5Bcode%5D
    示例:/index.php?a=auth&callback=https%3A%2F%2Fexample.com%2F%E5%9B%9E%E8%B0%83%3Ffrom%3D%E8%AE%BA%E5%9D%9B

    #2
  • bbs1org

    @altzin 存在命令执行:exec 让ai修改下

    #3
  • 233

    我已下载 1.0.6 完整源码核查。这里的 $db->exec(...) 是 PDO::exec 执行固定 SQL,不是 PHP 的 exec() 系统命令函数;参数中也没有用户输入,所以这一处不存在命令执行。该唯一索引其实还是重复的:建表时 code ... UNIQUE 已创建唯一约束,可以直接删除 open_login_ensure_code_unique_index(),但这是代码简化,不是 RCE 修复。

    不过插件当前确实有更严重的协议安全问题,建议先暂停使用:

    1. 任意网站都能传入 callback,没有后台注册客户端或回调白名单,授权页确认后会直接跳转任意 http/https 地址,属于开放重定向/钓鱼入口;
    2. /auth2/[code] 不验证客户端身份,任何拿到 code 的人都能兑换 UID;
    3. 文档和代码明确让未兑换授权码永久不过期,泄漏后的利用窗口无限;
    4. 仅返回 user_id,没有 state、PKCE、client_id、redirect URI 绑定或签名身份令牌,不能安全证明兑换方就是最初发起方;
    5. 回调允许明文 HTTP,code 可能在传输、日志和 Referer 中泄漏。

    最低修复方案应是:后台注册应用并完整匹配 HTTPS redirect URI;授权码只存哈希、5 分钟过期,并绑定 client_id + redirect_uri + S256 PKCE;授权请求必须有 state;兑换端验证 client_id、redirect_uri、code_verifier,使用原子条件更新消费 code。若目标是标准第三方登录,建议直接采用 Authorization Code + PKCE/OIDC,而不是继续扩展当前 UID 兑换协议。

    因此结论:没有命令执行,但当前版本不应作为安全的开放登录协议上线。

    #4
  • altzin

    第一,code是一次性且只能拿到用户id的。仅仅用于向网站证明用户是用户。
    如果被传输过程截获,说明没有用HTTPS,这不是我的问题。
    如果事后从其他地方截获,例如浏览器历史记录,因为一次性性质,不能再用。
    如果钓鱼网站填写特殊地址,只能钓到用户ID,没有用处。
    不需要证明兑换方就是发起方,因为我不提供任何敏感信息,而且如果兑换方不是发起方,发起方最终会发现不能兑换。
    使用的时间窗口不是无限,而是发起方兑换完成那一点点时间。

    #8
  • altzin

    替换了exec。旧表可以停用再启用插件迁移

    #5
  • altzin

    这个code只能说泄露不泄露或者被其它人兑换了都没什么关系,因为它只提供兑换用户id,是给网站确认你提供的不是伪造的凭据用的

    #6
  • altzin

    修复了回调url在本来就有get参数时会错误传参的问题

    #7
  • 350

    🔍 插件审查报告(对照《AI 开发规则》与开发者文档)

    🔒 安全问题

    回调地址无主机白名单:plugin.php:95-118 仅校验 http/https 与 host 存在,未限制目标主机,273 行 go() 会把用户重定向到任意(含私网/环回)主机并附带授权码,存在开放重定向风险。建议增加可选主机白名单配置,至少拦截内网地址。授权码为 128 位随机值,无 SQL 注入、XSS,兑换信息未泄露敏感数据。

    ⚡ 性能问题

    未发现明显问题。无红区钩子 DB 读,无循环逐条查询。

    🐛 功能/规范缺陷

    1. 授权码并发兑换竞态(中):plugin.php:224-234 事务内 SELECT used_at 后 UPDATE ... WHERE used_at=0,但返回值无条件用 SELECT 出的 user_id;MySQL 下并发两请求都能读到 used_at=0 并各自返回 user_id。应按 UPDATE 影响行数判断是否兑换成功。
    2. 未兑换码不清理(低):plugin.php:209 expires_at 固定写 0,309 行 cleanup 仅删 used_at>0 的记录,未兑换码永不过期导致表无限增长。建议给授权码设有效期并一并清理。
    3. 兑换接口用 GET 改状态(低):plugin.php:285-296 auth2 用 GET 消费授权码(UPDATE used_at),预加载/重试/日志泄露可能提前消费。建议改 POST(require_post)。

    ✅ 修复优先级

    ① 回调主机白名单(中);② 并发兑换竞态(中);③ 授权码有效期与清理、POST 兑换(低)。

    #9
  • 399

    🔍 插件审查报告(AI 自动审查,对照《AI 开发规则》与开发者文档;本插件未被 8/18 楼上 350 的报告覆盖,属独立首次审查)

    插件:开放登录(open_login)v1.0.8

    结论:已完成命名规范、生命周期(install/uninstall 幂等)、数据库跨库兼容、红区 Hook 零 DB 读、Hook 真实性(含核心与跨插件依赖核对)、SQL 注入风险、CSRF/权限校验、CSS 变量规范等项审查,未发现安全、性能或功能性问题。

    #10
  • altzin

    旧格式迁移:已将插件代码转存到开发日志,主题正文改为基础介绍。

    #11

发表回复

登录后回复