Search
Duplicate
๐Ÿ‘ฎ

SQL Injection ๋Œ€์‘ ๋ฐฉ์•ˆ

์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ๋…ธ์ถœ ์ฐจ๋‹จ

๊ณต๊ฒฉ์ž๊ฐ€ ๊ฒ€์ƒ‰์ฐฝ์— ์˜๋„์ ์ธ DB ์—๋Ÿฌ ์œ ๋ฐœ ์ฟผ๋ฆฌ ์ž…๋ ฅ ํ›„, ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ํ†ตํ•ด DB ์ •๋ณด(MySQL, ์ปฌ๋Ÿผ ๊ฐœ์ˆ˜ ๋“ฑ)๋ฅผ ์•Œ์•„๋‚ด๋ ค๋Š” ๊ณต๊ฒฉ ๋ฐฉ์ง€

์ž…๋ ฅ ๊ฐ’ ๊ฒ€์ฆ

1.
์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅ ๊ฐ€๋Šฅํ•œ ํŠน์ˆ˜๋ฌธ์ž ์ œํ•œ
2.
ํŠน์ˆ˜๋ฌธ์ž ํ•„ํ„ฐ๋ง
โ€ข
ex) input.replace(โ€œ--โ€, โ€œโ€);

Prepared Statement

Statement vs PreparedStatement

โ€ข
Statement : SQL ์ฟผ๋ฆฌ์— ์‚ฌ์šฉํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ง์ ‘ ๋„ฃ๊ณ  DB์— ์ฟผ๋ฆฌ๋ฅผ ์ „์†กํ•˜๋Š” ๋ฐฉ์‹
String sql = "select * from member where name = " + name + ";"; Statement statement = connection.createStatement(); statement.executeQuery(sql);
Java
๋ณต์‚ฌ
โ€ข
PreparedStatement : ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์ธ์ž๊ฐ’์ด ๋น„์–ด์žˆ๋Š” SQL ์ฟผ๋ฆฌ๋ฅผ ๋จผ์ € ์ค€๋น„ํ•œ ๋’ค์— ํ•„์š”ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋ฐ”์ธ๋”ฉํ•˜๋Š” ๋ฐฉ์‹
String sql = "select * from member where name = ?;" PreparedStatement preparedStatement = connection.preparedStatement(sql); preparedStatement.setString(1, name);
Java
๋ณต์‚ฌ

JdbcTemplate, JPA

๋‚ด๋ถ€์ ์œผ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐ”์ธ๋”ฉ ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ณ„๋‹ค๋ฅธ ์„ค์ • ์—†์ด SQL Injection์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

PreparedStatement(ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐ”์ธ๋”ฉ) ์‹ค์Šต

SQL Injection ๋ฐœ์ƒ ํ™˜๊ฒฝ

โ€ข
JpaRepository ํ˜น์€ JPQL์„ ์‚ฌ์šฉํ•˜๋ฉด ์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ์ด์œ ๋กœ ์ธํ•ด SQL Injection ๋ฐœ์ƒ ์ƒํ™ฉ์„ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์—†๋‹ค.
โ€ข
Native ์ฟผ๋ฆฌ๋ฅผ ์ง์ ‘ ์ž‘์„ฑํ•˜๋Š” ์ƒํ™ฉ์ด๋ผ๋ฉด SQL Injection ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ฅผ ์ด์šฉํ•˜์—ฌ SQL Injection ๋ฐœ์ƒ ํ™˜๊ฒฝ์„ ์„ธํŒ…ํ•œ๋‹ค.
1.
JPA์˜ Native ์ฟผ๋ฆฌ ์˜ต์…˜ ์‚ฌ์šฉ
โ€ข
@Query ์–ด๋…ธํ…Œ์ด์…˜์˜ nativeQuery = true ์˜ต์…˜
2.
JdbcTemplate(PreparedStatement ๋ฐฉ์‹)์„ ์‚ฌ์šฉํ•˜๋ฉด์„œ ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐ”์ธ๋”ฉ์ด ์•„๋‹ˆ๋ผ, SQL ์ฟผ๋ฆฌ๋ฌธ์— ์ธ์ž๊ฐ’์„ ์ง์ ‘ ๋ฌธ์ž์—ด concat์œผ๋กœ ์ถ”๊ฐ€ํ•ด์„œ ์ž‘์„ฑ๋œ ์ฟผ๋ฆฌ๋ฅผ DB์— ์ „์†ก
โ€ข
ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐ”์ธ๋”ฉ(SQL Injection ๋ฐฉ์ง€)
โ—ฆ
"WHERE content LIKE ?โ€
โ€ข
๋ฌธ์ž์—ด concat(SQL Injection ๋ฐฉ์ง€ X)
โ—ฆ
"WHERE content LIKE '%" + keyword + "%' โ€œ

