\( \newcommand{\N}{\mathbb{N}} \newcommand{\R}{\mathbb{R}} \newcommand{\C}{\mathbb{C}} \newcommand{\Q}{\mathbb{Q}} \newcommand{\Z}{\mathbb{Z}} \newcommand{\P}{\mathcal P} \newcommand{\B}{\mathcal B} \newcommand{\F}{\mathbb{F}} \newcommand{\E}{\mathcal E} \newcommand{\brac}[1]{\left(#1\right)} \newcommand{\abs}[1]{\left|#1\right|} \newcommand{\matrixx}[1]{\begin{bmatrix}#1\end {bmatrix}} \newcommand{\vmatrixx}[1]{\begin{vmatrix} #1\end{vmatrix}} \newcommand{\lims}{\mathop{\overline{\lim}}} \newcommand{\limi}{\mathop{\underline{\lim}}} \newcommand{\limn}{\lim_{n\to\infty}} \newcommand{\limsn}{\lims_{n\to\infty}} \newcommand{\limin}{\limi_{n\to\infty}} \newcommand{\nul}{\mathop{\mathrm{Nul}}} \newcommand{\col}{\mathop{\mathrm{Col}}} \newcommand{\rank}{\mathop{\mathrm{Rank}}} \newcommand{\dis}{\displaystyle} \newcommand{\spann}{\mathop{\mathrm{span}}} \newcommand{\range}{\mathop{\mathrm{range}}} \newcommand{\inner}[1]{\langle #1 \rangle} \newcommand{\innerr}[1]{\left\langle #1 \right \rangle} \newcommand{\ol}[1]{\overline{#1}} \newcommand{\toto}{\rightrightarrows} \newcommand{\upto}{\nearrow} \newcommand{\downto}{\searrow} \newcommand{\qed}{\quad \blacksquare} \newcommand{\tr}{\mathop{\mathrm{tr}}} \newcommand{\bm}{\boldsymbol} \newcommand{\cupp}{\bigcup} \newcommand{\capp}{\bigcap} \newcommand{\sqcupp}{\bigsqcup} \newcommand{\re}{\mathop{\mathrm{Re}}} \newcommand{\im}{\mathop{\mathrm{Im}}} \newcommand{\comma}{\text{,}} \newcommand{\foot}{\text{。}} \)

Sunday, June 14, 2020

SQL injection 及 prepared statement already exists

雖然知道 sql injection 成功後果很嚴重,但因為我很少打 raw sql,而我知道很多 library (sequelize, knex 等) 都會避免 sql injection 所以沒有特別去深究。

今天突然想起這個問題,而我也在為自己的手機 app 寫一個 backend 及想有一個自己 customize 的 query 結果。翻查 sequelize 的 doc 這件事沒有比寫 raw query 簡單,所以就開始自己寫 raw sequel。嘗試 sql inject 自己一下。發現如果沒有做任何預防操施真的很危險,甚至把我整個 database 毀掉:


所以開始學習寫 prepare statement:
PREPARE get_notes (int) AS
  SELECT v."id", v."word", v."pronounciation", v."explanation", p."dateTime", p."croppedScreenshot"
  FROM vocabs v
  INNER JOIN pages p 
  ON v."sqlitePageId"=p."sqliteId"
  WHERE p."sqliteNoteId"=$1;
EXECUTE get_notes(${sqliteNoteId});
在 postman get request 了一次,一切都很美好,再 get request 多一次,誒?
error: prepared statement "get_notes" already exists
搜尋了一下解決方法,最後只要每一次完成 EXECUTE 後把儲存好的 prepared statement 移除就好,整句變成:
PREPARE get_notes (int) AS
  SELECT v."id", v."word", v."pronounciation", v."explanation", p."dateTime", p."croppedScreenshot"
  FROM vocabs v
  INNER JOIN pages p 
  ON v."sqlitePageId"=p."sqliteId"
  WHERE p."sqliteNoteId"=$1;
EXECUTE get_notes(${sqliteNoteId});
DEALLOCATE get_notes;

No comments:

Post a Comment