Skip to content

Latest commit

ย 

History

History
116 lines (82 loc) ยท 3.9 KB

SQL_Injection_Persistence.md

File metadata and controls

116 lines (82 loc) ยท 3.9 KB

SQL Injection : Persistence

API Injection: Persistence ๋ž€?

J2EE Persistence API๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์‘์šฉํ”„๋กœ๊ทธ๋žจ์—์„œ ์™ธ๋ถ€์˜ ์ž…๋ ฅ์„ ๊ฒ€์ฆ ์—†์ด ์งˆ์˜๋ฌธ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ, ์—ญ์‹œ ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ์˜๋„ํ•˜์ง€ ์•Š์•˜๋˜ ์ž„์˜์˜ query ๋ช…๋ น์–ด๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ณต๊ฒฉ์„ ๋งํ•œ๋‹ค.

โžก๏ธ ์•ˆ์ „ํ•œ ์ฝ”๋”ฉ ๋ฐฉ๋ฒ•

  • ์™ธ๋ถ€์˜ ์ž…๋ ฅ์ด ์งˆ์˜๋ฌธ์˜ ๊ตฌ์กฐ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋„๋ก ํ•œ๋‹ค. ์ฆ‰, ์ธ์žํ™” ๋œ ์งˆ์˜๋ฌธ ์‚ฌ์šฉ
  • ์งˆ์˜๋ฌธ ์ƒ์„ฑ ์‹œ ์ƒ์ˆ˜ ๋ฌธ์ž์—ด๋งŒ์„ ์‚ฌ์šฉํ•˜๊ณ , javax.persistence.Query.setParameter() ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ธ์ž๊ฐ’์„ ์„ค์ •ํ•œ๋‹ค.

์˜ˆ์ œ 1 - ์ž…๋ ฅ๊ฐ’ ๊ฒ€์ฆ

์ž…๋ ฅ๊ฐ’์„ id๋ผ๊ณ  ํ•  ๋•Œ, ์ž…๋ ฅํ•œ ๊ฐ’์€ ๋‹ค์Œ ์œ„์น˜์— ๋“ค์–ด๊ฐ„๋‹ค.

SELECT col1 FROM MYTABLE WHERE name = '(์ž…๋ ฅ๊ฐ’)'

๋งŒ์•ฝ ๊ณต๊ฒฉ์ž๊ฐ€ ์ž…๋ ฅ๊ฐ’์œผ๋กœ foo'; DROP MYTABLE; โ€” ์„ ์ž…๋ ฅํ•˜๋ฉด ์งˆ์˜๋ฌธ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์™„์„ฑ๋œ๋‹ค.

SELECT col1 FROM MYTABLE WHERE name = 'foo'; DROP MYTABLE; --'

๋”ฐ๋ผ์„œ ๊ฒ€์ฆ ์—†์ด ์งˆ์˜๋ฌธ์„ ๊ทธ๋Œ€๋กœ ์ž…๋ ฅํ•˜๋ฉด, MYTABLE ์„ ์‚ญ์ œํ•˜๋Š” ๋ช…๋ น์–ด๊ฐ€ ์‹คํ–‰๋œ๋‹ค.


์•ˆ์ „ํ•˜์ง€ ์•Š์€ ์ฝ”๋“œ

Properties props = new Properties();
String fileName = "conditions.txt";
FileInputStream in = new FileInputStream(fileName);
props.load(in);

// ์™ธ๋ถ€๋กœ๋ถ€ํ„ฐ ์ž…๋ ฅ ๋ฐ›๊ธฐ
String id = props.getProperty("id");
// ์™ธ๋ถ€ ์ž…๋ ฅ๊ฐ’์ด ๊ทธ๋Œ€๋กœ query์˜ ์ธ์ž๋กœ ์‚ฌ์šฉ๋œ๋‹ค.
Query query = 
em.createNativeQuery("SELECT OBJECT(i) FROM Item i WHERE i.itemID > " + id);
List<ItemListner> items = query.getResultList();
โ€ฆโ€ฆ
return r_type;

โ‡’ ๋”ฐ๋ผ์„œ ์ธ์ž๋ฅผ ๋ฐ›๋Š” ์งˆ์˜๋ฌธ์„ ์ƒ์„ฑ ํ›„, ์ธ์ž ๊ฐ’์„ ์„ค์ •ํ•˜์—ฌ ์‹คํ–‰๋˜๋„๋ก ํ•œ๋‹ค.

๊ทธ๋ ‡๊ฒŒ ํ•˜๋ฉด ์™ธ๋ถ€ ์ž…๋ ฅ๊ฐ’์— ๋”ฐ๋ผ์„œ ์งˆ์˜๋ฌธ ๊ตฌ์กฐ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.


์•ˆ์ „ํ•œ ์ฝ”๋“œ

