Skip to main content

3 posts tagged with "Security"

Authorization, IDOR, HTTPS and the common vulnerability classes from the OWASP list.

View All Tags

Forwarding Headers in ASP.NET Core: Why 'Forward Everything' Is an Architectural Bug

· 11 min read
Nguyễn Huỳnh Minh Tiến
Middle Fullstack Developer @ Utop.vn
Summary

Copying every incoming header onto an outgoing request is an anti-pattern, and it fails in three different directions: correctness (one non-ASCII value makes HttpClient throw), security (you trust and relay data the client set itself), and architecture (headers injected by infrastructure become part of your application's contract). The fix is an allowlist — an explicit list of headers permitted to pass — placed in a shared DelegatingHandler. When you write that handler, mind one trap: it does not live in the request's scope.

This post closes a three-part series that began with a production incident on an e-commerce loyalty platform of roughly three million customers, where Cloudflare's cf-ipcity: Hồ Chí Minh header broke an internal call. The first part told the story, the second explained why headers cannot carry Vietnamese. This one answers what is left: how do you rewrite that code correctly?

Traefik + Cloudflare: Why Your Certificates All Expire on Day 60

· 17 min read
Nguyễn Huỳnh Minh Tiến
Middle Fullstack Developer @ Utop.vn
Summary

When a domain is proxied through Cloudflare (the orange cloud) with SSL mode Full (strict), ACME HTTP-01 cannot work: Let's Encrypt requests http://domain/.well-known/acme-challenge/... on port 80, Cloudflare receives it and calls back to your origin over HTTPS:443 — where Traefik's challenge handler does not live. You need a certificate to get through Cloudflare, and you need to get through Cloudflare to obtain a certificate. You can work around the first issuance by temporarily switching the cloud to grey, but the automatic renewal around day 60 will fail silently and every site will expire at the same time. The way out is DNS-01: validation through a TXT record via the Cloudflare API, with no request ever touching the origin. The price is that certificates can only be issued for zones your API token can see.

This VPS runs 14 containers behind one shared reverse proxy: 10 WordPress sites, a .NET API, an Angular app, an event web app, and Traefik itself. Thirteen hostnames, all behind Cloudflare, all needing HTTPS, and nobody wanting to renew a certificate by hand.

The architecture is boring in the best way. What is interesting sits between Cloudflare and Let's Encrypt — two systems each doing exactly their job, which together produce a circular dependency you only discover on the day your certificates expire. That is, two months after everything appeared to be finished.

Change the id in the URL and Get Someone Else's Data? Stop IDOR in a Single Layer

· 13 min read
Nguyễn Huỳnh Minh Tiến
Middle Fullstack Developer @ Utop.vn
Summary

IDOR happens when an endpoint takes an id from the request and loads the record directly, checking only that the caller is logged in rather than that the caller has rights over that particular record. Switching ids to GUIDs or encrypting them does not fix the bug, because the id still leaks somewhere else. The fix is to force every query through a layer that binds it to ownership on the server, instead of scattering checks through individual controllers.

You have a perfectly ordinary endpoint: GET /api/orders/1043 returns order details. It sits behind [Authorize], only a valid token gets through, and in the UI a user can only click into their own orders.

Then somebody logs in with their real account, changes 1043 to 1044, and hits send. If the server returns someone else's order, that is an Insecure Direct Object Reference — IDOR for short. No payload, no technique, just one number changed.