69

In my application, users have certain roles which have permissions. These permissions dictate which UI elements are available to them at the home screen. Many of the elements link to other pages, which many users cannot see because their permissions do not allow them to go to that web page.

For example, a button called button1 links to a random page in the application, let's say http://www.example.com/example.jsp. The user John however, has permissions set that don't allow him to see button1. Therefore John cannot go to http://www.example.com/example.jsp.

The issue I'm having is that if I am signed in as John, and I paste that URL, it will take me to the page.

Obviously this is a huge security risk if an attacker gets the URL to an administrator page for example. So, how can I protect against this? Do I need to verify the user for every single page, checking permissions and making sure that they are allowed to be there?

There are hundreds of pages in this application and that seems very redundant and not efficient to include code on every page to do so. Is there an easier way to do this than the method I just mentioned?

Peter Mortensen
  • 877
  • 5
  • 10
Michael
  • 861
  • 2
  • 9
  • 19
  • 2
    I'm curious if this is considered the same issue as "[Forced Browsing](https://www.owasp.org/index.php/Forced_browsing)" ? That page describes it as finding pages that were never meant to be public, rather than bypassing user permissions checks. – Mike Ounsworth Oct 10 '17 at 19:40
  • 107
    @Michael If executing code on each page actually requires modifying each page individually, you're probably doing other things wrong as well. If you have no provision for site-wide security and sanity checks, you should add it sooner rather than later. Do the developers have any security training? There are red flags everywhere here, and fixing the things you find will leave the things you didn't find unfixed. – David Schwartz Oct 10 '17 at 23:31
  • Since it looks like your application is servlet-based, Spring Security is worth looking at (you don't have to be using Spring to use it, even though Spring is awesome). – chrylis -cautiouslyoptimistic- Oct 11 '17 at 00:02
  • 10
    Yes, every page and every destructive action and every action that exposes private data. What you have here is called a "cross-cutting concern" – Bradley Thomas Oct 11 '17 at 02:26
  • 26
    Permissions should not be enforced by just hiding UI elements ;) but with the answers I think you understand that now – EpicKip Oct 11 '17 at 09:53
  • 14
    I always try changing the url ust for the fun. When there is only an enable.php I try disable.php for example. – feedc0de Oct 11 '17 at 11:35
  • 3
    If you're currently doing security checks at the client level (which is nice to avoid useless queries to the server, but in no way secured), you may have other security issues, like SQL injections. Make sure your server properly handles all the data your client throws at it (and yes as everyone already mentioned your server must make sure that the currently logged in user is allowed to execute the current HTTP query). – user276648 Oct 13 '17 at 01:54
  • 18
    I haven't read the magic words in any answer. **Do. Not. Trust. Input. Ever.**. – usr-local-ΕΨΗΕΛΩΝ Oct 13 '17 at 07:26
  • @usr-local-ΕΨΗΕΛΩΝ absolutely, that one rule thoroughly applied gets you a long way towards reasonable security. – Joseph Rogers Oct 13 '17 at 16:07
  • @danbru1211 I thought I'd accidentally cracked into a networking thing until I realised that it was just a demo of the product that the company was selling. The password "security" was a client-side `md5` hash, and it completely broke if you did something similar to what you described. It's a great way to perform really basic pen-testing though. – wizzwizz4 Oct 13 '17 at 17:24
  • 1
    I have a GreaseMonkey script that lets me to see **all hidden elements** on the page by pressing **just one key**! Just imagine what I can do to your website if I actually bother to read the source-code! – user21820 Oct 14 '17 at 14:01
  • "*The issue I'm having is that if I am signed in as John*" - Why can you sign in into others' accounts at will in the first place? – Buffer Over Read Oct 14 '17 at 15:23
  • Implementing the `javax.servlet.Filter` interface is what you want. It enables you to process every request. Btw jsp is grossly outdated and unless this is a university project you should strictly drop Java EE and proceed with more modern frameworks which have all these basic necessities built-in. – K DawG Oct 15 '17 at 07:31
  • 1
    Sorry but you seem to have no understanding at all of basic web application security. You should have a look at the [OWASP Top Ten](https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project). – Andrea Lazzarotto Oct 15 '17 at 21:06
  • It astounds me how common this situation actually is... – zxq9 Oct 16 '17 at 06:52

