SQL Injection ๊ณต๊ฒฉ๊ณผ ๋Œ€์‘

2023. 2. 11. 15:47ใ†Database/DB ์Šคํ„ฐ๋””

์ด์ „์— NodeJS Express์™€ MySql2๋ฅผ ์—ฐ๋™ํ•˜์—ฌ ํ† ์ด ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•œ ์ ์ด ์žˆ๋‹ค. 

๊ทธ๋•Œ ์‚ฌ์šฉ์ž์˜ ์ด๋ฉ”์ผ์„ ๊ฐ€์ง€๊ณ  ํ•ด๋‹น ์ด๋ฉ”์ผ์„ ๊ฐ–๋Š” ๊ณ„์ •์ด ์กด์žฌํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•œ ์ผ์ด ์žˆ๋Š”๋ฐ, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌ์„ฑํ–ˆ๋‹ค.

๋‹น์‹œ ์„œ๋กœ ์ฝ”๋“œ ๋ฆฌ๋ทฐ๋ฅผ ํ•ด์ฃผ๋˜ ๊ทธ๋ฃน์ด ์žˆ์—ˆ๋Š”๋ฐ, ํ•œ๋ถ„๊ป˜์„œ ์œ„ ์ฝ”๋“œ๋ฅผ ๋ณด์‹œ๊ณ ๋Š” "SQL Injection ๊ณต๊ฒฉ์— ์ทจ์•ฝํ•ด ๋ณด์ธ๋‹ค"๋ผ๊ณ  ํ”ผ๋“œ๋ฐฑ์„ ํ•ด์ฃผ์‹  ๊ธฐ์–ต์ด ์žˆ๋‹ค. 

์ง€๊ธˆ์ด์•ผ ์ €๋Ÿฐ ์‹์œผ๋กœ ์ฝ”๋“œ๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๊ฒƒ์ด ์œ„ํ—˜ํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ ์žˆ์ง€๋งŒ ๋‹น์‹œ์—๋Š” ์•„๋Š” ๊ฒƒ์ด ๋ณ„๋กœ ์—†์—ˆ๊ธฐ ๋•Œ๋ฌธ์— SQL Injection์„ ๋”ฐ๋กœ ๊ณต๋ถ€ํ–ˆ๋˜ ๊ธฐ์–ต์ด ์žˆ๋‹ค.

 

 

SQL Injection ์ด๋ž€?

SQL Injection์€ ํ•ด์ปค๊ฐ€ ํ”„๋กœ๊ทธ๋ž˜๋จธ์˜ ์˜๋„์— ๋ฒ—์–ด๋‚œ ๋ฐฉ๋ฒ•์„ ํ†ตํ•ด SQL๋ฌธ์„ ์žฌ๊ตฌ์„ฑ, DB์— ์งˆ์˜ํ•˜์—ฌ ์‚ฌ์šฉ์ž์˜ ๋น„๋ฐ€๋ฒˆํ˜ธ๋‚˜ ์‹ ์šฉ์นด๋“œ ์ •๋ณด ๋“ฑ ๋ฏผ๊ฐํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฝ‘์•„๋‚ด๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค. 

์œ„์˜ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด SQL๋ฌธ์ด ์ž‘์„ฑ๋˜์–ด ์žˆ๋‹ค.

SELECT * FROM `account` WHERE email='${email}'

์ด ๋•Œ ๊ณต๊ฒฉ์ž๊ฐ€ ์ด๋ฉ”์ผ์ด ์ž…๋ ฅ๋˜์–ด์•ผ ํ•˜๋Š” ๋ž€์— ๋‹ค์Œ์˜ ๋ฌธ์ž์—ด์„ ์ž…๋ ฅํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ?

email = "' OR 1=1 --"

๊ฒฐ๋ก ์ ์œผ๋กœ ๋‹ค์Œ์˜ SQL๋ฌธ์ด ์™„์„ฑ๋œ๋‹ค.

SELECT * FROM `account` WHERE email = '' OR 1 = 1 -- '

