Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Why can't we have raw UDP in JavaScript? (computerenhance.com)
72 points by adamrezich on July 5, 2022 | hide | past | favorite | 105 comments


Browsers don’t let you send raw UDP packets for the same reason they don’t let you send raw TCP packets: because devices in home and business networks implicitly trust many packets coming from inside your network. A short list of things you could do with raw TCP / UDP capabilities:

- Reconfigure a user’s router (if they have the default password)

- Print to a network printer

- Poison the home network ARP table

- Various network level DOS attacks (ICMP echo flooding attacks, etc)

- Control smart home appliances

- Access network shares

- Insanely invasive fingerprinting (including figuring out the make and model of other devices in the user’s house).

So no, it’s a terrible idea. I don’t want webpages printing things, turning my lights on and off or knowing anything else about me.

If you want the benefits of UDP through your browser, use webrtc or wait for HTTP3 or Webtransport.

The author seems to want the OS to have no knowledge or involvement in the network protocol, for unknown reasons. But they obviously think the user’s web browser is fine. From the point of view of a web application, what’s the difference?

And again - what actual benefits would there be to raw UDP access? The article is very light on specifics.


Amusingly half of those things have been modernized to run on HTTP, so browsers can already do them.


Except the very complicated 'same origin policy' makes it generally forbidden by browsers to do HTTP against local adresses.


It's not generally something browsers can do as there's no distinction about local addresses in IP (except localhost and IPv6 link-local addresses...)

Also see DNS rebinding attacks: https://unit42.paloaltonetworks.com/dns-rebinding/


CORS doesn't generally care if the final IP was resolved from localhost or example.com (or any other DNS entry), if the host doesn't have the right response to OPTIONS requests, you won't be able to communicate with it in the browser, unless your on the same IP/DNS as you're trying to talk to.


There are CORS bypass techniques, CSRF exploitation via methods which are not checked by CORS such as img tags, and common exploitable misconfigurations (and maybe you can race the preflight check with dns rebinding attack?) - but the question of local address handling playing a part was the main point of my response.

Here's some typical cases of csrf based vulnerabilities: https://seclists.org/fulldisclosure/2015/Mar/49 https://www.ciscozine.com/cisco-linksys-wag54gs-csrf-change-... https://www.arubanetworks.com/assets/alert/ARUBA-PSA-2021-01...

Remember, the S in IoT stands for security!


>OPTIONS requests

OPTIONS requests only happen for cross-origin requests. With DNS rebinding, there are no cross-origin requests, so there will be no OPTIONS requests.


But that requires you to load the page resource from that origin already, so if you're already in control of it, what would you want to do that you couldn't already?


Here's how DNS rebinding works:

1. You have the victim user open a tab to your page at attacker.com .

2. After the page loads, you change the DNS record for attacker.com to make it point to 127.0.0.1 .

3. Javascript on the page makes requests to attacker.com and can now read and interact with whatever servers are running on the victim user's machine.

Alternatively use 192.168.1.1 to attack the victim user's router.

This attack will be blocked if the victim servers check the Host request header. Often they don't.


Sites don't have to prevent browsers accessing other addresses. It's only protection against XSS, not against malicious sites.


I mean it's nowhere as bad, and for legacy stuff usually CORS/SOP helps.

New implementations that use websocket as their root (mostly for web browser compatibility) seem to take security more seriously out of the box, I use a couple apps in my day-to-day which expose APIs over Websocket and don't trust by default.

- Vtube Studio has a auth dialog that pops up on first connection you must accept before commands are executed

- obs-websocket by default requires a password to be used.

There's always outliers sadly, for example "beefweb" (Foobar plugin) has auth but it's not enabled by default.


Every one of your threat vectors listed would be prevented by appropriate browser origin policies (which already exist for existing protocols).

The only slight exception might be fingerprinting, as new APIs always extend this surface area somewhat, but not in the way you're describing (enumeration of local network devices) given aforementioned origin policies.


Browser origin policies are difficult to use to protect something that listens to an IP address rather than a host due to DNS rebinding. This can happen implicitly if the victim service doesn’t check the host header. This is already a big problem with HTTP but with UDP or raw TCP there is no host header so anything that trusted the network would be broken.


