PyScript์™€ Security ๐Ÿ๐Ÿ—ก

์ตœ๊ทผ PyCon US 2022์˜ ๋ฐœํ‘œ ์ค‘ PyScript๊ฐ€ ๊ณต๊ฐœ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. PyScript๋Š” HTML์—์„œ Python ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ œ๊ณตํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ์ตœ๊ทผ ์—„์ฒญ๋‚œ ๋ฒ”์šฉ์„ฑ๊ณผ ๋‚ฎ์€ ๋Ÿฌ๋‹ ์ปค๋ธŒ๋ฅผ ๊ฐ€์ง„ Python์ด ์›น์œผ๋กœ ํ™•์žฅํ•˜๋Š” ๋ถ€๋ถ„์ด๋ผ ๊ด€์‹ฌ๋„ ๋งŽ๊ณ  ๋ง๋„ ๋งŽ์Šต๋‹ˆ๋‹ค.

HMLT ๋‚ด๋ถ€์—์„œ ์ฝ”๋“œ๋ฅผ ์“ฐ๋Š” ๋ฐฉ์‹์ด PHP์™€ ๋ญ๋ผ ๋‹ค๋ฅด๋ƒ๋ž€ ์ด์•ผ๊ธฐ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜คํžˆ๋ ค ์‹œ๋Œ€๋ฅผ ์—ญํ–‰ํ•œ๋‹ค๋Š” ์ด์•ผ๊ธฐ๋„ ๋ดค๋˜ ๊ฒƒ ๊ฐ™๋„ค์š”.

๋””์ž์ธ ํŒจํ„ด์ด๋‚˜ ์ฝ”๋“œ์— ๋Œ€ํ•œ ๋‚ด์šฉ์€ ๊ฐœ๋ฐœ์ž๋ถ„๋“ค์ด ๋งŽ์ด ์‹ ๊ฒฝ์“ฐ์‹ค ๋‚ด์šฉ์ด๊ณ , ์šฐ๋ฆฌ๋Š” ๋ณด์•ˆ ์—”์ง€๋‹ˆ์–ด๋ง์ด๋‹ˆ ๋ณด์•ˆ์ชฝ ๊ด€์ ์—์„œ๋„ ํ•œ๋ฒˆ ์‚ดํŽด๋ด์•ผํ•ด์„œ ์š” ๋ฉฐ์น  ๊ฐ€๋ณ๊ฒŒ ๊ณ ๋ฏผํ•ด๋ณด๊ณ  ๊ธ€๋กœ ์ž‘์„ฑํ•ด๋ด…๋‹ˆ๋‹ค.

PyScript

PHP์—์„œ <?php ?> ๋ฌธ๋ฒ•์œผ๋กœ PHP ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•˜๋˜ ๊ฒƒ๊ณผ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค. <py-script> ํƒœ๊ทธ๋ฅผ ์ž‘์„ฑํ•œ ๋ถ€๋ถ„์€ python ๋ฌธ๋ฒ•์œผ๋กœ ๋™์ž‘ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

<html>
    <py-script> print('Hiiii') </py-script>|
</html>

์‹ค์ œ js ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊นŒ์ง€ ํฌํ•จํ•œ ๋‚ด์šฉ์€ ์•„๋ž˜์™€ ๊ฐ™๊ฒ ๋„ค์š”.

<html>
    <head>
        <link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
        <script defer src="https://pyscript.net/alpha/pyscript.js"></script>
    </head>
    <body>
      <py-script> print('Hello, World!')</py-script> 
    </body>
</html>

How to work

PyScript๋Š” Pyodide์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ฐœ๋ฐœ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์›น์–ด์…ˆ๋ธ”๋ฆฌ(WASM)๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ธŒ๋ผ์šฐ์ €์™€ Node.js๋ฅผ ์œ„ํ•œ ํŒŒ์ด์ฌ ๋ฐฐํฌํŒ์ž…๋‹ˆ๋‹ค.

์ฐธ๊ณ ๋กœ WASM์€ ์ œ๊ฐ€ ์˜ˆ์ „์— โ€œ์›น ์–ด์…ˆ๋ธ”๋ฆฌ(Web Assembly)๋Š” ์–ด๋–ป๊ฒŒ ๋ณด์•ˆ ์ทจ์•ฝ์  ๋ถ„์„์„ ํ• ๊นŒ์š”?โ€œ๋ž€ ๊ธ€์„ ์ž‘์„ฑํ–ˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ WASM์ด ๋ญ”์ง€, ์–ด๋–ป๊ฒŒ ๋ณด์•ˆ ํ…Œ์ŠคํŒ…์„ ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ๋ณด์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ž์„ธํ•œ ๋™์ž‘์„ ๋ณธ๊ฑด ์•„๋‹ˆ์ง€๋งŒ ์–ด์จŒ๋˜ PyScript๋Š” WASM ๊ธฐ๋ฐ˜์œผ๋กœ Python(cPython)์„ ๋™์ž‘ํ•˜์—ฌ ์‹คํ–‰ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Elements

