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?

  • 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
  • 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" – Brad Thomas Oct 11 '17 at 2:26
  • 25
    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 9: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
  • 18
    I haven't read the magic words in any answer. Do. Not. Trust. Input. Ever.. – usr-local-ΕΨΗΕΛΩΝ Oct 13 '17 at 7:26
345

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.

  • 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
  • 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 0: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 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 Oct 11 '17 at 12:18
  • 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
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.

  • 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 3: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.

  • 7
    HEAD or any other weird 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

  • 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: 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, 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
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.

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.).

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.

protected by Anders Oct 14 '17 at 10:30

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.