How do you enforce an origin policy on raw TCP? CORS/SOP are heavily built on HTTP semantics, and you cannot easily map this back to raw TCP sockets. Even just allowing a TCP socket to the page origin's IP address is unsafe, because it might be a CDN and allow skipping CORS for other sites.


True, it wouldn't be as straightforward as HTTP, as there would need to be new semantics (e.g. a handshake protocol for locally-cached IP allowlists or similar), but I guess my general point here is that the gp cited a large list of vectors that are all essentially the same problem & could be tackled with a single targetted (very conceivable) solution.

Any new such solution would of course come with its own incorrect-implementation dangers - increased attack surface is increased attack surface. The sibling commenter rightfully points out these are still a potential issue with HTTP (servers not checking Host). But spec-wise a solution is still very doable.


The article states that, just like microphone access, users would have to approve UDP access and it would only be allowed to a single server. I think that solves your router/printer/etc issue?

> what actual benefits would there be to raw UDP access

Author appears to want to control the whole stack. Based on their calling out HTTPS and friends as way too complex to implement. This is the HandmadeHero author afterall.

And the standard answer to “why UDP?” is “required for game dev”. TCP is a non-option for many types of games.


The connectivity to any address/host would be a bad idea, what about restricting only to the same host of document's origin.

Edit: Java's applets used to have the bog standard TCP (and UDP) and since late 90s. While Java/applets were a security nightmare, as all of them run in the same process and the impl. of SecurityManager (and its checks) was not up to the task [along with various deserialization exploits], the connectivity was not an issue.


Same-origin isn't sufficient, because an attacker who controls the DNS resolution of their domain can create a DNS record with the same origin that points to an internal target address. (And before you ask, no, the browser can't reliably distinguish internal from external IP addresses.)

If the attacker is restricted to performing HTTP requests, then things like the Host and Origin headers allow servers to defend against this. If you allow web pages to make raw TCP connections, those protections evaporate.

And I'm pretty sure that if Java applets allowed raw TCP, they would have had the same vulnerability; it's just that typical attackers weren't quite as sophisticated in the 1990s.


> And before you ask, no, the browser can't reliably distinguish internal from external IP addresses.

Why can't it?


How would it? IP has no concept of “Internal IP addressees”. There are reserved private address spaces, reserved local address spaces, and reserved public address spaces.

Both the private and public address spaces can be used for “Internal Addresses”. The fact that we frequently use NATs and private address spaces to work around IPv4 exhaustion does not mean you can expect all “Internal Addresses” to be in a private range.

The second you start using IPv6, or your in an old internet environment like a University, the DoD etc who has huge IPv4 address space, then you’ll find every machine has a IP address in a public range, there’s just firewalls preventing inbound connections, but you can’t easily detect those firewalls from the client.


>IP has no concept of “Internal IP addressees”.

IPv4 has defined 10/8, 172.16/12, 192.168/16 as site-local (or internal). IPv6 has similar concept with fec0:/10


Those v4 examples are really ambiguous addresses, orthogonal to local-ness. Same goes for ambiguous addresses used in CGNAT. More importantly, the complement: you don't know that a non-rfc1918 address isn't local. This is important because the latter is actually the definition the proposed "only allow non-local" use case would require.