7 Answers7

344

Do I need to verify the user for every single page?

Absolutely. Not only every page, but every request to a privileged resource, e.g POST request to update data, delete, view, etc, etc. It is not just about viewing the pages, it is about controlling who can do what on your system.

It sounds like your entire authentication and permissions system is broken in its current implementation. The steps to remedy this are too broad for this one answer. It would be worth a general search of this forum and the wider net to find solutions suitable for your framework (JSP, ASP.Net, PHP, etc.). Most frameworks have out-of-the-box functionality for solving this problem.

A good start would be this high level guide from OWASP: Operational Security: Administrative Interfaces.

TrickyDupes
  • 2,809
  • 1
  • 13
  • 27
  • 157
    I just want to reiterate because your answer is not a small thing to do at the OPs stage: Yes, this is absolutely the correct and only answer. Every single page must properly enforce security rules. It sounds like all that is in place currently is client-side security, which doesn't actually provide any security. There are ways to write the code so that you can easily apply security on every page, but there is no answer that doesn't involve enforcing security on every individual request. Otherwise you don't have any security. – Conor Mancone Oct 10 '17 at 17:03
  • 2
    To be a bit more precise Than what you say Trickycm, Ideally, you need to find a unified solution to handle both navigation links/button/... and direct URL navigation. Since it's unified you have way less chances to forget one thing. Because if it is not, that mean you always have to handle at least two different declration of the same security (note : I have that currently and I do need to unify it, :3). – Walfrat Oct 10 '17 at 22:02
  • 74
    Just a note: **AJAX requests** are requests, too, and **should be verified**. It doesn't matter that this particular AJAX request should only happen from a page that already verified user. I know that this falls under "every request" in the answer. just making sure OP knows that, too. – Mołot Oct 11 '17 at 00:47
  • 65
    One additional point: This check must be done **on the server** - not by javascript code which is run (or not) on the client. A malicious user can avoid running the javascript code. – Martin Bonner supports Monica Oct 11 '17 at 12:17
  • 38
    Finally: using javascript to hide links to which the user doesn't have access is fine - but that's a matter of having a nice UI, not security. – Martin Bonner supports Monica Oct 11 '17 at 12:18
  • 1
    It might be useful to include the term "authorization" somewhere in this post, as that's also a common term for describing permissions checking/management and so might be helpful in searching. – jpmc26 Oct 11 '17 at 19:17
  • @MartinBonner I'd prefer to "hide" the links in PHP -- might be slower, but if the HTML never gets generated for these links, the client/user would be none the wiser even if they combed through the source code via a browser inspector. – psosuna Oct 11 '17 at 21:12
  • 3
    @psosuna Why would it matter if the client/user could find the URLs? They can't *do* anything with them. If they try to use those URLs the server will just say "Sorry, you aren't an administrator". – user253751 Oct 11 '17 at 22:07
  • 2
    @immibis for the sake of cleanliness, if anything at all. It could be that there is *the one page* in the site that isn't enforcing security (as it should be!) and the address to it can be discovered when inspecting the source on the client side. To mitigate that possibility, it's better to not reveal it, no? Better safe than sorry, I say. – psosuna Oct 11 '17 at 22:16
  • 2
    @psosuna: [shrug] I don't really care where you hide the links. The point is that hiding the links is not really about security, it's about a good UX. (Although it is one case where a good UX is certainly not in conflict with security.) – Martin Bonner supports Monica Oct 12 '17 at 07:06
  • 8
    @MartinBonner totally agree with you, but generally, security is about layers. And while hiding the links is of course not security, it can help. If there is a bug somewhere in the security checking, not having the links still adds something, so I also prefer not sending the data to the clients in the first place. (I see it as another layer). – kap Oct 12 '17 at 11:56
  • 1
    For all intents and purposes, any and all resources/requests that your server isn't directly authenticating and authorizing must be considered public. If you do not check that X request comes from a registered user with proper permissions, then X request is public and can be accessed by anyone, regardless of what your UI will provide. – Delioth Oct 13 '17 at 19:25
38

The quick answer is yes, as you gathered. But it doesn't need to be the huge job you're thinking of. (The whole security thing might be big, but this is only one part of it). You have far more serious issues than that.

Why it matters