๊ณต๊ฒฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ๋ฌธ์ž์—ด ๋‚ด ๊ตฌ๋ฌธ์„ ๋ถ„์„ํ•ด ๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  1. ์‹œ์ž‘ ๋ถ€๋ถ„์˜ ' : ์ด๋ฏธ ์กด์žฌํ•˜๋Š” email ์กฐ๊ฑด์— ๋นˆ๋ฌธ์ž์—ด์„ ์ œ๊ณตํ•˜์—ฌ email ์กฐ๊ฑด์ ˆ์„ ์ข…๋ฃŒ์‹œํ‚ด.
  2. OR : OR์„ ํ†ตํ•ด ์ด์ „์— ์ž‘์„ฑ๋œ ์กฐ๊ฑด๋ฌธ์˜ ์ฐธ, ๊ฑฐ์ง“๊ณผ ๊ด€๊ณ„์—†์ด ์ดํ›„ ์กฐ๊ฑด์„ ํ†ตํ•ด ์ฟผ๋ฆฌ๋ฅผ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ฆ.
  3. 1 = 1 : ํ•ญ์ƒ ์ฐธ์ด ๋˜๋Š” ์กฐ๊ฑด์„ OR๊ณผ ํ•จ๊ป˜ ์ถ”๊ฐ€ํ•˜์—ฌ ์ „์ฒด WHERE ์ ˆ์ด ์ฐธ์ด ๋˜๋„๋ก ๋งŒ๋“ฆ.
  4. -- : ์ดํ›„ ๋‚˜์˜ค๋Š” SQL ๊ตฌ๋ฌธ์„ ๋ชจ๋‘ ์ฃผ์„์ฒ˜๋ฆฌํ•จ. ์ฆ‰, ๋’ค์— ์–ด๋–ค ์ ˆ์ด ๊ธฐ์ˆ ๋˜์–ด ์žˆ๋”๋ผ๋„ ๋‹จ์ˆœ ์ฃผ์„์œผ๋กœ ๊ฐ„์ฃผ๋˜์–ด ์ž‘๋™ํ•˜์ง€ ์•Š๋„๋ก ๋งŒ๋“ฆ.

์ฆ‰, ์ด๋ฉ”์ผ ๋ž€์— ์œ„ ๋ฌธ์ž์—ด์„ ์ž…๋ ฅํ•˜์—ฌ ๊ณต๊ฒฉ์ž๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ account ํ…Œ์ด๋ธ” ๋‚ด ๋ชจ๋“  ์‚ฌ์šฉ์ž์˜ ์ •๋ณด๋ฅผ ์งˆ์˜ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

์ด๋Š” ๋ช…๋ฐฑํžˆ ํ”„๋กœ๊ทธ๋ž˜๋จธ์˜ ์˜๋„์™€๋Š” ๋‹ค๋ฅด๋ฉฐ ์„œ๋น„์Šค์— ํฐ ์œ„ํ˜‘์ด ๋  ์ˆ˜ ์žˆ๋‹ค.

 

 

SQL Injection ๊ณต๊ฒฉ์„ ๋ฐฉ์ง€ํ•˜๋Š” ๋ฐฉ๋ฒ•

1. Prepared Statement ์‚ฌ์šฉ

Prepared Statement๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์ดํ•ด๋ฅผ ๋•๊ธฐ ์œ„ํ•ด, DBMS์˜ ์ฟผ๋ฆฌ ์ž‘๋™ ๊ณผ์ •๊ณผ ํŒŒ์‹ฑ์— ๋Œ€ํ•ด ์•Œ์•„๋‘˜ ํ•„์š”๊ฐ€ ์žˆ๋‹ค.

DBMS ์ฟผ๋ฆฌ ์ž‘๋™ ๊ณผ์ •๊ณผ ํŒŒ์‹ฑ

DBMS์—์„œ ์ฟผ๋ฆฌ๊ฐ€ ์ž‘๋™๋˜๋Š” ๊ณผ์ •์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  1. ์ฟผ๋ฆฌ ์ž…๋ ฅ : ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ž‘์„ฑํ•œ SQL์„ DBMS์— ์ „์†ก
  2. ํŒŒ์‹ฑ (Parsing) : DBMS๋Š” ์ž…๋ ฅ๋ฐ›์€ ์ฟผ๋ฆฌ์— ๋Œ€ํ•œ ๊ตฌ๋ฌธ ๋ถ„์„์„ ์ง„ํ–‰ํ•˜๊ณ , ๊ตฌ๋ฌธ ํŠธ๋ฆฌ๋ฅผ ์ƒ์„ฑ
  3. ์ตœ์ ํ™” (Optimization): DBMS๊ฐ€ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰์‹œํ‚ฌ ์ตœ์  ์‹คํ–‰ ๊ณ„ํš์„ ๊ฒฐ์ •
  4. ์‹คํ–‰ (Execution) : ์ตœ์  ์‹คํ–‰ ๊ณ„ํš์„ ํ†ตํ•ด DB์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์ƒ‰
  5. ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜ (Fetching) : ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋ฅผ ํด๋ผ์ด์–ธํŠธ์— ์ „๋‹ฌ