(Also fec00::/10 was deprecated 15+ years ago - there are still some special prefixes like ULA but for IPv6 their usage is marginal since there's no shortage of normal address space)


The argument was about having a concept, not ensuring any address is publicly available.


Only if you completely ignore the preceding discussion about same-origin policies, and how browsers can’t provide a guarantee that a host at particular IP address is a public system or an internal-only system.

A host with an IP in a private range might always be internal, but a host with an IP in a public range isn’t always external. And as the stated goal is to avoid browsers being a trampoline to attack internal equipment, not being able to guarantee that a particular host is an internal host is problematic.


Many organizations use “real” publicly routable addresses on their hosts for IPv4 (rare) and IPv6 (common), without NAT devices. Stateful firewalls don’t require the use of NAT.



That's a defense-in-depth measure; it can't be relied on. The exact same attack can be used against targets on a corporate network that doesn't use the RFC1918 address ranges.


I wouldn't associate those mainly with corporate networks. The prevalence of RFC1918 use is an artifact of IPv4 and address shortage. IPv6 usage is already at 40% today.

Also hosts are increasingly multihomed, devices are likely tohave 2-3 network interfaces, with v4/v6 addresses for each. VPNs are run in "split tunnel" mode where some traffic goes via VPN and some not, so both un-tunneled and tunneled traffic is allowed simultaneously, etc.


Because you could be (and many high-value targets likely are) using your own IP address space "internally", rather than RFC1918. (Plus, IPv6.)


Actually Java resolved the host to the same IP to prevent that type of attacks... which has other issues.


HTTP has Host and Origin. Raw TCP/UDP do not. “The same host of document’s origin” can host any number of completely unrelated websites/services thanks to vhosting.


I think the connectivity issues were simply overshadowed by the deficiencies of the SecurityManager.


In TFA, it says

> If DDoS was the concern, just require that UDP packets be sent exclusively within the same domain as the originating code.

So you couldn't do any of these things.

> And again - what actual benefits would there be to raw UDP access? The article is very light on specifics.

It seems like writing game netcode without setting up a WebRTC server should be reason enough.


Restricting origins doesn’t work thanks to a fun little trick called DNS rebinding. Let’s say you get the user to browse your site, say, attacker.com. They lookup your DNS and see that it’s 1.2.3.4, with a TTL of (say) 5 seconds.

Five seconds later, the user’s DNS cache entry expires. Your page triggers a new request to attacker.com. Since the TTL has expired, they do another DNS lookup - and you serve them a different IP address, say, 192.168.1.1. Now they make a new request to that IP believing that they’re still accessing attacker.com.

With HTTP requests there’s at least the possibility of detecting these attacks via the Host header (even if that doesn’t usually happen in practice). With raw UDP, however, the attacking packets would be indistinguishable from legitimate ones.


This could be resolved by having the browser cache the IP and refresh it for child operations. Sure, this is a change in current behavior - but for a new feature like UDP, or arbitrary TCP, it could work.


As others have pointed out caching the DNS past the TTL is it’s own security problem.

I think the fix is actually to disallow resolution when the TTL is too short (eg <1 hour) and refusing new outbound requests once the IP address changes without a refresh of the page. However, I’m not a security / network expert so there may be a critical flaw in that idea.


Have a page load up a script from <nonce>.relevantdomain.tld, once the script sends back a packet to <nonce>.relevantdomain.tld, have the dns settings change subdomain to 192.168.0.1, and then etc

the war between safe things and unsafe things is endless, so we shouldn't be adding a massive unsafe thing and then bodging patches onto it to make it "safer" than completely unsafe


> It seems like writing game netcode without setting up a WebRTC server should be reason enough.

this begs the question - is the browser really the right platform for a game where netcode like that is needed?

Why make the browser even more complex, when the original design of it is meant to only display documents? If we keep going down this road, you'd end up with an operating system inside the browser.


> If we keep going down this road, you'd end up with an operating system inside the browser.

Arguably, we're already there. I stopped pretending the web wasn't going to be the common platform of the future when WebUSB dropped and I learned you can root a Nintendo Switch from Chrome OS. Without the Linux part.

If you build something today, without too many resources backing you up, and you want it to run anywhere, you build something that resembles a PWA with Electron wrappers. (resembling because it could also be something like Flutter).


> when WebUSB dropped

You mean when Google implemented it in their EEE fork of the web.


If we're going to have games and audio on the web, which we do, we could at least have them work without mountains of additional latency or WebRTC servers.

I would also like it if web sites would display documents, allow the browser's "find" feature to work, and not use "responsive UI" to delete the form that I'm halfway done filling out when I resize my window, but I don't think my preferences have much weight here.


WebRTC is peer-to-peer so there's no additional network latency from the protocol. There's the TURN fallback for when the participants can't reach each other, in which case bouncing through a proxy is the best you can do anyway.

(If some implementations have high processing latency on top of the network latency, this can be fixed without changing the protocol).


While I may personally agree with your line of thinking there, we are about 15 years too late to argue that point I think.


> when the original design of it is meant to only display documents?

Ship sailed, horse out of barn, etc etc on this point.


> this begs the question - is the browser really the right platform for a game where netcode like that is needed?

Yes, it works pretty well using established technologies in the browser already.


DDOS is essentially the exact opposite of what the parent comment is talking about.


Can you explain how "require that UDP packets be sent exclusively within the same domain as the originating code" does not address any of that comment's concerns, or are you just nitpicking?


evil.example.com can easily set up a subdomain such that 192-168-2-44.home.evil.example.com resolves to 192.168.2.44, so requiring that UDP packets be sent exclusively within the same domain as the originating code doesn't help at all.


That wouldn't work, the same way CORS can't be bypassed that way. It was to be the exact same origin.


CORS work because the target is HTTP and exposes permissions in headers.

There is no HTTP headers for raw UDP.


You can rebind the exact same origin then.


Same domain is pretty meaningless until all browsers mitigate DNS rebinding, which as far as I know they still don't. And even that would presumably only help with private IPs.


Oops, I misunderstood "same domain", sorry.


Hide it under prompt and that's about it. Alternative is that user will install some sketchy exe file which will do the same, but without any prompts. Browser could make it more secure.


Small nit, you cannot do ICMP with TCP or UDP.


Also ARP isn't over TCP or UDP.


ARP and ICMP are protocols separate from TCP/UDP.


"If you were a large company with significant academic and engineering resources, you might instead want to design your own private secure protocol that:

    Uses encryption you control, so it cannot be bypassed by hacking the certificate authority,

    Uses UDP to avoid having OS connection state on the server side, and

    Uses a well-designed, known packet structure to improve throughput and reduce security vulnerabilities from HTTP/TLS parsing."
I think at this point they would have done well to explain why WebRTC data channels are not usable or incrementally fixable for the purpouse. It's SCTP tunneled in DTLS over UDP. Missing is just the home brewed encryption requirement which would generally be a no-no in security engineering practices.


Fully forgetting that what ever they roll has to have state on server side, just this time in the server software... Not solving too much...

And then forgetting the nice stuff TCP offers like in-order guaranteed delivery...

Both which is needed for most sensible encryption schemes. And doesn't really get away from needing a PKI... Or then you could just grab a connection before it is formed. If you can MitM HTTPS you can MitM anything else...


> Missing is just the home brewed encryption requirement which would generally be a no-no in security engineering practices.

Maybe if the "large company" he talked about was the NSA/FSB/MI6/Chinese Intelligence it would make sense.


one half of me is crying and clapping knowing it'll let me do more cool web stuff. The other is cowering in fear, knowing full well this is just one more step in the web cabal's master plan to run a full virtual pentium 3 with soundblaster and ATI card just so i can read the news



Can't believe there's no Windows ME


Maybe if you don’t like HTTP you shouldn’t be trying to implement whatever it is you’re trying to do in a web browser ?


You either target the web browser, or have to deal with the Stores (Play Store, App Store, Steam, ...).


Or, hear me out, ship a binary/package from your own website.


Unfortunately that restricts your platforms a lot, and even for the platforms that this reasonably works for, requires a lot of porting and testing effort (or you need to settle for a single narrow target platform).


How does that restrict you more than targeting a specific store like App Store, Play Store or Steam?


The point of comparison was targeting the web.


Good luck shipping a binary for iOS from your own website :-)

