You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CTF Node Express+SQLite站点SQL注入转义绕过求解

问题原因分析

  1. 语法错误导致注入未生效:你最初构造的OR WHERE是非法SQL语法,就算成功注入也只会触发数据库报错。另外getUser使用的是db.get()方法,只会返回查询结果的第一行,永远不会返回数组,你预期的数组类型报错不可能出现。
  2. 单引号转义导致闭合失败:登录生成JWT时,系统会自动将用户名中所有的'替换为两个',而SQLite中连续两个单引号默认是转义后的单引号字符,所以你直接在用户名中加的单引号会被当成普通字符串内容,无法闭合查询语句的前后单引号。

绕过方法

核心利用点:SQLite默认不将反斜杠\识别为转义字符,仅将连续的两个单引号识别为转义的单引号,结合JWT转义逻辑构造闭合语句:
你注册的用户名中如果包含\'结构,登录转义时单引号会被替换为两个单引号,最终得到\''结构:

  • 在SQLite解析时,\是普通字符,和前面的内容组成普通字符串
  • 后面两个连续的'中,第一个会闭合查询语句开头的单引号,第二个和后续拼接的空字符串''会被当成合法字符串拼接,不会影响后续注入语句的执行
  • 最后用--注释掉查询语句末尾多余的单引号即可

利用步骤

  1. 猜解users表字段数
    注册用户名格式为a\' ORDER BY {n}-- ,逐步递增n的值,直到访问首页触发500错误,即可得到users表的字段总数。
  2. 枚举数据库表名
    构造用户名({n}替换为实际字段数,缺少的字段用1/'test'等填充保证字段数匹配):
a\' AND 1=2 UNION SELECT name,1,1... FROM sqlite_master WHERE type='table'--

登录后访问首页,显示的用户名就是数据库中的表名,可通过增加OFFSET {x}参数遍历所有表,找到存储flag的表。
3. 读取flag内容
找到flag所在的表和对应字段后,构造用户名:

a\' AND 1=2 UNION SELECT flag,1,1... FROM {flag_table_name}--

登录后访问首页,欢迎信息中显示的用户名就是flag内容。


内容的提问来源于stack exchange,提问作者Fabio R.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 09:57:02