์‹ค์Šต ๋‚ด์šฉ

โ€ข
๋‹ค์Œ๊ณผ ๊ฐ™์€ SQL Injection ์œ ๋ฐœ ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  DB์— ์ „์†กํ•œ๋‹ค.
create table eden (id int not null auto_increment, name varchar(255), primary key(id)); -- SQL Inejection ์œ ๋ฐœ ์ฟผ๋ฆฌ insert into eden (id, name) values (1, 'morak2'); drop table test; --'';
SQL
๋ณต์‚ฌ
โ—ฆ
๋ฌธ์ž์—ด concat ๋ฐฉ์‹๊ณผ ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐ”์ธ๋”ฉ ๋ฐฉ์‹์œผ๋กœ ๊ฐ๊ฐ ์ฟผ๋ฆฌ๋ฅผ ์ „์†กํ–ˆ์„ ๋•Œ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์–ด๋–ค ์ฐจ์ด๋กœ ์ธํ•ด SQL Injection์ด ์„ฑ๊ณต ํ˜น์€ ์‹คํŒจํ•˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
1.
๋ฌธ์ž์—ด concat ๋ฐฉ์‹
String sql = "insert into eden (id, name) values (1, " + name + ");";
Java
๋ณต์‚ฌ
2.
ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐ”์ธ๋”ฉ ๋ฐฉ์‹
// JpaRepository edenRepository.save(new Eden(null, "morak2'); drop table test; --'"));
Java
๋ณต์‚ฌ
โ€ข
๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” MySQL์„ ๊ธฐ์ค€์œผ๋กœ ํ•œ๋‹ค.

์‹ค์Šต ๊ฒฐ๊ณผ

๋ฌธ์ž์—ด concat ๋ฐฉ์‹

โ€ข
SQL SyntaxError๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
โ—ฆ
MySQL ์„œ๋ฒ„์—์„œ ํ•ด๋‹น ์ฟผ๋ฆฌ๋ฅผ ์ง์ ‘ ์ž…๋ ฅํ•˜๋ฉด ํ…Œ์ด๋ธ”์ด drop๋œ๋‹ค. โ†’ ์ฟผ๋ฆฌ ์ž์ฒด์—๋Š” ๋ฌธ์ œ X
โ—ฆ
๊ทธ๋ ‡๋‹ค๋ฉด ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋‹จ์—์„œ๋Š” ์™œ SyntaxError๊ฐ€ ๋ฐœ์ƒํ• ๊นŒ?
โ–ช
์ด๋ธŒ์™€ ์„ธ์šด ๊ฐ€์„ค - SQL ์ฟผ๋ฆฌ๊ฐ€ 2๊ฐœ ์ด์ƒ์ด๋ฉด ๊ฒฐ๊ณผ ์—ญ์‹œ 2๊ฐœ ์ด์ƒ์ด ๋œ๋‹ค. ํ•˜๋‚˜์˜ JdbcTemplate ๋ฉ”์†Œ๋“œ๋กœ ์—ฌ๋Ÿฌ ๊ฒฐ๊ณผ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†์–ด์„œ ์ด๋Ÿฌํ•œ ์ฟผ๋ฆฌ๋Š” JdbcTemplate์—์„œ SyntaxError๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค.
โ€ข
๊ทธ๋Ÿผ JdbcTemplate์„ ์‚ฌ์šฉํ•˜๋ฉด SQL Injection์ด ๋ฌด์กฐ๊ฑด ๋ฐฉ์ง€๋˜๋‚˜?
โ—ฆ
์กฐํšŒ ์ฟผ๋ฆฌ์—์„œ or 1=1;โ€”๊ณผ ๊ฐ™์€ ๊ฐ’์„ ์ž…๋ ฅํ•˜๋ฉด, ์กฐํšŒ ๊ฒฐ๊ณผ๋Š” ํ•˜๋‚˜์ง€๋งŒ ์กฐ๊ฑด์‹ ๊ฒฐ๊ณผ๊ฐ€ ๋ฌด์กฐ๊ฑด ์ฐธ์ด๋ฏ€๋กœ ํ…Œ์ด๋ธ”์˜ ๋ชจ๋“  ๋ ˆ์ฝ”๋“œ๋ฅผ ์กฐํšŒํ•ด์˜ค๊ฒŒ ๋œ๋‹ค. ์ฆ‰, SQL Injection์ด ์„ฑ๊ณตํ•œ๋‹ค.

ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐ”์ธ๋”ฉ ๋ฐฉ์‹