That's doable on Android, though security sensitive people won't install a random APK found on the web.

And signing a binary on windows is doable, but rather expensive.


You do its called the webrtc data channel.


Yeah and its an absolute PITA to set up, and a nightmare from the ops perspective, I'm not even sure what even are you supposed to use on the server side.


The client is fairly easy, imho. Did you mean setting up the infrastructure? Because yeah, hard to do properly


Yeah the infra (NAT traversal is hell), and I'm unsure how I would hook something like that up to a web server like Flask.

Either you get a proper WebRTC implementation like Google's which is huge and does a ton of other stuff, or you talk to another browser peer to peer.


Or use something specific like libdatachannel https://libdatachannel.org/

If you’re using WebRTC data channels in a client server config then infra is no more complex than a regular setup because the server will almost certainly have an external facing IP address.

People should really try using WebRTC as well because you can get the full pipeline setup for a toy demo in a couple of slow days. I did whilst also writing my own signalling server in Go without having used Go before!

It’s certainly not any more complex than rolling all the stuff the article is talking about on top of raw UDP.


If you're doing nodejs you can just `npm i wrtc` and get the same api as in the browser.


I see just too many issues. Including things like NAT having to guess what to do with your unique UDP packets and then some users complaining why your site doesn't work...

Also generally rolling your own anything isn't that great idea from interoperability to security concerns. And just imagine this multiplied to everyone copying some blog post who knows from where...