์ด ์ค‘ ํŒŒ์‹ฑ ๊ณผ์ •์€ ๋˜๋‹ค์‹œ ๋‹ค์Œ์œผ๋กœ ๋‚˜๋‰œ๋‹ค.

  1. ๋ฌธ๋ฒ• ๊ฒ€์‚ฌ : ์ฟผ๋ฆฌ์˜ ๊ฐ ๊ตฌ๋ฌธ(ex. SELECT, WHERE, FROM ๋“ฑ)์ด ์œ ํšจํ•˜๊ฒŒ ์ž‘์„ฑ๋˜์—ˆ๋Š”์ง€ ๊ฒ€์‚ฌ.
  2. ๊ตฌ๋ฌธ ๋ถ„์„ : ์ฟผ๋ฆฌ์—์„œ ๊ฐ ๊ตฌ๋ฌธ์˜ ์˜๋ฏธ๋ฅผ ํŒŒ์•…ํ•˜๊ณ  ๊ตฌ๋ฌธ ํŠธ๋ฆฌ๋ฅผ ์ƒ์„ฑ. ์ด๋•Œ ๊ตฌ๋ฌธ ํŠธ๋ฆฌ๋ž€ ์ฟผ๋ฆฌ์˜ ๊ฐ ๊ตฌ๋ฌธ์˜ ์ƒํ˜ธ ๊ด€๊ณ„๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๊ตฌ์กฐ.
  3. ๋ถ„์„ ๊ฒฐ๊ณผ ์ €์žฅ : ํŒŒ์‹ฑ๋œ ๊ตฌ๋ฌธ ํŠธ๋ฆฌ๋ฅผ DBMS์— ์ €์žฅ. ํ–ฅํ›„ ์ด๋Š” ์ตœ์ ํ™”์™€ ์‹คํ–‰์— ์ด์šฉ๋จ.

ํŒŒ์‹ฑ์—๋Š” ํ•˜๋“œ ํŒŒ์‹ฑ๊ณผ ์†Œํ”„ํŠธ ํŒŒ์‹ฑ์ด ์กด์žฌํ•˜๋Š”๋ฐ,

ํ•˜๋“œ ํŒŒ์‹ฑ์€ ์œ„์—์„œ ์„ค๋ช…ํ•œ ๋ชจ๋“  ํŒŒ์‹ฑ ๊ณผ์ •์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค. ๋ณดํ†ต SQL ์ฟผ๋ฆฌ๋ฅผ ์ฒ˜์Œ ์‹คํ–‰ํ•  ๋•Œ ์ด์šฉ๋œ๋‹ค.  

๋ฐ˜๋ฉด ์†Œํ”„ํŠธ ํŒŒ์‹ฑ์€ ์ด๋ฏธ DBMS์— ์กด์žฌํ•˜๋Š” ๊ตฌ๋ฌธ ํŠธ๋ฆฌ๋ฅผ ์ด์šฉํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ, ์ƒˆ๋กœ ๋“ค์–ด์˜จ ํŒŒ๋ผ๋ฏธํ„ฐ ์ •๋„๋งŒ์„ ์ฒจ๊ฐ€ํ•˜๋Š” ๊ณผ์ •์„ ๊ฑฐ์นœ๋‹ค.

Prepared Statement

Prepared Statement๋Š” ์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ํŒŒ์‹ฑ๋“ค ์ค‘ ์†Œํ”„ํŠธ ํŒŒ์‹ฑ์„ ์ด์šฉํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.

๋ฌผ๋ก  ํ•˜๋“œ ํŒŒ์‹ฑ์„ ์•„์˜ˆ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋ฉฐ, Prepared Statement์˜ ์˜๋ฏธ๋Œ€๋กœ ์‹ค์ œ ์ฟผ๋ฆฌ๊ฐ€ ์ž…๋ ฅ๋˜๊ธฐ ์ „์— ์ด๋ฏธ ํ•˜๋“œ ํŒŒ์‹ฑ์ด ์™„๋ฃŒ๋˜์–ด ๊ตฌ๋ฌธ ๋ถ„์„์„ ์™„๋ฃŒํ•ด ๋‘”๋‹ค. ๊ทธ ํ›„ ์‚ฌ์šฉ์ž๊ฐ€ ์ถ”๊ฐ€ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ๋“ค์„ ํ•ด๋‹น ๊ตฌ๋ฌธ์— ์ฒจ๊ฐ€ํ•˜์—ฌ ์ด๋ฅผ ๋ฐ”๋กœ ์งˆ์˜์— ํ™œ์šฉํ•œ๋‹ค. 

