Skip to content

Commit 65fa0be

Browse files
committed
Obfuscate WHIP ids.
If the WHIP session is not authenticated, then the only thing preventing an attacker from DELETEing the session is the session URL. Since client ids are known, obfuscate the id before using it in the session URL.
1 parent 9f3bee8 commit 65fa0be

File tree

2 files changed

+84
-4
lines changed

2 files changed

+84
-4
lines changed

webserver/webserver_test.go

+20
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,23 @@ func TestFormatICEServer(t *testing.T) {
136136
})
137137
}
138138
}
139+
140+
func TestObfuscate(t *testing.T) {
141+
id := newId()
142+
obfuscated, err := obfuscate(id)
143+
if err != nil {
144+
t.Fatalf("obfuscate: %v", err)
145+
}
146+
id2, err := deobfuscate(obfuscated)
147+
if err != nil {
148+
t.Fatalf("deobfuscate: %v", err)
149+
}
150+
if id != id2 {
151+
t.Errorf("not equal: %v, %v", id, id2)
152+
}
153+
154+
_, err = obfuscate("toto")
155+
if err == nil {
156+
t.Errorf("obfuscate: no errror")
157+
}
158+
}

webserver/whip.go

+64-4
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ package webserver
22

33
import (
44
"bytes"
5+
"crypto/aes"
6+
"crypto/cipher"
57
crand "crypto/rand"
68
"encoding/base64"
9+
"errors"
710
"fmt"
811
"io"
912
"log"
@@ -37,12 +40,56 @@ func parseWhip(pth string) (string, string) {
3740
return "", ""
3841
}
3942

43+
var idSecret []byte
44+
var idCipher cipher.Block
45+
46+
func init() {
47+
idSecret = make([]byte, 16)
48+
crand.Read(idSecret)
49+
var err error
50+
idCipher, err = aes.NewCipher(idSecret)
51+
if err != nil {
52+
log.Fatalf("NewCipher: %v", err)
53+
}
54+
}
55+
4056
func newId() string {
41-
b := make([]byte, 16)
57+
b := make([]byte, idCipher.BlockSize())
4258
crand.Read(b)
4359
return base64.RawURLEncoding.EncodeToString(b)
4460
}
4561

62+
// we obfuscate ids to avoid exposing the WHIP session URL
63+
func obfuscate(id string) (string, error) {
64+
v, err := base64.RawURLEncoding.DecodeString(id)
65+
if err != nil {
66+
return "", err
67+
}
68+
69+
if len(v) != idCipher.BlockSize() {
70+
return "", errors.New("bad length")
71+
}
72+
73+
idCipher.Encrypt(v, v)
74+
75+
return base64.RawURLEncoding.EncodeToString(v), nil
76+
}
77+
78+
func deobfuscate(id string) (string, error) {
79+
v, err := base64.RawURLEncoding.DecodeString(id)
80+
if err != nil {
81+
return "", err
82+
}
83+
84+
if len(v) != idCipher.BlockSize() {
85+
return "", errors.New("bad length")
86+
}
87+
88+
idCipher.Decrypt(v, v)
89+
90+
return base64.RawURLEncoding.EncodeToString(v), nil
91+
}
92+
4693
func canPresent(perms []string) bool {
4794
for _, p := range perms {
4895
if p == "present" {
@@ -186,6 +233,13 @@ func whipEndpointHandler(w http.ResponseWriter, r *http.Request) {
186233
}
187234

188235
id := newId()
236+
obfuscated, err := obfuscate(id)
237+
if err != nil {
238+
http.Error(w, "Internal Server Error",
239+
http.StatusInternalServerError)
240+
return
241+
}
242+
189243
c := rtpconn.NewWhipClient(g, id, token)
190244

191245
_, err = group.AddClient(g.Name(), c, creds)
@@ -214,7 +268,7 @@ func whipEndpointHandler(w http.ResponseWriter, r *http.Request) {
214268
http.StatusInternalServerError)
215269
}
216270

217-
w.Header().Set("Location", path.Join(r.URL.Path, id))
271+
w.Header().Set("Location", path.Join(r.URL.Path, obfuscated))
218272
w.Header().Set("Access-Control-Expose-Headers",
219273
"Location, Content-Type, Link")
220274
whipICEServers(w)
@@ -226,8 +280,14 @@ func whipEndpointHandler(w http.ResponseWriter, r *http.Request) {
226280
}
227281

228282
func whipResourceHandler(w http.ResponseWriter, r *http.Request) {
229-
pth, id := parseWhip(r.URL.Path)
230-
if pth == "" || id == "" {
283+
pth, obfuscated := parseWhip(r.URL.Path)
284+
if pth == "" || obfuscated == "" {
285+
http.Error(w, "Internal server error",
286+
http.StatusInternalServerError)
287+
return
288+
}
289+
id, err := deobfuscate(obfuscated)
290+
if err != nil {
231291
http.Error(w, "Internal server error",
232292
http.StatusInternalServerError)
233293
return

0 commit comments

Comments
 (0)