Properties props = new Properties();
String fileName = "conditions.txt";
FileInputStream in = new FileInputStream(fileName);
props.load(in);

// ์™ธ๋ถ€ ์ž…๋ ฅ๊ฐ’ ๋ฐ›๊ธฐ
String id = props.getProperty("id");
// ์ž…๋ ฅ๊ฐ’์„ ๊ฒ€์‚ฌํ•œ๋‹ค
if (id == null || "".equals(id)) id = "itemid";
// Query์„ ์ž‘์„ฑํ•œ๋‹ค
Query query = 
em.createNativeQuery("SELECT OBJECT(i) FROM Item i WHERE i.itemID > :id");
query.setParameter("id", id);
List<ItemListner> items = query.getResultList();
โ€ฆโ€ฆ
return r_type;

์˜ˆ์ œ2 - ๋ฌธ์ž์—ด ๊ฒ€์ฆ ํ•จ์ˆ˜

  • ์ž…๋ ฅ๊ฐ’์— userID์™€ passwd๋ฅผ SQL ์งˆ์˜๋ฌธ์— ๊ทธ๋Œ€๋กœ ๋„ฃ๋Š” ๊ฒฝ์šฐ

์•ˆ์ „ํ•˜๊ฒŒ SQL ๊ตฌ๋ฌธ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด, ์™ธ๋ถ€๋กœ๋ถ€ํ„ฐ ์ž…๋ ฅ๋˜๋Š” ๊ฐ’์„ ์งˆ์˜๋ฌธ์— ๋ฐ”๋กœ ์‚ฌ์šฉํ•˜๊ธฐ ์ „์— ์•ˆ์ „ํ•œ ํ˜•ํƒœ๋กœ makeSecureString ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๋ณ€๊ฒฝํ•œ๋‹ค.

์ด ํ•จ์ˆ˜๋กœ๋Š” 3๊ฐ€์ง€ ์ œํ•œ ์กฐ๊ฑด์„ ์‚ฌ์šฉํ•˜์—ฌ ์•ˆ์ „ํ•œ ๋ฌธ์ž์—ด์„ ์ƒ์„ฑ ๊ฐ€๋Šฅํ•˜๋‹ค.

  1. ์ธ์ž์— SQL๋ฌธ์—์„œ ์“ฐ์ด๋Š” ์˜ˆ์•ฝ์–ด๋ฅผ ์ œํ•œํ•œ๋‹ค.
  2. ์ธ์ž์— ์•ŒํŒŒ๋ฒณ๊ณผ ์ˆซ์ž๋ฅผ ์ œ์™ธํ•œ ๋ฌธ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ์ œํ•œํ•œ๋‹ค. ( ํŠนํžˆ ' ์‹ฑ๊ธ€๋”ฐ์˜ดํ‘œ)
  3. ์œ„์˜ ์กฐ๊ฑด์„ ์ œํ•œํ•˜๊ธฐ ์œ„ํ•ด ์ •๊ทœ์‹์„ ์‚ฌ์šฉํ•œ๋‹ค.

โžก๏ธ ๋ฌธ์ž์—ด์„ ๋” ์•ˆ์ „ํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  1. ๋ฌธ์ž์—ด์˜ ๊ธธ์ด ์ œํ•œ์„ ๋‚ฎ์ถ˜๋‹ค.
  2. ์ •๊ทœ์‹์— ํฌํ•จ๋˜๋Š” ๋‹จ์–ด์˜ ๊ฐœ์ˆ˜๋ฅผ ๋†’์ธ๋‹ค. (๋ธ”๋ž™๋ฆฌ์ŠคํŠธ ๊ฐœ๋…์œผ๋กœ SQL procedure๋ช…์ด๋‚˜ SQL ๋ช…๋ น์–ด๋“ค์„ ํ•„ํ„ฐ๋งํ•  ์ •๊ทœ์‹์— ํฌํ•จ)

private String makeSecureString(final String str, int maxLength) 
{
	String secureStr = str.substring(0, maxLength);
	Matcher matcher = unsecuredCharPattern.matcher(secureStr)
	return matcher.replaceAll("");
}

๋”ฐ๋ผ์„œ ํ•จ์ˆ˜๋Š” ์œ„์™€ ๊ฐ™์ด ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

String query = "SELECT * FROM members WHERE username= '" + makeSecureString(userId) + "' AND password = '" + makeSecureString(password) + "'";
Query query = manager.newQuery(queryStr);

๊ทธ ํ›„ ์ž…๋ ฅ๊ฐ’์„ ์œ„์˜ ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ์ „๋‹ฌ ํ•œ ํ›„, ์ƒ์„ฑ๋œ ๋ฌธ์ž์—ด์„ SQL ๋ช…๋ น์–ด์— ๋„ฃ์–ด ์‹คํ–‰ํ•˜๋ฉด ๋ณด๋‹ค ์•ˆ์ „ํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.