From a14f5d08c264637639d518267a1397e137823fcf Mon Sep 17 00:00:00 2001 From: Rose Hogenson Date: Mon, 10 Nov 2025 22:31:03 -0800 Subject: Validate the QR code Since the qr code is generated by a 3rd party dependency that I probably won't update, let's make sure to only pass it trusted input. --- roseh.moe.go | 24 +++++++++++++++++++----- templates/wormhole.html.template | 2 +- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/roseh.moe.go b/roseh.moe.go index f5141f3..213e44f 100644 --- a/roseh.moe.go +++ b/roseh.moe.go @@ -191,6 +191,7 @@ var ( type wormholeTemplateArgs struct { Self string Hole string + Sig string } func makeHole() string { @@ -205,11 +206,12 @@ func makeHole() string { } func newWormhole(w http.ResponseWriter, r *http.Request) { - http.Redirect(w, r, "/wormhole/"+makeHole()+"/upload", http.StatusSeeOther) + hole := makeHole() + http.Redirect(w, r, "/wormhole/"+hole+"/upload?s="+base64.RawURLEncoding.EncodeToString(mac([]byte(hole))), http.StatusSeeOther) } func wormhole(w http.ResponseWriter, r *http.Request) { - if err := wormholeTemplate.Execute(w, wormholeTemplateArgs{Self: *selfURL, Hole: r.PathValue("hole")}); err != nil { + if err := wormholeTemplate.Execute(w, wormholeTemplateArgs{Self: *selfURL, Hole: r.PathValue("hole"), Sig: r.FormValue("s")}); err != nil { log.Printf("Warning: wormhole: %s", err) } } @@ -300,6 +302,16 @@ func wormholeRecv(w http.ResponseWriter, r *http.Request) { } func wormholeQR(w http.ResponseWriter, r *http.Request) { + sig, err := base64.RawURLEncoding.DecodeString(r.FormValue("s")) + if err != nil { + http.Error(w, fmt.Sprintf("Bad signature: %s", err), http.StatusBadRequest) + return + } + expectedMAC := mac([]byte(r.PathValue("hole"))) + if !hmac.Equal(sig, expectedMAC) { + http.Error(w, "Bad signature", http.StatusBadRequest) + return + } qr, err := qrcode.Encode(*selfURL+"/wormhole/"+r.PathValue("hole"), qrcode.Medium, 200) if err != nil { http.Error(w, fmt.Sprintf("failed to encode QR code: %s", err), http.StatusInternalServerError) @@ -309,10 +321,12 @@ func wormholeQR(w http.ResponseWriter, r *http.Request) { w.Write(qr) } +const macSize = 16 // sorry + func mac(msg []byte) []byte { mac := hmac.New(sha256.New, secretKey) mac.Write(msg) - return mac.Sum(nil) + return mac.Sum(nil)[:macSize] } func sign(msg []byte) []byte { @@ -320,10 +334,10 @@ func sign(msg []byte) []byte { } func verify(msg []byte) ([]byte, bool) { - if len(msg) < sha256.Size { + if len(msg) < macSize { return nil, false } - msg, messageMAC := msg[:len(msg)-sha256.Size], msg[len(msg)-sha256.Size:] + msg, messageMAC := msg[:len(msg)-macSize], msg[len(msg)-macSize:] expectedMAC := mac(msg) if !hmac.Equal(messageMAC, expectedMAC) { return nil, false diff --git a/templates/wormhole.html.template b/templates/wormhole.html.template index ad23b57..eb423ca 100644 --- a/templates/wormhole.html.template +++ b/templates/wormhole.html.template @@ -12,7 +12,7 @@
  • Visit this URL {{.Self}}/wormhole/{{.Hole}} or scan QR code:

    - QR code for {{.Self}}/wormhole/{{.Hole}} + QR code for {{.Self}}/wormhole/{{.Hole}}
  • -- cgit v1.3.1