ANYTHING you create will be hit with attempts to break it. Someone will be curious. Someone will do something you never expected and which defies your thinking. Someone will be curious, or malicious, or nosey.

You should also take for granted that your software/web app will be tested hard by automated tools. Servers with an online portal (of almost any kind) get discovered by hackers within tens of minutes of first going online, and start to be probed for any one of thousands of possible security lapses or oversights. This means they probe for what exactly is running "behind the scene", as well as for any detectable lapses that can be exploited (in data validation, cross scripting validation, SQL or binary injection, JavaScript hacking, the back-end itself, what weaknesses can arise by forcing something to fail, what data can be exposed...).

Your web server(s) will be probed this way, constantly, for any possible web code and back-end lapses, by hundreds if not thousands of automated tools. That's as well as humans and users, not instead of.

Would you rather this was far down the road and brought to your attention forcefully by critics, media, and irate users, or led to liability? Or would you rather fix it?

How to resolve it

Its not a huge job in one sense. You create a security framework and then each page imports or uses it. The concepts to do so aren't hard and are well documented. So the number of pages isn't a big deal.

The hard part of the job is that security is hard. Your real problem is that, from the fact that these issues are there and you're asking these questions, you don't know enough to have a hope of doing it without help. Seriously. You. Do. Not.

I don't know what size team you have, or resources. You need it - and you probably don't have a hope of doing it without outside help.

My real concern here

That said, my real concern isn't the web app. It's the mindset this question suggests.

Imagine I'm considering buying or using your app.

It doesn't help, or reassure the reader, that you apparently consider security as an afterthought, a disruption to your work or inconvenience to fix up afterwards (or don't understand it enough that so far you've treated it that way), and maybe the issues are things that are really basics, like coding a button URL properly.

Security is your work, because however technically wonderful the product/service is and whoever its users are, your real product is trust and reassurance that you'll address my needs and not cause me a major disaster.

I'm supposed to trust your app with my data? Right now, and I'm sorry to say this, I think I might as well publish it on Google+ myself. Yes it is "that bad" a situation and impression, and no this is not overstating it for effect.

I'm sorry.

Now, if your app is any good, get someone else involved.

