0

I am creating a web-app using PHP and jQuery Ajax for my client-side. When I was testing some security stuff, I thought of inserting a malicious user account with admin access in the database by executing an Ajax call from the developer's console in Google Chrome:

$.ajax({
    url: base_url + "callbacks/AccountSettingsCallback/addUpdateAccount",
    type: "POST",
    data: {
        "addUpdateAccount": 1,
        "id": ""
        "first_name": "hack",
        "last_name: "hack",
        "username": "gethack",
        "password": "1234",
        "account_type": 1
    },
    dataType: "JSON",
    success: function(data) {
        console.log("get hacked")
    }
});

To my surprise, it was actually executed and the data has been inserted into the database, even though I was not logged in and should not have been able to do that!

I know that this is a very critical vulnerability, so my question is, what are the ways to prevent this kind of attack? Is there anyway to check via PHP wheather the request came from the console?

Anders
  • 64,406
  • 24
  • 178
  • 215
Akio
  • 3
  • 2

4 Answers4

3

No, you can not tell if a request came from the console, because when you have a client-server application, client and server are black boxes to each other. A request could come from the javascript running in the browser, the browser console, a telnet client, a handmade program, or a bunch of monkeys typing random characters on keyboards directly connected to an Ethernet cable. There is no way to tell one from the other.

So when you handle requests on the server, make sure that every request handler checks authentication. This includes handlers for ajax web services. Just because the average user should not notice that they exist does not mean nobody will find them. So your script which is listening to the endpoint callbacks/AccountSettingsCallback/addUpdateAccount needs to check the user's session cookie (or what other mechanism you use for tracking user sessions), check if the user has the required permission to execute that operation and that the data passed to the operation is plausible. Additionally, you should implement adequate measures against cross-site request forgeries so owners of other websites can not build web applications which cause the user to call ajax webservices on your site.

Philipp
  • 48,867
  • 8
  • 127
  • 157
  • Thank you for this. I'm now more concerned because of the last sentence of your comment. So, can CSRF Tokens solve this problem? – Akio Oct 24 '17 at 08:48
  • 1
    @Roland , not alone. Just think about an Application which don't check if you have the permissions to do something. That is what you currently have. The AJAX Website is just a nice view, it should not have any kind of logic that validates requests. And if it has some, do the same on the server side (PHP) – Serverfrog Oct 24 '17 at 11:22
  • @Serverfrog Understood, will add that handling! Thanks – Akio Oct 24 '17 at 11:48
  • @Roland The CSRF token only prevents requests from javascript embedded in other websites. It does not prevent requests from the same website. Keep in mind that every browser today comes with a javascript debugger, so it is easy to manipulate your javascript code which forms your ajax requests. Input validation and permission handling in client-server applications **must** be implemented on the server-side. – Philipp Oct 24 '17 at 11:50
1

There are two different scenarios:

  1. the user you used to execute the request is allowed to do that.

    In this case, you might not be able to do much about it - except inserting CSRF-protection to cope with that and/or XSS.

  2. the user you used to execute the request is not allowed to do that.

    In this case, you should add authentication and access control to all ajax endpoints.

Tobi Nary
  • 14,302
  • 8
  • 43
  • 58
0

No, there is no way you can distinguish if a request was made from the console or not. Neither is there any point to try to. It's not only that requests could be send from the console. The JS code of your application could be modified, or requests could be sent from a program that isn't even a browser, and there is no way for you to tell the difference.

Therefore, security needs to be enforced on the server. You can never, never trust the client to enforce security for you.

If you can only create new users when you are logged in with an account that is authorized to do that, it's fine. Someone who can create users created a user, thats all.

However, if you created that user without being logged in as someone authorized to do that, you have big problems. Clearly the server does not properly check if users have permission to do things. That means your app is wide open to abuse, and you should probably take it offline until you can fix that.

So how do you fix it? At the server, at every endpoint, you need to check if the logged in user is authorized to access it, and deny if not.

Anders
  • 64,406
  • 24
  • 178
  • 215
0

Yes you CAN tell if it is an ajax request (as per your console code) or a regular request. See here for a PHP implementation: https://davidwalsh.name/detect-ajax

It is pointless though. It is not 100% reliable and more importantly security should never happen on the client side. Add client side checks for convenience but always 100% of the time, no exceptions, filter, sanitise and validate server side.

TrickyDupes
  • 2,809
  • 1
  • 13
  • 27