The Temple was up all evening. In the morning it sat in the debugger. A bot had
asked for /%s%s%s%s.
What happened
-
DirNameAbs,FileNameAbsandCdglued path pieces together withCatPrint(buf,name). The name was the format string. Terry's users typed their own paths, so nobody noticed in ten years. Then the Temple got a web server. - A
%in the requested path madeStrPrintJointhrow insideFileRead. - Nobody caught it. In TempleOS an unhandled exception does not kill a session, it stops the whole Temple in the debugger. One HTTP request did that. The CIA would have needed a whole agency.
The fix
-
Kernel (
Kernel/BlkDev/DskStrA.HC,DskDirB.HC):CatPrint(buf,"%s",name).FileRead("/Www/%s%s%n")now says File not found, like it always should have. -
HtServ, honest paths only: letters, digits and
. _ - / ~, at most 128 characters. Anything else gets400 Bad Request. -
HtServ, no exception leaves a session:
HtServProcessruns in try/catch. The client gets a 500, the Temple keeps serving.
How it was tested
QEMU, 256 MB, 1 vCPU, virtio-net:
| Request | Before | After |
|---|---|---|
GET /%s%s%s%s |
Temple in the debugger, nothing answers | 400 |
GET /%n%n%n |
not tried, the Temple was already dead | 400 |
GET /../Once.HC |
403 | 403 |
GET /mcp |
404 | 404 |
GET / after all of the above |
no answer | 200 |
FileRead("/Www/%s%s%n") and Cd("/%s%n") from the Confessional: File not found,
no exception. Load tests unchanged: 30 parallel requests, 20 mixed with resets,
silent connections hung up after 15 seconds.
Deploying
The kernel changed, so tools/update_vds.py HOST rebuilds it with BootHDIns('C').
If C: does not come back, pick D at the boot menu.
Known sins
- A request line longer than 256 characters or with a space in the path is still dropped without an answer, as before. It no longer hurts anything.
- Other kernel code may still pass user strings as formats. These three were the ones a web request reaches.
Terry, forgive us. Your kernel trusted its users. Ours are bots.