As a person who worked on the original web socket spec - it's because many networks run "deep packet inspection" routers, etc (to protect the network or some such), and those routers are almost universally badly written.

There have been many cases where those routers can be compromised by sending specially crafted content. That's apparently something that hit Java applets, presumably ActiveX (though with activex that is surely on the lower end of the security issue spectrum?).

Because of the nature web sockets providing much more control of the actual bytes on the wire from a browser it was necessary to "encrypt" the bytes. The goal isn't to secure the content, it's to make it so attacker JS can't control the byte content - the "encryption" key is literally prepended to the data being sent so anyone sniffing network traffic can "decrypt" the WS data.* From JS running on a webpage this is completely transparent (or is that opaque?) because obviously if the web content knew the key material they could modify their data to get the correct bytes again.

This is one of the things people forget when asking for browsers to provide features: it's not just "what can I use this for?" but "what can a malicious actor do with this?". Because the threat model for a browser is not the same as an app - browsers can be trivially made to load and run arbitrary JS - Ad networks are notorious for it, but unending websites make it possible. One of the things that make the web a great and amazing thing is that I can go to any website, and not worry about it doing anything to my computer (and with the exception of chrome) browsers also try to make malicious behaviour like spying on you hard as well. Yes there are security bugs that can be exploited, but there's a difference between a security bug that can be fixed, and a literal specified attack surface. *

* To actually protect data you should be using TLS, but you knew that right?

* Fun story, there was a version of the SVG standard (or a draft? it was a long time since I was on that committee) that provided raw socket access


We also don’t have raw TCP or ICMP in a web browser. It’s probably for very similar reasons.

My guess is that there is no strong enough demand for such low levels network protocols in major web browsers. It is not worth the risks, and the costs, and the complexity.

We have HTTP, WebSockets, and WebRTC.


raw ICMP requires root permissions. For instance 'ping' runs with elevated/root permissions. "Raw" TCP is a mystery, though. WebScokets are like, ehh, fine, whatever - it's a framed stream protocol.


We have raw USB in a web browser. I can access my USB security token from the browser right now. I can access my raw keyboard USB connection from the browser right now. How is network access have less demand that raw USB? Even simple thing like mail client can't work in browser without using third-party server (and sending your password to that server). Same about ssh client, etc. A lot of apps are currently impossible in browser or security nightmare because of this artificial restriction.


Raw USB is a Chrome-only extension, Safari and Firefox don't support it because it's an awful idea. Even so, it's much easier to make a meaningful permission dialog for USB than for a TCP or UDP connection. With USB there's a limited set of devices you can connect to, and they somewhat human-readable names or vendor IDs that can be translated into names, and there's no way to do something like a DNS rebinding attack with them since the browser can detect when the device is unplugged.

It is entirely possible to make a secure SSH or IMAP client in the browser, just proxy the encrypted data and do TLS or the SSH protocol in Javascript.


This seems more of a rant then a well thought out technical analysis.


I suppose one could do this but then each OS will have to set flags on the browser executable and there is a whole can of security worms that opens. In Linux one could use

    sudo setcap cap_net_raw,cap_net_admin=eip /usr/lib/firefox/firefox
This could and probably should be automated in firejail or bubblewrap rather than the installer. Does this exist for Windows or Mac?

If using AppArmor or SELinux rules would need to be created unless Firejail is managing the rules on the fly. Then the browser would need to test for the capabilities and give some meaningful log in the web console because a way to debug this is considered good ettiquite. Then one would need a library or API in the browser that knows how to open raw sockets which means getting all the major browser developers to agree on a standard.

Thinking long term there are going to be security auditing tools that will detect the binary has non standard setcap modes meaning that browser developers would have to reach out to all these companies to get on the same page otherwise corporations will have some knee-jerk reactions.


UDP is not a privileged protocol. You don't need any capabilities to speak UDP. It's used by web browsers already for HTTP/3 as TFA mentions.

But also, apps needing additional capabilities is rather common and handled by most any package manager that's going to be providing you a browser. Chrome in various configurations ships with a `setuid` binary to implement their sandbox, for instance.


