What would a web app canary look like?

Monday, October 2, 2023

Recently, I listened to an interview with Haroon Meer, the founder of a company focused on honeypots. Honeypots (also known as canaries or tripwires) are used to detect network intrusions and people nosing around at things they're not supposed to. They are an essential component of modern network security.

It got me thinking: These are part of network security, so could we use this same concept for application security? What would it look like to setup a honeypot in a web app? How much can I make our pentesters personally loathe me?

The idea behind honeypots

The main concept behind a honeypot is that you deploy something that looks like an attractive target and monitor it for attempts to access it. Employees and legitimate users know where they're supposed to go, but attackers have to do some discovery, so they're likely to stumble across it. When access to the honeypot is detected, you can then respond however you'd like. Typically you will alert people to the honeypot access.

We could do this within our web applications, too. A component of penetration tests can include attempts to escalate privileges, or to access data you are not supposed to have access to. There are least a few diferent sorts of honeypots we could use.

But first, we need to think about what we want to protect against. Here, I'm going to consider two classes of bad actors. The first is malicious users, who try to use their legitimate access as a user of the application to gain access to information or resources they're not supposed to have access to. The second is insider threats, people who have high levels of privilege due to their role working on the application. Honeypots can be useful for both of these scenarios, but they have different considerations.

Sweetening the web app

The concept of a honeypot is nice and simple. What does it look like in a web app? There are a few obvious ideas that are also pretty easy to implement.

Tripwires on well-known values. There are some values which you know may be tried if someone is just nosing around. If you use integers for IDs, you could put a tripwire on 0 and powers of 2 (while ensuring these aren't used by the application). This would let you detect enumeration attacks: since these values wouldn't be legitimately used, attempts to access them are a sign someone is being naughty. Protects against malicious users; doesn't help with insider threats.

Decoy records in the admin interface. You can make fake records in your database which are real in one sense (they exist in the DB) but fake in that they are not for legitimate users. Then, you can monitor for access to these through various internal facing tools. If someone accesses these, that means that they're accessing records they have no legitimate business purpose to access (probably). Protects some against insider threats, and malicious users who escalated privilege.

Extraneous IDs embedded in pages and responses. There's no law that says that everything you return in a response has to be legitimate. You can populate extra fields with fake data if you know that the client using it is not going to do anything with that data. (This only really works if you control the client, otherwise you're setting up your users for failure.) If you receive requests with this fake data (decoy IDs or decoy endpoints) then you'll know someone was poking around for access to more things. This could be an attack, but it could also just be a curious dev who's using your product. Protects against malicious users, punishes curious users.

Tripwires on common URL paths. There are some common paths which many web apps use, like /admin or /wp-admin. If your application does not use these, you can place a honeypot on that URL. Then, if you get requests on that URL, you'll know that someone is nosing around a little. This is likely to be noisy; since these are common, you'll get a lot of random traffic on them hoping you've got an outdated WordPress installation. But, it can provide valuable signal, and if you get a request on this from a logged in user... yikes. Protects against malicious users, annoys whoever gets paged.

The possibilities here are almost endless! Some are good ideas, some are bad. But what's clear is that it's doable.

If you can think of any other ideas that will make a pentester's life absolutely miserable when testing a web app, please let me know!

If this post was enjoyable or useful for you, please share it! If you have comments, questions, or feedback, you can email my personal email. To get new posts and support my work, subscribe to the newsletter. There is also an RSS feed.

Want to become a better programmer? Join the Recurse Center!