BitBang CLI Part 2: What a WebRTC Reverse Shell Looks Like From the Wire
Lab-only framing note up front: this is a design and detection analysis, not an exploitation walkthrough. The commands shown are the same bitbang serve/connect/cp usage from Part 1, the tool’s own documented normal operation, run against machines already under test with authorization. Nothing here is a novel technique against a specific vulnerability.
Pivoting and Tunneling Part 1 framed pivoting as a routing problem: something on the far side has a route you don’t, and you want traffic to travel through it. Part 2 covered Chisel wrapping a reverse SOCKS tunnel in HTTP, and Part 3 covered ligolo-ng doing the same thing at the TUN-interface level, no proxychains required. bitbang-cli solves the same “no inbound port needed” problem with a genuinely different transport, and one detail changes the usual calculus: unlike Chisel or ligolo-ng, it needs no attacker-run listener at all. Both of those tools still require standing up a server somewhere reachable, then getting the target to dial out to it. bitbang-cli’s model is the reverse: the compromised host runs bitbang serve, a free public signaling server (bitba.ng) brokers the introduction, and the operator connects to a URL from anywhere, no infrastructure of their own required.
Why this is worth treating as a pivoting primitive
Strip the legitimate use case (remote-accessing your own Raspberry Pi from a phone) down to the mechanics and it’s the same shape as every tool in the Pivoting and Tunneling series: an outbound-initiated channel that survives NAT, CGNAT, and an egress policy that only permits ordinary outbound web traffic. bitbang serve needs nothing more than outbound access to bitba.ng on 443, the same bar Chisel clears by wrapping its tunnel in HTTP. It clears that bar with less setup than either existing tool in this series: no listener to provision, no domain to register, no TLS certificate to manage. Run one command, get a URL.
What that URL actually grants matches everything bitbang serve was built to grant, which is the point: a full interactive shell, a file browser with optional upload, and an HTTP/WebSocket proxy into whatever the host can reach on its LAN. That last piece is the pivoting-relevant one. A bitbang serve proxy pointed at nothing in particular lets the connecting party type a LAN address into a browser and reach it, from anywhere, through a connection that never needed an inbound port on either end.
What the operator sees, and what the defender sees
This is where Part 1’s live testing pays off directly. The listener’s own log for a real connection looked like this:
Connection request from 5NR9bGVISjYWYjY7HvJSVQ_ed70947a (browser_ip=203.0.113.42)
Connection connected for 5NR9bGVISjYWYjY7HvJSVQ_ed70947a via DIRECT in 471ms (local=host remote=host)
Connection data channel opened for 5NR9bGVISjYWYjY7HvJSVQ_ed70947a
Shell started: argv=[whoami] pty=false
Shell exited: argv=[whoami] code=0
That’s the view from the compromised host, which is also the view an EDR agent or a host-based log shipper gets, if one is watching the process at all. A few real, testable signals fall out of it:
| Signal | What it looks like |
|---|---|
| Process execution | A statically linked, unsigned Go binary spawning a shell or PTY, with no parent relationship to a normal remote-access tool. Its own identity directory (~/.bitbang/, an RSA identity.pem, devices.json) is a stable filesystem artifact even if the binary itself is renamed. |
| Outbound DNS/TLS | A DNS lookup and outbound TLS 443 connection to bitba.ng (or a self-hosted equivalent’s -server value) that precedes a WebRTC/DTLS handshake rather than an ordinary HTTPS request-response pattern. |
| ICE/STUN/TURN traffic | WebRTC’s negotiation is a recognizable protocol family on the wire, distinct from plain TLS, whether or not the eventual data path goes direct or through a relay. |
| No inbound listener | The one signature every “block inbound, permit outbound” heuristic relies on doesn’t apply here, same as it doesn’t apply to Chisel or ligolo-ng, which is exactly why Part 6’s hardening checklist leans on egress control rather than inbound firewalling. |
The one point genuinely worth flagging as different from Chisel: bitbang-cli’s default signaling infrastructure is a single, named, non-rotating domain. Chisel’s server can be stood up anywhere, on any domain, which is exactly why domain or IP-based blocking of Chisel infrastructure doesn’t generalize. bitba.ng is a known quantity today. An organization that has no legitimate reason for any host to reach it can add it to an egress deny list outright, the same category of control as FortiGuard’s botnet C2 domain rating already applied to known-bad infrastructure elsewhere on this site. That control stops working the moment someone self-hosts the signaling server on their own domain, which the project explicitly supports, so it’s a real but narrow mitigation, not a durable one.
Where it’s weaker than Chisel and ligolo-ng today
Part 1 already flagged this honestly from the project’s own roadmap: no TCP port forwarding yet. serve proxy is HTTP/WebSocket only. That means bitbang-cli, as it stands, can’t reach a raw TCP service the way ligolo-ng’s TUN interface or even plain SSH -L 1433:10.10.40.10:1433 can. It’s a real shell and a real file transfer channel, but not yet a general-purpose tunnel for arbitrary protocols. Against a target like FIN-DB01 from the original Pivoting and Tunneling lab (MSSQL on 1433, no HTTP surface at all), bitbang-cli in its current form has nothing to offer, where Chisel and ligolo-ng both do.
That gap narrows the moment -L-style TCP forwarding ships (it’s explicitly on the roadmap), and it’s worth revisiting this series’ comparison once it does.
Comparison, updated
SSH -R | Chisel | ligolo-ng | bitbang-cli | |
|---|---|---|---|---|
| Needs a client on target | Yes (OpenSSH) | Yes (binary) | Yes (binary) | Yes (binary) |
| Needs attacker-run infra | No (just a reachable box) | Yes (Chisel server) | Yes (ligolo proxy) | No (public signaling default) |
| Raw TCP forwarding | Yes | Yes | Yes | Not yet |
| Transport | SSH/TCP | HTTP(S) | Custom over TLS | WebRTC/DTLS |
| Fixed, blockable infra domain | N/A | No (self-hosted, varies) | No (self-hosted, varies) | Yes, by default (bitba.ng) |
The practical read: bitbang-cli is the lowest-setup option of the four for getting an interactive shell and LAN web-app access out of a segmented host, and the easiest of the four to block wholesale today, precisely because its default infrastructure is a single known domain rather than operator-chosen. Whether that tradeoff holds depends entirely on whether self-hosting the signaling server becomes common practice as the project matures.
Closing
The same “no inbound port, no config on target” properties that make bitbang-cli genuinely useful for legitimately reaching your own homelab are the properties that put it in this series rather than only in Part 1. Nothing about that is unique to bitbang-cli. It’s the same story DNS tunneling told about iodine and dnscat2, and the same story Chisel and ligolo-ng told before that: reach for the tool shaped like whatever the egress policy still allows, and defend by watching what leaves the network rather than trusting what’s blocked from coming in. Egress filtering, TLS inspection, and a deny list for signaling infrastructure with no legitimate business use, the same checklist Part 6 closed this series with, still applies here without modification.