์ด๋ฅผ ํ†ตํ•˜๋ฉด ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ์˜๋„๋Œ€๋กœ ์‚ฌ์ „์— ๊ตฌ๋ฌธ ๋ถ„์„์„ ์™„๋ฃŒํ•ด ๋‘˜ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์œ„ ์˜ˆ์‹œ์ฒ˜๋Ÿผ SQL๋ฌธ์ด ์ž…๋ ฅ์œผ๋กœ ๋“ค์–ด์˜จ๋‹ค ํ•ด๋„ ์ƒˆ๋กญ๊ฒŒ ๊ตฌ๋ฌธ ๋ถ„์„์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Š” ๋‹จ์ˆœ ๋ฌธ์ž์—ด๋กœ๋งŒ ์ธ์‹๋œ๋‹ค.

์ฆ‰ SQL Injection ๊ณต๊ฒฉ์„ ํšจ๊ณผ์ ์œผ๋กœ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ ํ•ด๋‹น ๋ฐฉ์‹์„ ์ด์šฉํ•˜๋ฉด ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ํ•˜๋“œ ํŒŒ์‹ฑ์„ ์ค„์—ฌ ์„ฑ๋Šฅ ์ƒ์˜ ์ด์ ๋„ ์กด์žฌํ•œ๋‹ค.

NodeJS์—์„œ Prepared Statement ํ™œ์šฉ

NodeJS์—์„œ๋Š” MySql2 ํŒจํ‚ค์ง€๋ฅผ ํ†ตํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด Prepared Statement๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ธฐ์กด์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑ๋˜์–ด ์žˆ๋˜ ์ฝ”๋“œ๋ฅผ

const sql = `SELECT * FROM account WHERE email='${email}'`;
await dbConnection.query(sql);

์•„๋ž˜์™€ ๊ฐ™์ด ์ˆ˜์ •ํ•˜๋ฉด ๋œ๋‹ค.

const sql = 'SELECT * FROM account WHERE email = ?';
await dbConnection.execute(sql,[email]);

๊ทธ๋Ÿฌ๋ฉด ? ๊ฐ€ ๋“ค์–ด๊ฐ„ ์ž๋ฆฌ๋ฅผ ๋น„์›Œ๋‘” ์ฑ„ ๊ตฌ๋ฌธ ๋ถ„์„์„ ์ˆ˜ํ–‰ํ•œ ๋’ค์—, ์ดํ›„ ํ•ด๋‹น ์ž๋ฆฌ์— ๋“ค์–ด๊ฐˆ ๊ฐ’๋งŒ ๋ฐ”๊พธ๋Š” ์‹์œผ๋กœ ์ž‘๋™ํ•˜๊ฒŒ ๋œ๋‹ค.

 

2. User Input์— ๋Œ€ํ•œ ์ถ”๊ฐ€์ ์ธ ๊ฒ€์ฆ ์ˆ˜ํ–‰

์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ ๊ฐ’์ด ํ”„๋กœ๊ทธ๋ž˜๋จธ์˜ ์˜๋„์™€ ๋ถ€ํ•ฉํ•˜๋Š”์ง€ ์ฟผ๋ฆฌ ์‹คํ–‰ ์ „ ๊ฒ€์ฆํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ๋‹ค. 

๊ฐ€๋ น ์œ„ ์˜ˆ์‹œ์—์„œ๋Š” ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ์œผ๋กœ ์ด๋ฉ”์ผ ํ˜•์‹ (xxxxxxxxx@xxxxx.xxx)์ด ๋“ค์–ด์™€์•ผ ํ•œ๋‹ค.

์ด๋ฅผ ์ •๊ทœ์‹์„ ํ†ตํ•ด ์‚ฌ์ „์— ๊ฒ€์ฆํ•œ๋‹ค๋ฉด SQL Injection ๊ณต๊ฒฉ์„ ๋Œ€์‘ํ•˜๋Š”๋ฐ ๋„์›€์ด ๋œ๋‹ค.