A web request crossing a shield boundary while an unsafe branch is blocked
View source on GitHubB1Z0N/RustWebSoftwareSecurity

labsecuritywebacademic

Rust Web Software Security

Security coursework with Rust web tooling.
  • Rust
  • Rocket
  • PostgreSQL
  • OWASP ZAP
Date
April 2023
Status
Historical
Visibility
Public

This is my Rust software security assignment from my major at the University of Twente. I was supposed to write a secure web image gallery — and I did. It is a Rocket site backed by PostgreSQL, brought up with docker-compose, serving image uploads with private galleries.

Scanning it

I set up a clean virtual environment — Ubuntu 22.04 Arm — brought the site up, and checked basic functionality first. Then I built OWASP ZAP and ran automated scans against it: the traditional spider for a first pass, then the AJAX HtmlUnit spider, which took longer and expectedly found more.

ZAP alerts reported by the traditional spider scan

Fixing it

The scans and a read through the code became a hardening pass:

  1. Proper handling of non-values, with metamacros I prepared for it: null!, http_code!, define_http!, redir!, templ!.
  2. Transactions and rollback support in upload_post, so a failed upload cannot leave half-written state behind.
  3. The xmllint CLI replaced with the minidom library, and the imagemagick CLI with the MagicWand API — no shelling out, less room for command injection.
  4. A shield against XSS and an html_sanity check.
  5. SQL injection checks: tokio_postgres provides safety in its queries, and ' gets escaped in search input.
  6. A CSP outlining where images, objects, stylesheets and scripts may come from — see src/utils/fairings.rs.
  7. An anti-CSRF solution through the rocket_csrf crate, with my modification and work from other open-source contributors — mainly CsrfForm, which auto-validates the tokens.
  8. UUID-based ids, so private images are harder to predict, plus a unique u16 in static file naming so nobody can accidentally — or not so accidentally — override someone else’s image.
  9. cargo audit over the dependencies, and Google’s osv-scanner on top. Nothing meaningful: a stale net2 advisory on Rocket’s side and a minor atty one.

cargo audit reporting the dependency tree clean

Along the way I published my own Docker image that builds imagemagick together with Rust on Debian.