UDP is not a privileged protocol.

True, but a raw socket does require privs.


Wouldn’t you rather control these capabilities based on the origin domain, through the browser itself?


I would. That would be up to the library. The things I mentioned are the foundation required for the rest of that to work.


The point is moot at best; how many layers of security does browsing FB and posting pictures on Instgram need ?


Casey is a game developer, his use-cases are probably games targeting the browser and how it would be possible to improve their communication with external servers.


*is a game developer with a particular focus on "RETVRN TO TRADITION" where anything that isn't super lean-and-mean is bloated and inefficient and ridiculous, and only exists because web developers are misguided, miseducated, etc. WebRTC could do what he wants, but then he'd have to build a WebRTC->pure UDP gateway.

I can sympathize, but, even in the original discussion on Twitter it's clear he is ill-informed of the relevant security fiascos that made all these complicated protocols necessary, or the messy legacy constraints they must operate under. Infrastructure is not magic, and tying together e.g. application-level concepts with DNS-level concepts would be a recipe for misery IRL.

I also find it funny he considers the string/text-based parts of HTTPS to be unworthy of a secure protocol, when in fact, the whole reason that approach is considered so dangerous is because of programmers with his attitude who underestimated the difficulty of secure parsing. The niche of "LangSec" is all about solving this problem properly by treating input processing as a formal parsing problem with formal grammars.


Is it really necessary to attack Casey with this two bits sarcasm? You can disagree and still be polite for the sake of me taking you seriously, if not for his.


It is really PITA. We're making a service which works with various devices. Most devices work over serial, so WebSerial makes it painless. But there are some devices which work over TCP/UDP. So we have to install our software to user computer, install our CA certificate into user store just to be able to talk to TCP/UDP from the browser. Much security.


Unless you support Safari you don't need to add a cert, http connections to localhost are considered secure connections in Firefox and Chrome and basically every browser besides Safari, so you can connect to them from an HTTPS site with no mixed content issues.


Thanks!


Find "SOP" "same origin": 0 hit.


If this for some reason gets momentum, please do IP, or at least both TCP and UDP.


But nooo, I also want to send raw Ethernet and IEEE 802.11 frames from the browser! /s

There's always a baby that will cry for more. People have been begging for raw socket access and other "I just can't get my head around this"-shortcuts since they wrote their first "Hello World!", TODO-list or guestbook API. There isn't really anything you couldn't solve with the things there are now in every browser. What would UDP bring to the table other than more work to deal with it in that regard? This is nothing about innovation or technical limitations. This is just another case of "B- b- but I want it my way because that's how I always did it! :(".


what is the impetus for your over-the-top characterization?


Ah, the "wave off as strawman"-argument. HN's favorite meme. (I guess that's why you edited it out?) Any real counter arguments, though? Even the article fails to make a point other than "UDP can be as secure as HTTPS!" which no one really ever argued about other than the article writer itself to make a synthetic point about it.


I edited out the word "strawman" almost immediately after posting since I (correctly) realized it could become a fixation point in your response that you would use to dodge the question.


Funny you mention dodging questions. I mean you could have just given one instead of posting that and even having to edit it afterwards.


Why can't we send UDP over Cellular data?


Small point of order, but shouldn't this be retitled to, "No really, why can't we have raw UDP in the browser?" since you definitely can do UDP in "JavaScript"?[0]

[0] https://nodejs.org/api/dgram.html


At this point the primary operating system globally is Chrome. It is an overlay operating system, but still should go in that category.

The web platform has APIs for just about everything else at this point. Even USB.

The main reason we don't have UDP, aside from some security challenges, is probably that it actually really opens up possibilities for decentralization via direct P2P connectivity, which could rapidly decrease the control and profits of the big internet companies. Yes there is WebRTC but that is not quite the same and specifically is scoped inside of the browser.

Ordinary UDP support would invite things like libp2p to be ported. Then people bringing in entire decentralized applications using web assembly.. and finally people will eventually realize they don't need a bloated overly complex browser and start using lighter weight platforms built in web assembly extended with things like UDP and cryptocurrency support etc.

That will also pave the way for script/app free information browsing as it becomes popular to break out of the Google platform.

So there are billions of reasons for Google to suppress UDP. They would never admit it though.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: