Skip to content

Latest commit

ย 

History

History
285 lines (214 loc) ยท 9.34 KB

File metadata and controls

285 lines (214 loc) ยท 9.34 KB

Xquery Injection

๊ฐ€. ์ •์˜

๋Œ€ํ‘œ์ ์ธ ๋งˆํฌ์—… ์–ธ์–ด์ธ XML ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•ด ๋™์  ์ฟผ๋ฆฌ๋ฌธ์„ ์ƒ์„ฑํ•  ๋•Œ XQuery๋ฅผ ์‚ฌ์šฉํ•˜๊ณค ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋•Œ ์™ธ๋ถ€ ์ž…๋ ฅ ๊ฐ’์— ๋Œ€ํ•ด ์ ์ ˆํ•œ ๊ฒ€์ฆ ์ ˆ์ฐจ๊ฐ€ ํ•„์š”ํ•œ๋ฐ์š”. ๋งŒ์ผ ๊ฒ€์ฆ ์ ˆ์ฐจ๊ฐ€ ์—†์„ ๊ฒฝ์šฐ์—๋Š” ๊ณต๊ฒฉ์ž๊ฐ€ ์ฟผ๋ฆฌ๋ฌธ์˜ ๊ตฌ์กฐ๋ฅผ ์ž„์˜๋กœ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์•…์˜์ ์ธ ์ฟผ๋ฆฌ๊ฐ€ ์‹คํ–‰๋˜์–ด ํ—ˆ๊ฐ€๋˜์ง€ ์•Š์€ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๊ฑฐ๋‚˜ ์ธ์ฆ ์ ˆ์ฐจ๋ฅผ ์šฐํšŒํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์–ด ์œ„ํ˜‘์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๊ณต๊ฒฉ์„ ๋ฐ”๋กœ XQuery ์‚ฝ์ž…(XQuery Injection) ์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

XQuery Injection์˜ ๊ณต๊ฒฉ ์›๋ฆฌ๋ฅผ ์ •๋ฆฌํ•ด๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ˆœ์„œ๋กœ ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค.

  1. ๊ณต๊ฒฉ์ž๊ฐ€ XQuery Injection ์‹œ๋„
  2. XML ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ์กฐ์ž‘๋œ ๋™์  ์ฟผ๋ฆฌ๋ฌธ ์ƒ์„ฑ
  3. ์กฐ์ž‘๋œ XQuery๋ฌธ ์‹คํ–‰
  4. ์„œ๋ฒ„๋Š” ์‹คํ–‰๋œ ๊ฒฐ๊ณผ ์ฆ‰, ๊ณต๊ฒฉ ๊ฒฐ๊ณผ๋ฅผ ๊ณต๊ฒฉ์ž์—๊ฒŒ ์ „๋‹ฌ

๋‚˜. ์•ˆ์ „ํ•œ ์ฝ”๋”ฉ๊ธฐ๋ฒ•

XQuery Injection์„ ์˜ˆ๋ฐฉํ•˜๊ธฐ ์œ„ํ•œ ์•ˆ์ „ํ•œ ์ฝ”๋”ฉ ๊ธฐ๋ฒ•์€ ํฌ๊ฒŒ 2๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. XQuery์— ์‚ฌ์šฉ๋˜๋Š” ์™ธ๋ถ€ ์ž…๋ ฅ๊ฐ’์— ๋Œ€ํ•˜์—ฌ ํŠน์ˆ˜๋ฌธ์ž๋‚˜ ์ฟผ๋ฆฌ ์˜ˆ์•ฝ์–ด๋ฅผ ํ•„ํ„ฐ๋งํ•ฉ๋‹ˆ๋‹ค
  2. XQuery๋ฅผ ์‚ฌ์šฉํ•œ ์ฟผ๋ฆฌ๋ฌธ์€ string์„ ์—ฐ๊ฒฐํ•˜๋Š” ํ˜•ํƒœ๊ฐ€ ์•„๋‹Œ ํŒŒ๋ผ๋ฏธํ„ฐํ™”๋œ ์ฟผ๋ฆฌ๋ฌธ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค

์•„๋ž˜ ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ์กฐ๊ธˆ ๋” ๊ตฌ์ฒด์ ์œผ๋กœ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋‹ค. ์˜ˆ์ œ1

๋จผ์ € ์•ˆ์ „ํ•˜์ง€ ์•Š์€ ์ฝ”๋“œ ์ „์ฒด๋ถ€ํ„ฐ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ด ์˜ˆ์ œ๋Š” ์™ธ๋ถ€๋กœ๋ถ€ํ„ฐ ์ž…๋ ฅ๋ฐ›์€ ๊ฐ’(name)์„ executeQuery๋ฅผ ์‚ฌ์šฉํ•œ ์งˆ์˜ ์ƒ์„ฑ ๋ฌธ์ž์—ด ์ธ์ž ์ƒ์„ฑ์— ์‚ฌ์šฉํ•˜๋Š” ๊ณผ์ •์˜ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

