Wisp is in pre-release, self-hosted since GitHub suspended us. Install it.

Wisp

PHP2Shell Would Never Happen on Wisp

A PHP upload form turned into a shell on the server. Wisp would never.

· itzcozi · 1 min read

If you don't live under a rock you know the story. (if you do live under a rock read this mate) Somebody builds a PHP site with a "upload your avatar" form, the server checks that the file name ends in .jpg, and then some kid uploads cat.php.jpg (or just shell.php) and visits it. Now the server happily runs it, and a picture upload is a shell on the box. Quite literally this has been an issue for decades and just now is it discovered... Mossad or other state actors definitely have used this in the wild.

Nothing Gets Run

A Wisp app is one compiled binary. There's no folder of scripts the server looks through to decide what to execute, so there's nothing for an uploaded file to turn into. Your routes were turned into Rust at build time, and a .php file sitting next to them is just a file sitting next to them. It never gets run, because the server doesn't know how to run it.

Uploads Check the Bytes

On top of that, Wisp doesn't trust the file name or the Content-Type header, since the visitor controls both. Take avatar: Image in a form and Wisp reads the actual bytes: PNG, JPEG, GIF, WebP or AVIF, and anything else is a 422. Not even SVG gets through, since SVG can carry scripts. For other files, #[validate(types = "application/pdf image/*")] does the same byte check.

Names Can't Walk Out

The other classic is ../../etc/passwd as a file name. doc.name() hands you a cleaned name with no folders in it, and doc.save_to(...) only writes where you told it to. Uploads stream to a temp file and get deleted unless you keep them, and when you do, they're saved as 0600 on Unix, so nobody else on the machine can read them by default.

It's Not Foolproof

Look, I'm not saying a Wisp app can't be hacked. If you write a handler that runs whatever a visitor sends it, I can't save you from that. But the usual way of getting there, where a file upload quietly becomes code execution, isn't on the menu. The safe thing is the default thing, and you have to go out of your way to be unsafe.

If you're curious how the rest of it holds up, there's more in why use Wisp. Otherwise, go check your upload folder. Seriously.

Type to search every docs page and heading.