Validating Signed URLs with Vinyl Cache¶
Note
This Tips & Tricks article is unannounced and unfinished. It serves the purpose of providing example code for a talk for which insufficient preparation time was allocated.
Signed URLs are created by some other component, for example a CMS. Signed URLs can not be manipulated externally: Only URLs which are generated by the signing component are accepted (unless of course the secret / signing key is leaked).
Here, only the basic concept is demonstrated. Many useful variations exist:
Using other algorithms than SHA256, in particular asymmetric crypto
Shortening the signature for less security, but shorter URLs
Accepting unsigned query parameters after the signature
Checking additional signed query parameters, for example timestamps
Adding additional data to the signature, for example a session cookie, which personalizes the URL.
VCL¶
The following VCL requires these VMODs:
The VCL code:
import blob;
import blobdigest;
import re;
import std;
sub vcl_init {
new signed_url_re = re.regex("^(/.*)[?&]sig=([-_A-Za-z0-9]{43})$");
new signer = blobdigest.hmac(SHA256, :affed00f:);
}
sub vcl_recv {
if (! signed_url_re.match(req.url)) {
return (synth(404));
}
# log expected signature - remove for prod
std.log(signed_url_re.backref(1) + "&sig=" +
blob.encode(encoding=BASE64URLNOPAD,
blob=signer.hmac(blob.decode(
encoded=signed_url_re.backref(1)))));
if (! blob.equal(
blob.decode(decoding=BASE64URLNOPAD,
encoded=signed_url_re.backref(2)),
signer.hmac(blob.decode(
encoded=signed_url_re.backref(1))))) {
return (synth(403));
}
# remove the signature. Can be kept if the backend handles it
set req.url = signed_url_re.backref(1);
# here we would normally fall through to normal processing
return (synth(200));
}
What is happening here:
signed_url_re is a regular expression for the expected req.url format:
It needs to end on a sig query parameter with a 32 byte value as base64 with
no padding (43 base64 characters).
signer is a SHA256 HMAC signer with the base64 secret affed00f, which
obviously must not be used in production.
In vcl_recv, requests to URLs which do not have the required format are
rejected with a 404 status. For a match, the provided signature is decoded and
compared with the calculated signature. A 403 status is returned for a wrong
signature.
Finally, the signature is stripped off.
References¶
This work is used as an example in the presentation WAF: Wrong Approach Firewall at GPN24.
Acknowledgements¶
Development of the VCL code and this documentation has been funded through an investment of the Sovereign Tech Agency.