Script

<py-script>๋Š” ์›น ํŽ˜์ด์ง€ ๋‚ด์—์„œ ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ํŒŒ์ด์ฌ ์ฝ”๋“œ๋ฅผ ์ •์˜ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ํ•ด๋‹น Element๋Š” ํŽ˜์ด์ง€์— ๋ Œ๋”๋ง๋˜์ง€ ์•Š๊ณ  ๋งˆ์น˜ <script> ํƒœ๊ทธ์™€ ๊ฐ™์ด ๋กœ์ง๋งŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. src ์†์„ฑ๋„ ๋น„์Šทํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

<py-script src="/app.py"></py-script>

Repl

ํŽ˜์ด์ง€์— ์ฝ”๋“œ ํŽธ์ง‘๊ธฐ๋กœ ๋ Œ๋”๋ง๋˜๊ณ  ์‚ฌ์šฉ์ž๊ฐ€ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋Š” REPL์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

Examples

  • https://github.com/pyscript/pyscript/tree/main/pyscriptjs/examples

Security

์ œ๊ฐ€ ์œ„์—์„œ PyScript๊ฐ€ WASM ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค๊ณ  ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ฒฐ๊ตญ ๋‹จ์ˆœํžˆ ๋ฌธ๋ฒ•๋งŒ ๋งคํ•‘์‹œํ‚จ๊ฒŒ ์•„๋‹ˆ๋ผ ์‹ค์ œ๋กœ Python์ด ๊ตฌ๋™๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉ์ž์—๊ฒŒ ํŽ˜์ด์ง€์— ๋Œ€ํ•œ ์ œ์–ด๊ถŒ์„ ์ฃผ๊ฑฐ๋‚˜ XSS ๋“ฑ์˜ ์ด์Šˆ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ์ข€ ๋” ๋ฆฌ์Šคํฌ๊ฐ€ ์ฆ๊ฐ€ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

Sensitive data exposure

Python ์ฝ”๋“œ๊ฐ€ FE๋‹จ์—์„œ ์‚ฌ์šฉ๋œ๋‹ค๋ฉด ์‹œํ์–ด ์ฝ”๋”ฉ์—์„œ๋„ ๊ด€์ ์ด ์•ฝ๊ฐ„ ๋ณ€ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋ณดํ†ต Secret์ด๋‚˜ Key ๋“ฑ์˜ ์ •๋ณด๋Š” ๋ฐฑ์—”๋“œ์—์„œ ์ฒ˜๋ฆฌํ•˜๋„๋ก ํ•˜์ง€๋งŒ, FE์—์„œ ์‰ฝ๊ฒŒ Python ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ ๋ถ„๋ช…ํžˆ ์ผ๋ถ€ ๊ฐœ๋ฐœ์ž๋Š” ์ค‘์š”ํ•œ ์ •๋ณด๋ฅผ PyScript ๋‹จ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

๋งŒ์•ฝ ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉ๋˜๋Š” ๊ฒฝ์šฐ ์‰ฝ๊ฒŒ ์ค‘์š”์ •๋ณด๋ฅผ ํƒˆ์ทจํ•  ์ˆ˜ ์žˆ์–ด์„œ ์—ฐ์‡„์ ์ธ ๊ณต๊ฒฉ์œผ๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Leak without browser policy

์ฝ”๋“œ ๋™์ž‘์ด WASM ๋‚ด๋ถ€์—์„œ ๋ณ„๋„๋กœ์˜ ๋ฐ”์ด๋„ˆ๋ฆฌ๋กœ ๋ฐœ์ƒํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ์กด Browser์—์„œ์˜ ๋ณด์•ˆ ์ •์ฑ…๊ณผ ํ†ต์ œ ๋กœ์ง์„ ์ ์šฉ๋ฐ›์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ณต๊ฒฉ์ž๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๋นผ๋Œ๋ฆฌ๋Š”๋ฐ ์žˆ์–ด์„œ CSP ๋“ฑ์œผ๋กœ ์ œํ•œ์„ ๋ฐ›๋”๋ผ๋„, PyScirpt ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด์„œ ์šฐํšŒํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ์œ ์ถœํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

DOS

