Jinja: ๊ธฐ๋ณธ์ ์œผ๋กœ ๋น„ํ™œ์„ฑํ™”๋œ ์ž๋™ ์ด์Šค์ผ€์ดํ”„๋Š” ์œ„ํ—˜ํ•œ ๊ธฐ๋ณธ๊ฐ’์ž…๋‹ˆ๋‹ค.

์— ๋งŒ๋“  2016๋…„ 01์›” 06์ผ  ยท  4์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: pallets/jinja

์ €๋Š” ์˜ค๋Š˜ ์™ธ๋ถ€์—์„œ ๋ณด๊ณ ๋œ XSS๋ฅผ ํ†ตํ•ด Jinja๊ฐ€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ž๋™ ์ด์Šค์ผ€์ดํ”„๋ฅผ ์ผœ์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์„ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์œ„ํ—˜ํ•œ ๊ธฐ๋ณธ๊ฐ’์ž…๋‹ˆ๋‹ค. ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด 2007๋…„๋ถ€ํ„ฐ ์ž๋™ ์ด์Šค์ผ€์ดํ”„๊ฐ€ ๊ธฐ๋ณธ์ ์œผ๋กœ ํ™œ์„ฑํ™”๋œ Django ํ…œํ”Œ๋ฆฟ์— ๋Œ€ํ•œ ์ด์ „ ์ง€์‹์„ ํ†ตํ•ด Jinja๋ฅผ ์•Œ๊ฒŒ ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋”์šฑ ์œ„ํ—˜ํ•ด์กŒ์Šต๋‹ˆ๋‹ค.

์ธํ„ฐ๋„ท์„ ๋’ค์ ธ๋ณด๋ฉด ์ด ์‚ฌ์‹ค์ด ์ž˜ ์•Œ๋ ค์ง€์ง€ ์•Š์€ ๊ฒƒ ๊ฐ™๋‹ค. ์‚ฌ์‹ค, ์›น ์‚ฌ์ดํŠธ์— jinja2๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์ž๋™ ์ด์Šค์ผ€์ดํ”„๋ฅผ ํ•ด์ œํ•˜๋„๋ก ๊ถŒ์žฅํ•˜๋Š” ์ฑ…(Python 3 ๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ, 12์žฅ, cc @buchuki)๋„ ์ฐพ์•˜์Šต๋‹ˆ๋‹ค. Github ํ”„๋กœ์ ํŠธ์˜ ๋ฌด์ž‘์œ„ ์ƒ˜ํ”Œ์€ ๋˜ํ•œ ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ๋žŒ๋“ค์ด autoescape=True ๋˜๋Š” autoescape ํ™•์žฅ์„ ํ”„๋กœ์ ํŠธ์— ์ถ”๊ฐ€ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

๊ทธ ์‹œ์ ์—์„œ ๋” ์•ˆ์ „ํ•œ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๋Š” ๊ฒƒ์ด ๊ณ ํ†ต์Šค๋Ÿฌ์šธ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์ดํ•ดํ•˜์ง€๋งŒ ๋ฌธ์„œ์—์„œ๋Š” ์ตœ์†Œํ•œ ์ž๋™ ์ด์Šค์ผ€์ดํ”„๊ฐ€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๊บผ์ ธ ์žˆ์Œ์„ ๋ถ„๋ช…ํžˆ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. jinja2.Environment ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ชจ๋“  ์˜ˆ์ œ์— autoescape=True ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ๋ฌธ์„œ ์ดˆ๊ธฐ์— ์„น์…˜์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

ํ’€ ๋ฆฌํ€˜์ŠคํŠธ์— ์ ํ•ฉํ•œ ํ›„๋ณด์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. :)

๋ชจ๋“  4 ๋Œ“๊ธ€

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

์ฆ‰, HTML์„ ์ƒ์„ฑํ•  ๋•Œ ์ž๋™ ์ด์Šค์ผ€์ดํ”„๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ ์„ ๋ฌธ์„œ์—์„œ ๋ถ„๋ช…ํžˆ ๋ฐํžˆ๋Š” ๊ฒƒ์ด ์ข‹์€ ์ œ์•ˆ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋Œ€๋ถ€๋ถ„์˜ ์ฃผ์š” ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์ง€๋งŒ(๋ˆˆ์ด ๋” ๋งŽ์ด, ๋ฒ„๊ทธ๊ฐ€ ๋” ์ ์€ ๋“ฑ) Jinja๋ฅผ ์ˆ˜๋™์œผ๋กœ ํ†ตํ•ฉํ•˜์—ฌ ์ด๋Ÿฌํ•œ ์‹ค์ˆ˜๋ฅผ ํ•˜๋Š” ์†Œ๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ๋„ ๋งŽ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์†”์งํžˆ ๋งํ•ด์„œ, Jinja์˜ ๋ฌธ์„œ๋Š” ๊ทธ ์ฃผ์ œ์— ๋Œ€ํ•ด ์ •๋ง ์—ด์•…ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ์€ Jinja์˜ ๋ฌธ์„œ๋ฅผ ์—ด ๋•Œ ๊ฐ€์žฅ ๋จผ์ € ํ‘œ์‹œ๋˜๋Š” ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.