Stilez
  • 1,664
  • 8
  • 13
  • The latter part of this seems to suggest that customers decide on products based on the security. Except in some very, very specific niches this is just not true and from a business PoV it's a horrible idea to spend any more than the bare amount necessary on non-functional requirements such as security as a startup. Yes everybody here hates that mindset, but the simple fact remains that users don't care about security and even if they did they couldn't judge what is secure and what isn't (don't believe that? Go ahead and check the user numbers of TextSecure/Signal with WhatsApp) – Voo Oct 16 '17 at 18:21
  • You're thinking of up front. Not initially, no. But once a major issue becomes known - yes. Once it hits reviews - yes. Once social media starts to get comments like "What's happened and how could it be able to happen" by more than one or two people - yes. People don't actively look for security, but they do look at reviews and public knowledge, if its out there, and it will be after a while. (I do agree it would be nicer if they looked first but if its a major issue, as the OP indicates, it'll get visible fairly fast - right about when something screws up and someone posts about it angrily) – Stilez Oct 17 '17 at 03:36
28

You need to check the user permission level for every request (GET, POST, PUT, DELETE). Browsing to a page, like in your case is a GET request. A user shouldn't be able to post a request without permission as well.

Now whether you need to add the code on each page of your application depends on your application framework. For example, some frameworks (Laravel, Express.JS) allow you to group routes and apply a filter to each request for that route, and this is where you put in the checks. For applications in plain PHP, you would need to have the code on each page, you can use the "include" statement to minimize repition of the entire block of your code.

Silencer310
  • 380
  • 2
  • 4
  • 7
    HEAD or any other [weird HTTP methods](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods), too (unless of course you *always* block those). – jpmc26 Oct 11 '17 at 19:13
7

It's been said before, but, yes, you should verify your user credentials on every page. If your site uses PHP, for example, the absolute easiest way to do this is to save the logged-in user and their privilege level in session variables, then do a verification of these session variables at the start of the code. These are wiped on logout (if you created logout logic to wipe these variables) or session timeout (the time for timeout can be defined, but I think the default is 5 minutes of inactivity), so an unauthorized user should not be able to access a page. Other technologies will have similar handling.

I really do not mean to sound condescending when I say this so I hope you don't see it in that light, but this is sort of bread-and-butter information. If you somehow didn't learn this or didn't come across this in your self-studies, I strongly suggest you take note of this and read a little more in-depth on this particular subject, because it is very important. You'll be doing this time and time again for any similar application of the sort.

Do take note that there are various ways to do this in a simple and efficient manner, and a personal suggestion from me to you would be to practice coding it in your own logic so that you fully understand how it works, before you attempt using a framework. Test it against several access methods, and once you're satisfied, you can look into how the various frameworks perform user session handling.

EDIT: I put this on a comment down below, but this is actually a good resource for OP as well: https://www.w3schools.com/php/php_sessions.asp

psosuna
  • 201
  • 1
  • 7
  • 1
    What safety guarantees does PHP provide for these session variables? Are they stored on the client machine; if not, how does a client identify its session? Is the client side data encrypted? Are there safeguards against sharing the client side data? – jpmc26 Oct 11 '17 at 19:25
  • Here's a quick and easy explanation of PHP sessions: https://www.w3schools.com/php/php_sessions.asp . Information and session variables are not stored client-side, only server side. A key is provided by the server to the client. The key is used to identify the session that the user is on at the moment. – psosuna Oct 11 '17 at 20:48
  • @jpmc26 an additional aside: PHP = Hypertext *Pre-* processor. This means that PHP code runs server-side. It executes before the HTML does, so there are many things that don't need to transmit to the user's machine. This is why PHP is a good option for doing authentication, as the input data can be verified before a response is sent back to the client. – psosuna Oct 11 '17 at 20:59
  • Oh, I'm quite familiar with PHP being a server side technology. (I work on web apps for a living, just not PHP ones. ;) ) But I know *something* has to be stored client side for the user session to be identifiable. Hence my questions about whether this data is encrypted and what have you (for preventing session hijacking or intentionally sharing the key to another user). See [this criticism](https://security.stackexchange.com/a/18898/46979), for instance. I dunno if some of that has changed in the past 5 years, though. – jpmc26 Oct 11 '17 at 22:52
  • 3
    @jpmc26 I think that criticism is poorly-targeted: it's about shared servers being badly configured so that users can access each other's data. Rather than encryption, the answer is to put the sessions in a directory other users can't access; if there is no such directory, they'll be able to access your decryption key anyway. It also has nothing to do with session hijacking, which generally describes an attacker stealing the session identifier *on the client side*; encryption would not help there, either. – IMSoP Oct 12 '17 at 14:14
  • @jpmc26 For fear of going too off-topic, you keep sessions safe with csrf tokens. Every action you take refreshes the token (so I request something with my token=>server sends back a new token to use for the next thing). – Delioth Oct 13 '17 at 19:35
3

The user must not be able to navigate to the page irrespective of whether he types the address or clicks on the link.

A generic solution to your problem is to use a role-based access control (RBAC) approach. Create different groups and assign users of equal privileges to the corresponding group. Similarly, group web pages and other resources inside different folders; each owned by a specific group. I had used chgrp (change group) to achieve this on a system running embedded Linux with a lightweight webserver. The same can be achieved in Apache webserver by placing a .htaccess file and denying access as mentioned on Stack Overflow.

For the UI elements, you will have create different pages (or hide elements by group checking). You will need to identify the user (logging them in and determining their corresponding group) and then display web pages per the user's privileges.

TRiG
  • 609
  • 5
  • 14
Majid Khan
  • 31
  • 2
1

Just a quick suggestion on implementation, since you had some concerns about 100s of pages. For example, in ASP.NET MVC, you could create a global filter or a "base" page all the others could inherit from.

Then the code, which is centrally located, could check user context/session and compare it against a list of rights/permissions/or group membership for the current page (maybe a data structure on each page or a database lookup based on page name, etc.).

Peter Mortensen
  • 877
  • 5
  • 10
Jester
  • 127
  • 3
1

Other answers have been very general, so I'll add this because JSP pages were mentioned, so I think I can assume you are working in Java.

As such, you most likely can use Filters to have code executed every time a request is made to the application. If you use a security framework like Spring you can configure URLs that may be accessed and by who.

Peter Mortensen
  • 877
  • 5
  • 10
Readin
  • 111
  • 1