Javascript ์ฒ˜๋Ÿผ ๋ธŒ๋ผ์šฐ์ €์— ๋‚ด์žฅ๋˜์–ด ๋ฐ€์ ‘ํ•˜๊ฒŒ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ WASM์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ตฌ์„ฑ์— ๋”ฐ๋ผ ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ํด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฒฐ๊ตญ ์ด๋ฅผ ์ž˜ ์ด์šฉํ•˜๋ฉด ๊ฐ„๋‹จํ•œ ์ฝ”๋“œ๋กœ๋„ ์ถฉ๋ถ„ํžˆ ๋‹จ์ผ ๋˜๋Š” ๊ด‘๋ฒ”์œ„ํ•œ ์‚ฌ์šฉ์ž๋ฅผ ๋Œ€์ƒ์œผ๋กœ DOS๋ฅผ ์ผ์œผํ‚ค๊ธฐ ์ถฉ๋ถ„ํ•˜๋‹จ ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

XSS

PyScript๋ฅผ ํ†ตํ•ด์„œ XSS ์šฐํšŒ ํŒจํ„ด์„ ์ถฉ๋ถ„ํžˆ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ Deny-list ๊ธฐ๋ฐ˜์˜ ๊ฒ€์ฆ ๋กœ์ง์ด๋ผ๋ฉด ๋‹น์—ฐํžˆ <py-script> ๋“ฑ์€ ํŒจํ„ด์— ๋น ์ ธ์žˆ์„ ํ™•๋ฅ ์ด ๋†’์•„์„œ ํƒœ๊ทธ ๊ธฐ๋ฐ˜์œผ๋กœ๋„ ์ถฉ๋ถ„ํžˆ ์šฐํšŒํ•  ์ˆ˜ ์žˆ๊ณ , ๋งŒ์•ฝ ์ฃผ์š” ๊ณต๊ฒฉ ๊ตฌ๋ฌธ ๋“ฑ์œผ๋กœ Escape ์ฒ˜๋ฆฌํ•œ๋‹ค๊ณ  ํ•ด๋„ Python ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ์‰ฝ๊ฒŒ ๋‚œ๋…ํ™”ํ•˜์—ฌ XSS ๋Œ€์‘ ๋กœ์ง์„ ๋ฌด๋ ฅํ™” ์‹œํ‚ฌ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

Bypassing Sandbox

๊ธฐ๋ณธ์ ์œผ๋กœ os ๋“ฑ ์—ฌ๋Ÿฌ ๋ชจ๋“ˆ์„ ๋กœ๋“œํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— Command Execute์˜ ๊ฐ€๋Šฅ์„ฑ ๋˜ํ•œ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋งŒ Pyodide์ด ์ด๋Ÿฌํ•œ ๋ณด์•ˆ ๋ฌธ์ œ๋Š” Sandboxing ๋“ฑ์˜ ๊ธฐ์ˆ ๋กœ ํ†ต์ œํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜๋„ Pyodide์—์„œ ์ด๋Ÿฌํ•œ ๋ณด์•ˆ ๋กœ์ง์— ๋Œ€ํ•œ ์šฐํšŒ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ ๋‹จ์ˆœํžˆ ํ•ด๋‹น ๋ชจ๋“ˆ๋งŒ์˜ ๋ฌธ์ œ๊ฐ€ ์•„๋‹Œ PyScript์—์„  ๊ด‘๋ฒ”์œ„ํ•œ ์‚ฌ์šฉ์ž๋ฅผ ๋Œ€์ƒ์œผ๋กœ Command Execution ๋“ฑ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์–ด์„œ ๋ฌธ์ œ๊ฐ€๋  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ํ˜น์‹œ๋‚˜ PyScript๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด ์ด์ ์„ ๊ณ ๋ คํ•˜๊ณ  ๋ณด์•ˆ ์ด์Šˆ์— ๋Œ€ํ•ด์„œ ๋ฏผ๊ฐํ•˜๊ฒŒ ์ฒดํฌํ•˜๊ณ  ์žˆ์–ด์•ผํ•  ๊ฒƒ ๊ฐ™๋„ค์š”.

Etc

์ด์™ธ์—๋„ WASM์— ๋Œ€ํ•œ ๋ณด์•ˆ ์ด์Šˆ๋ถ€ํ„ฐ ๋กœ์ง์ ์ธ ๋ถ€๋ถ„, ํŒŒ์ด์ฌ ์ฝ”๋“œ์ƒ์˜ ๋ฌธ์ œ๋“ฑ์œผ๋กœ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์ด์Šˆ๊ฐ€ ๋‚˜ํƒ€๋‚  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค ๐Ÿ˜ญ

References

  • https://pyscript.net
  • https://twitter.com/mariatta/status/1520439766130454530
  • https://www.hahwul.com/2018/10/06/hacking-security-analysis-web-assembly/