Jinja2๋Š” Django์˜ ํ…œํ”Œ๋ฆฟ์„ ๋ชจ๋ธ๋กœ ํ•œ Python์šฉ ํ˜„๋Œ€์ ์ด๊ณ  ๋””์ž์ด๋„ˆ ์นœํ™”์ ์ธ ํ…œํ”Œ๋ฆฟ ์–ธ์–ด์ž…๋‹ˆ๋‹ค. ์„ ํƒ์  ์ƒŒ๋“œ๋ฐ•์Šค ํ…œํ”Œ๋ฆฟ ์‹คํ–‰ ํ™˜๊ฒฝ์œผ๋กœ ๋น ๋ฅด๊ณ  ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋ฉฐ ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค.

"Django์˜ ํ…œํ”Œ๋ฆฟ์„ ๋ชจ๋ธ๋กœ ํ•จ" ๋ฐ "secure"๋Š” ์ž๋™ ์ด์Šค์ผ€์ดํ”„์™€ ๊ฐ™์€ Django์˜ ํ…œํ”Œ๋ฆฟ ๋ณด์•ˆ ๊ธฐ๋Šฅ์ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋‹ค์Œ HTML์ธ ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ ์งํ›„ ๊ธฐ๋Šฅ ๋ชฉ๋ก์—์„œ:

XSS ๋ฐฉ์ง€๋ฅผ ์œ„ํ•œ ๊ฐ•๋ ฅํ•œ ์ž๋™ HTML ์ด์Šค์ผ€์ดํ”„ ์‹œ์Šคํ…œ

์„ ํƒ ์‚ฌํ•ญ์ด๋ฉฐ ๊ธฐ๋ณธ์ ์œผ๋กœ ํ™œ์„ฑํ™”๋˜์–ด ์žˆ์ง€ ์•Š๋‹ค๋Š” ๊ฒƒ์„ ์–ธ๊ธ‰ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

"๊ธฐ๋ณธ API ์‚ฌ์šฉ" ๋ฌธ์„œ ํŽ˜์ด์ง€์—๋Š” ์ž๋™ ์ด์Šค์ผ€์ดํ”„๊ฐ€ ํ™œ์„ฑํ™”๋œ ๊ฒƒ์œผ๋กœ ํ‘œ์‹œ๋˜์ง€ ์•Š์ง€๋งŒ HTML๋„ ํ‘œ์‹œ๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๊ดœ์ฐฎ์€ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ API "๊ธฐ๋ณธ"ํŽ˜์ด์ง€ ๋กœ ์ด๋™ํ•˜๋ฉด :

from jinja2 import Environment, PackageLoader
env = Environment(loader=PackageLoader('yourapplication', 'templates'))
template = env.get_template('mytemplate.html')
print template.render(the='variables', go='here')

์ฒซ ๋ฒˆ์งธ ์˜ˆ๋Š” ์‚ฌ์†Œํ•œ XSS์— ์ทจ์•ฝํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ๋žŒ๋“ค์€ ํ˜ผ๋ž€์Šค๋Ÿฌ์›Œํ•˜๋Š” ๊ฒƒ์ด ์˜ณ์Šต๋‹ˆ๋‹ค.

ํ’€ ๋ฆฌํ€˜์ŠคํŠธ์— ์ ํ•ฉํ•œ ํ›„๋ณด์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. :)

๋ชจ๋“  ์‚ฌ๋žŒ์˜ ์ฝ”๋“œ๋ฅผ ๊นจ๋œจ๋ฆฌ์ง€ ์•Š๊ณ ๋Š” ์ด ๊ธฐ๋Šฅ์„ ๋Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ทธ์— ๋”ฐ๋ผ ๋ฌธ์„œ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๊ฒŒ ๋˜์–ด ๊ธฐ์ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ์ด๊ฒƒ์„ wontfix๋กœ ๋‹ซ์„ ๊ฒƒ์ด์ง€๋งŒ ๋ฌธ์„œ ์—…๋ฐ์ดํŠธ๋ฅผ ์œ„ํ•ด ์ž์œ ๋กญ๊ฒŒ PR์„ ์—ฌ์‹ญ์‹œ์˜ค.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