โ€ข
Hibernate ๋กœ๊ทธ
โ€ข
MySQL ์„œ๋ฒ„ ์ฟผ๋ฆฌ ๋กœ๊ทธ
2022-12-08T07:18:54.504132Z 559 Query SET autocommit=0 2022-12-08T07:18:54.536313Z 559 Query insert into eden (name) values ('morak2''); drop table test; โ€”''') 2022-12-08T07:18:54.551643Z 559 Query commit 2022-12-08T07:18:54.556176Z 559 Query SET autocommit=1
Shell
๋ณต์‚ฌ
โ€ข
MySQL ๊ธฐ์ค€, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ๋ฐ”์ธ๋”ฉ ๋  ์ž๋ฆฌ์˜ ์•ž๋’ค๋กœ (โ€™ ์™€ โ€˜)๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.
โ€ข
๋ฐ”์ธ๋”ฉ ๋  ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์ž…๋ ฅ๋˜๋ฉด, โ€˜(์ž‘์€ ๋”ฐ์˜ดํ‘œ)๊ฐ™์€ ํŠน์ˆ˜๋ฌธ์ž๋Š” ๋ฌธ์ž์—ด(ํŒŒ๋ผ๋ฏธํ„ฐ)๋กœ์จ SQL์— ๋ฐ”์ธ๋”ฉ ๋  ์ˆ˜ ์žˆ๋„๋ก MySQL์—์„œ ํŠน์ˆ˜๋ฌธ์ž ์•ž์— ์ด์Šค์ผ€์ดํ”„ ๋ฌธ์ž๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.
โ—ฆ
์ด๋•Œ ์ถ”๊ฐ€๋˜๋Š” ์ด์Šค์ผ€์ดํ”„ ๋ฌธ์ž๋Š” ํ„ฐ๋ฏธ๋„์—์„œ ํ™•์ธํ•˜๊ธฐ์— ์ž‘์€ ๋”ฐ์˜ดํ‘œ์™€ ์ฐจ์ด๊ฐ€ ์—†๋‹ค. ์•„๋งˆ ๋ณด๊ธฐ์—๋Š” ์ž‘์€ ๋”ฐ์˜ดํ‘œ์™€ ๋˜‘๊ฐ™์ง€๋งŒ MySQL ๋‚ด๋ถ€์ ์œผ๋กœ ์ธ์ฝ”๋”ฉ ๋„˜๋ฒ„๊ฐ€ ๋‹ค๋ฅธ ๋ณ„๋„์˜ ์ด์Šค์ผ€์ดํ”„ ๋ฌธ์ž์ผ ๊ฒƒ์œผ๋กœ ์ถ”์ •
โ€ข
๊ฒฐ๊ณผ์ ์œผ๋กœ SQL Injection์ด ๋ฐฉ์ง€๋œ๋‹ค.