......

	// ์™ธ๋ถ€๋กœ๋ถ€ํ„ฐ ์ž…๋ ฅ ๊ฐ’(name) ๋ฐ›์Œ
	String name = props.getProperty("name");
	
	//
	Hashtable env = new Hashtable();
	env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
	env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=rootDir");
	javax.naming.directory.DirContext ctx = new InitialDirContext(env);
	javax.xml.xquery.XQDataSource xqds = (javax.xml.xquery.XQDataSource) ctx.lookup("xqj/personnel");
	javax.xml.xquery.XQConnection conn = xqds.getConnection();

	//์•ˆ์ „ํ•˜์ง€ ์•Š์€ ์ฝ”๋“œ
	String es = "doc('users.xml')/userlist/user[uname='" + name + "']";
	
	// ์ž…๋ ฅ๊ฐ’์ด Xquery ์ธ์ž๋กœ ์‚ฌ์šฉ
	XQPreparedExpression expr = conn.prepareExpression(es);
	XQResultSequence result = expr.executeQuery();
	
	while (result.next())
	{
				String str = result.getAtomicValue();
				if (str.indexOf('>') < 0)
				{
						System.out.println(str);
				}

......

์ด ๋•Œ, ์™ธ๋ถ€๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ์ž…๋ ฅ ๊ฐ’์„ ๋ฐ›์€ ๊ฒƒ์„ ๋ฐ”๋กœ XQuery๋ฌธ์— ํฌํ•จ์‹œ์ผœ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

String es = "doc('users.xml')/userlist/user[uname='" + name + "']";

์ด ๊ฒฝ์šฐ, ๋งŒ์ผ ์™ธ๋ถ€ ์ž…๋ ฅ๊ฐ’์ด XQuery ์ƒ์˜ ์ฟผ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๋ณ€๊ฒฝ์‹œํ‚ค๋Š” ๊ตฌ๋ฌธ์ผ ๊ฒฝ์šฐ, XQuery Injection์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

name์˜ ๊ฐ’์„ something' or '1'='1 ๊ณผ ๊ฐ™์ด ์ „๋‹ฌํ•˜๊ฒŒ ๋˜๋ฉด doc('users.xml')/userlist/user[uname='something' or '1'='1' ์™€ ๊ฐ™์€ ์งˆ์˜๋ฌธ์„ ์ˆ˜ํ–‰ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด ํŒŒ์ผ ๋‚ด์˜ ๋ชจ๋“  ๊ฐ’์„ ์ถœ๋ ฅํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์–ด ์ •๋ณด๊ฐ€ ์œ ์ถœ๋  ์œ„ํ—˜์ด ์žˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์ด๋ฅผ ๋ง‰๊ธฐ ์œ„ํ•ด ์•„๋ž˜์™€ ๊ฐ™์ด ์ธ์ž(parameter) ํ˜•์‹์œผ๋กœ ์ „๋‹ฌ๋  ์ˆ˜ ์žˆ๋„๋ก ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

String es = "doc('user.xml')/userlist/user[uname='$xpathname']";
expr.bindString(new QName("xpathname"), name, null); 
XQResultSequence result = expr.executeQuery();

preparedExpression์„ ์‚ฌ์šฉํ•˜์—ฌ bindString, bindInt ๋“ฑ์˜ ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์ธ์ž ํ˜•์‹์œผ๋กœ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ์‹์ธ๋ฐ์š”. ์ด๋ฅผ ํ†ตํ•ด ์™ธ๋ถ€์—์„œ ์ž…๋ ฅ๋ฐ›์€ ๊ฐ’์€ ๋‹จ์ˆœํžˆ ๋ฌธ์ž์—ด๋กœ ์ทจ๊ธ‰๋˜๋ฉฐ XQuery ์ƒ์˜ ์ฟผ๋ฆฌ ๋ฌธ๋ฒ•์œผ๋กœ ์ธ์‹๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์™ธ๋ถ€ ์ž…๋ ฅ์œผ๋กœ๋ถ€ํ„ฐ ์ฟผ๋ฆฌ ๊ตฌ์กฐ๊ฐ€ ๋ฐ”๋€Œ๋Š” ๊ฒƒ์„ ๋ง‰์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์•ˆ์ „ํ•œ ์ฝ”๋“œ์˜ ์ „์ฒด๋Š” ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

......

	// ์™ธ๋ถ€๋กœ๋ถ€ํ„ฐ ์ž…๋ ฅ ๊ฐ’(name) ๋ฐ›์Œ
	String name = props.getProperty("name");
	Hashtable env = new Hashtable();
	env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
	env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=rootDir");
	javax.naming.directory.DirContext ctx = new InitialDirContext(env);
	javax.xml.xquery.XQDataSource xqds = (javax.xml.xquery.XQDataSource) ctx.lookup("xqj/personnel");
	javax.xml.xquery.XQConnection conn = xqds.getConnection();

	//์•ˆ์ „ํ•œ ์ฝ”๋“œ
	String es = "doc('users.xml')/userlist/user[uname='$xpathname']";
	
	// ์ž…๋ ฅ๊ฐ’์ด Xquery ์ธ์ž๋กœ ์‚ฌ์šฉ
	XQPreparedExpression expr = conn.prepareExpression(es);
	expr.bindString(new QName("xpathname"), name, null);
	XQResultSequence result = expr.executeQuery();
	
	while (result.next())
	{
				String str = result.getAtomicValue();
				if (str.indexOf('>') < 0)
				{
						System.out.println(str);
				}

๋‹ค. ์˜ˆ์ œ2

ํŠน์ • ์•„์ดํ…œ์˜ ํŒ๋งค๊ฐ€๊ฒฉ์„ ์•Œ์•„์˜ค๋Š” ์ฝ”๋“œ ์ค‘ ์•ˆ์ „ํ•˜์ง€ ์•Š์€ ์ฝ”๋“œ์˜ ์˜ˆ์‹œ๋ฅผ ํ•œ๋ฒˆ ๋ณผ๊นŒ์š”?

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

๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ์ฝ”๋“œ๊ฐ€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฃผ์–ด์ ธ์žˆ์Šต๋‹ˆ๋‹ค. โฌ‡๏ธ

<?xml version="1.0"?>
 <items>
	 ...
	 <price>
	 <selling_price>
	 <iem001>100</iem001>
	 <iem002>150</iem001>
	...
	 </selling_price>
	 <buying_price>
	 <iem001>50</iem001>
	 <iem002>140</iem001>
	 ...
	 </buying_price>
	 </price>
	 ...
</items>

์—ฌ๊ธฐ์—์„œ ํŠน์ • ์•„์ดํ…œ์˜ ํŒ๋งค๊ฐ€๊ฒฉ์„ ์•Œ์•„์™€๋ด…์‹œ๋‹ค.

string์„ ์—ฐ๊ฒฐํ•˜๋Š” ํ˜•ํƒœ๋กœ ๊ตฌ์„ฑ๋œ ์ฟผ๋ฆฌ๋ฌธ์œผ๋กœ ์ž‘์„ฑ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค. โฌ‡๏ธ

String itemId = request.getParameter(ITEM_ID);
			
			 XQExpression xqe = conn.createExpression();
			 String xqueryString = "doc('items.xml')/items/price/selling_price/" + itemId;

์ด๋ ‡๊ฒŒ ๋˜๋ฉด ์ ์ ˆํ•œ ๊ฒ€์ฆ ์ ˆ์ฐจ๋ฅผ ๊ฑฐ์น˜์ง€ ์•Š๊ณ ๋„ ํŠน์ • ์•„์ดํ…œ์˜ ๊ตฌ๋งค๊ฐ€๊ฒฉ์„ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋•Œ๋ฌธ์— ์›ํ•˜์ง€ ์•Š๋Š” ์ •๋ณด๊ฐ€ ๋…ธ์ถœ๋  ์œ„ํ—˜์ด ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ’ก ๊ทธ๋Ÿผ ์–ด๋–ป๊ฒŒ ์•ˆ์ „ํ•œ ์ฝ”๋“œ๋ฅผ ์งค ์ˆ˜ ์žˆ์„๊นŒ์š”?

์ด์ „์˜ ์•ˆ์ „ํ•˜์ง€ ์•Š์€ ์ฝ”๋“œ์—์„œ๋Š” ๋™์  ์ฟผ๋ฆฌ๋ฌธ์„ ์ƒ์„ฑํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ์™ธ๋ถ€ ์ž…๋ ฅ ๊ฐ’์— ๋Œ€ํ•ด ์ ์ ˆํ•œ ๊ฒ€์ฆ ๊ณผ์ •์„ ๊ฑฐ์น˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์ด์™€ ๋‹ฌ๋ฆฌ ์ด๋ฒˆ์—๋Š” ๋™์  ์ƒ์„ฑ์„ ํ•˜๋Š” ๋Œ€์‹ ์— ์งˆ์˜๋ฌธ์„ PrepareExpression์œผ๋กœ ์ค€๋น„ํ•œ ํ›„, ์ž…๋ ฅ๊ฐ’์„ ์ธ์ž๋กœ ์ „๋‹ฌํ•˜์—ฌ ์•ˆ์ „์„ฑ์„ ๋†’์—ฌ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

	 String xqueryString = "doc('items.xml')/items/price/selling_price/'$itemId';
		 //๋ณด์•ˆ์„ฑ์„ ์œ„ํ•ด prepareExpression์œผ๋กœ ์งˆ์˜๋ฌธ ์ค€๋น„
		 xqe = conn.prepareExpression(xqueryString);

์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์งœ๋ฉด, ์งˆ์˜๋ฌธ์— ๋Œ€ํ•œ ๊ตฌ๋ฌธ ๋ถ„์„์ด ๋”์ด์ƒ ๋™์ ์œผ๋กœ ์ด๋ฃจ์–ด์ง€์ง€ ์•Š๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ž…๋ ฅ ๊ฐ’์— ์งˆ์˜๋ฌธ์˜ ๊ตฌ์กฐ๊ฐ€ ๋ฐ”๋€Œ๋Š” ๊ฒƒ์„ ๋ง‰์•„ ์›ํ•˜์ง€ ์•Š๋Š” ์ •๋ณด๊ฐ€ ๋…ธ์ถœ๋˜๋Š” ํ˜„์ƒ์„ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค.

		 if (command.equals(GET_ITEM_PRICE))
		 {
			 String itemId = request.getParameter(ITEM_ID);
			
			 xqe.bindString(new QName("itemId"), itemId, null);
			 XQResultSequence rs = xqe.executeQuery();
			 ...
		 }

์•ˆ์ „ํ•œ ์ฝ”๋“œ์™€ ์•ˆ์ „ํ•˜์ง€ ์•Š์€ ์˜ˆ์‹œ์˜ ์ „์ฒด ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

โฌ‡๏ธ ์ „์ฒด ์ฝ”๋“œ

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

 public class Service extends HttpServlet
 {
	 private final String COMMAND_PARAM = "command";
	
	 // Command ๊ด€๋ จ์ •์˜
	 private final String GET_ITEM_PRICE = "get_item_price";
	
	 private final String ITEM_ID = "item_id";
	
	 private XQDataSource xqs;
	 private XQConnection conn;
	
	 public Service()
	 {
		 ...
		 xqs = new SednaXQDataSource();
		 xqs.setProperty("serverName", "localhost");
		 xqs.setProperty("databaseName", "test");
		 conn = xqs.getConnection("SYSTEM", "MANAGER");
		 ...
	 }
	 ...
	 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws
	ServletException, IOException
	 {
			 String command = request.getParameter(COMMAND_PARAM);
		 ...
		if (command.equals(GET_ITEM_PRICE))
		 {
			 String itemId = request.getParameter(ITEM_ID);
			
			 XQExpression xqe = conn.createExpression();
			 String xqueryString = "doc('items.xml')/items/price/selling_price/" + itemId;
			
			 XQResultSequence rs = xqe.executeQuery(xqueryString);
			 ...
		 }
		 ...
	 }
	 ...
}

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

public class Service extends HttpServlet
 {
	 private final String COMMAND_PARAM = "command";
	
	 // Command ๊ด€๋ จ์ •์˜
	 private final String GET_ITEM_PRICE = "get_item_price";
	
	 private final String ITEM_ID = "item_id";
	
	 private XQDataSource xqs;
	 private XQConnection conn;
	 private XQPrepareExpression xqe;
	
		public Service()
		{
			...
		 xqs = new SednaXQDataSource();
		 xqs.setProperty("serverName", "localhost");
		 xqs.setProperty("databaseName", "test");
		 conn = xqs.getConnection("SYSTEM", "MANAGER");
		 String xqueryString = "doc('items.xml')/items/price/selling_price/'$itemId';
		 //๋ณด์•ˆ์„ฑ์„ ์œ„ํ•ด prepareExpression์œผ๋กœ ์งˆ์˜๋ฌธ ์ค€๋น„
		 xqe = conn.prepareExpression(xqueryString);
		 ...
	 }
	 ...
	 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws
	ServletException, IOException
	 {
		 String command = request.getParameter(COMMAND_PARAM)
		...
		 if (command.equals(GET_ITEM_PRICE))
		 {
			 String itemId = request.getParameter(ITEM_ID);
			
			 xqe.bindString(new QName("itemId"), itemId, null);
			 XQResultSequence rs = xqe.executeQuery();
			 ...
		 }
		 ...
	 }
	 ...
 }

๋ผ. ์ถœ์ฒ˜

ํ–‰์ •์•ˆ์ „๋ถ€_JAVA ์‹œํ์–ด์ฝ”๋”ฉ ๊ฐ€์ด๋“œ

ํ–‰์ •์•ˆ์ „๋ถ€_C ์‹œํ์–ด์ฝ”๋”ฉ ๊ฐ€์ด๋“œ