51

I work on web applications and as you know, having an administrator panel is a must in most cases. We can see that a lot of web applications have a specific login page for administrators in which there is a form (usually POST method) that admins can use to login their panel.

But because the field names are known, a hacker can attempt to crack the passwords even if some security methods are implemented.

So what is the problem with a simple GET key (as username) and its value (as password)? Why it's not used a lot or at least, is not suggested in many articles?

For administrators, user-friendly login pages are not really needed! Data will be logged in both cases (GET/POST) if there is a MiTM attacker.

But using this method, fields will be unknown expect for admins themselves. Here is a sample PHP code:

"category.php": (A meaningless page name)

<?php
if (isset($_GET['meaningless_user']) && $_GET['meaningless_word'] == "something"){
    session_start();
    $_SESSION["user"] = "test";
    header('Location: category.php');   // Redirect to same or other page so GET parameters will disappear from the url     
} else {
    die(); // So it'll be like a blank page
}
?>
  • 8
    You should use HTTPS then you wouldn't have to worry about MITM. Additionally, if you don't care about user friendliness, you can implement HTTP Basic or client certificate authentication, then you would not have to implement authentication in the web application itself. – Lie Ryan Jan 4 '17 at 3:44
  • 43
    Web server logs and proxy logs, period, primary reasons to POST this info and not GET it. Everything jdow and tlng05 say is also true, but logs are the foremost "oops there it is" with HTTP(S) GET. – gowenfawr Jan 4 '17 at 4:53
  • 8
    Your admin on some forum: "Hey, I'm having this problem with my site's administrator panel. You can see it here: example.com/category.php?catID=admin&pageNumber=hunter2 – immibis Jan 4 '17 at 10:12
  • 4
    "fields will be unknown expect for admins themselves" - I'm not sure what you mean by that. Are they dynamically generated? Or are you suggesting ?myusername=mypassword? Why couldn't you do the same with POST? – Bergi Jan 4 '17 at 11:17
  • 8
    GET requests are stored in HISTORY on web browser too -- thats an easy target for just about anyone who manages to get onto your computer for even 15-20 seconds.. – mike510a Jan 5 '17 at 16:04
63

I can think of quite a few reasons why this would not be ideal:

  • In the code snippet you posted, you are now hardcoding a secret key into your program's source code. This is bad because now if you want to publish or share your source code with anyone else, you will have to remember to redact that key. The security of a system should not be dependent on its source code remaining hidden.
  • This doesn't scale well. If you have only one secret key that all administrators must share, it becomes a lot easier to accidentally leak. If it does leak, you would have no way of knowing who was responsible for leaking it. You could provide a different key to each administrator, but this becomes messy very quickly.
  • You cannot change the key easily. Generally speaking, you will likely need to have site administrators who are not also server operators. But with this setup, you cannot grant anyone the ability to change the key without also granting access to the source code and server, which they may or may not know how to use handle. Tweaking the source code running on a production system willy-nilly is error-prone and will likely result in downtime.
  • Because you use GET, it is very easy for the key to leak through browser histories, or accidental link sharing.
  • It is not very user friendly. Using this requires knowing how to manually manipulate a specific GET parameter. You say that user-friendliness for administrators is not needed, but this is definitely not true in general. Your entire site should be as user-friendly as possible, including the administrator panel.

In summary, I can see this kind of system in use as a temporary measure on a tiny site, where there is one site administrator who also wrote the site's source code and manages the server. But anything bigger than that, you'll want to have an actual administrator login panel, with hashed and salted credentials stored in the database like any other user.

  • Regarding point 2: giving different keys to each administrator isn't really that messy. Secret sharing is actually pretty simple. – Mego Jan 5 '17 at 9:40
  • @Mego I mainly meant messy in terms of code. e.g., what happens when you want to assign different privilege levels, or add/remove administrators. This also leads to the third point. – tlng05 Jan 5 '17 at 13:32
138

This would store the login link with password and username in the browsers history. It could also be accidentally be captured by things like firewall logs, that wouldn't capture post variables.

  • 64
    Also, people pass around URLs with parameters all over the place (imagine your query, with username and password parameters, appearing on stackexchange). This could also open you up to CSRF attacks. – Ari Trachtenberg Jan 4 '17 at 3:47
  • 2
    And even if you're using HTTPS, there's still plenty of browser extensions that collect the full URL of the page you are visiting. WOT is a recent example that got much publicity, but there are and have been other ones. – user2428118 Jan 5 '17 at 19:11
  • 1
    I remember a site that did a proper authenticate, but then generated a session key that it embedded (GET style) into the URL. Was rather prone to this URL sharing, because more people notice ?user=me&password=letmein but ?sess=012345678 is less obviously a problem. – Sobrique Jan 6 '17 at 14:17
  • If you use Google Chrome, your browsing history is also sent to Google by default. – Brendon Jan 28 '17 at 20:10
27

Not strictly from a security stance, but Hypertext Transfer Protocol -- HTTP/1.1 RFC 2616 makes it quite clear:

...the convention has been established that the GET and HEAD methods SHOULD NOT have the significance of taking an action other than retrieval. These methods ought to be considered "safe". This allows user agents to represent other methods, such as POST, PUT and DELETE, in a special way, so that the user is made aware of the fact that a possibly unsafe action is being requested.

GET should be used only for retrieval. In your case, you are submitting data to the server, the server is performing these specific actions (at a minimum):

  • Authenticating a user
  • Creating a session to track user state (PHP creates session data in flat files or a database)
  • Setting a session cookie to track the session

POST over HTTPS would be the preferred method to transmit sensitive data; username, password in this case.

  • 5
    GET operations should be idempotent, meaning that you can perform the operation over and over again safely. In other words, you aren't changing anything on the server... you are simply supplying the data necessary to request a specific resource (in this case, an authenticated page). For anything other than a static HTML site, a GET request will almost always be performing actions of significance (eg. www.mystore.com/product.php?productid=123 still has to build and display the product page). Using GET for sensitive data is indeed a VERY bad idea, but not necessarily because of RFC 2616. – DVK Jan 4 '17 at 20:13
  • @DVK: It's a very good reason, though there are others outlined in other answers. When logging in and starting a session (in PHP) there are several changes on the server, and your session is persistent across pages. – AbraCadaver Jan 4 '17 at 20:45
  • 1
    @DVK GET operations shouldn't just be idempotent, they should be pure (which I think is what you meant). Being idempotent means doing it twice has the same side effects as doing it once. Being pure means doing it once has the same side effects as not doing it at all. For comparison, DELETE is idempotent, but not pure. – James_pic Jan 5 '17 at 11:27
  • @James_pic "Being pure means doing it once has the same side effects as not doing it at all." When we are talking about significance, we're talking about resources, not the invocation of server-side processes necessary to retrieve the resource. Logging in really has no side effects in terms of resources. It doesn't create, delete, or change a resource. It provides the data necessary (in this case, authentication information) to locate and display the resource, no different than ?productid=123 does. The major difference is that the RFC DOES specify that sensitive info should NOT be in GET. – DVK Jan 5 '17 at 16:05
  • @AbraCadaver Pretty much any dynamic site is going to invoke changes on the server for any request whether you authenticate or not. The importance is that you aren't doing anything with the underlying resources themselves. Any server-side changes are merely incidental to displaying the resource. A user logging in or not logging in (or logging in 9 times) generally has no impact on the resources they are attempting to access, so I would argue that logging in IS pure (safe). If creating a session precludes using GET, then GET could basically only be used for static resources. – DVK Jan 5 '17 at 16:12
26

How comfortable are you with storing administrator passwords in clear-text in your web server access logs?

The problem I see here is that a GET request must put all the field names and values in the request URI. Request URIs are logged by all sorts of processes and will likely be stored, in full, in the web server access log.

That means your web server access log increases in security risk because it now contains the usernames and passwords for GET-based login pages. While you might generally treat server logs as containing privileged information (your customer's IPs for instance), they are not typically so sensitive as to contain enough information to compromise a client's administrative interface.

POST is superior for this, because the field names and values are not stored in the log.

4

A malicious user gains admin credentials. Using an image tag

<img src="https://example.com/login?username=admin&amp;password=topsecret" style="display:none"> 

they trick your browser to log in (images are not subject to cross-domain restrictions by default). They can then use a series of "image" calls to obtain or change data (a lot of AJAX calls use GET incorrectly as well). There are ways to avoid this, but most people don't enable them. If you're using POST, this attack vector doesn't work.

  • Field key is unknown, how can an attacker guess that? – Amirreza Nasiri Jan 4 '17 at 22:36
  • 3
    As has been mentioned elsewhere, you could get this from a browser or it could be shared by a user. Security through obscurity only lasts as long as your users care about it. – Machavity Jan 4 '17 at 23:45
  • 1
    @AmirrezaNasiri if there's a publicly-visible login form using GET, how can the password field name be unknown? – moopet Jan 6 '17 at 16:11
  • 1
    I think @AmirrezaNasiri is suggesting that there wouldn't be a visible form - instead admins would just know how to type get parameters into the address bar. – bdsl Jan 6 '17 at 23:39
3

The problem of using the get method is that the data will be visible on screen and in the webserver logs by default.

My rule of thumb is use post for passwords and big information such as blog article editors and use get for most everything else. Of course there is a few exceptions where the data is too sensitive to appear even in the logs. But those are rare even in the corporate sector.

For example, I have a wizard like functionality with 5 steps where I generate a process id on the first step and on every step you will see ?proc_id=123. PHP supports the query string even in post methods. Even in a step where the form data is too big and I am forced to use the post method the process id still goes visible in the URL like ?proc_id=123.

This makes easier to bookmark things, easier to understand the access logs, as well more educative to third parties that wants to integrate with my apps.

Some precautions must be taken in that scenario to avoid problems with the back button such as clearing from history URLs that must not be resubmitted. Most save actions are like that.

Of course the POST will not protect you from a MiTM attack. It will only prevent sensitive information such as passwords to be written in the logs in your site and in the local history of the browser.

3

Also consider that GET-Requests are intended not to change anything on the server side. A state change like "logged out" -> "logged in" always have to be done with a POST-Request.

Having a GET parameter like

https://example.com/loginpage.php?password=topsecret 

is semantically exactly the same as

https://example.com/loginpage/password/topsecret 

So there is no authentication at all. It is just an "secret" URL that you have to know to "login".

To make it more clear. If you use Apache for instance you can get the same result with a redirect like this:

RedirectTemp password/topsecret veryobfuscateddirectoryname/loggedin

and then on the loggedin-page place your session_start()

2

Even if the user and password weren't stored in the browser's history (which they are, as URL parameters) this makes it extremely easy for any hacker to steal your information. It will appear in the server's logs, it makes it even easier to perform a man-in-the-middle attack. It also allows for lots of bad practice, like people bookmarking the login URL, forgetting about it, and letting other humans use their Web browser.

TL;DR: This is a horrible idea.

1

Yes, it is bad practice. Any security advantage available by having a secret field name could also be gained by prepending that secret on to the password.

Instead of GET with

elephant=rthg4e5sdc

you would be better to use POST with

password=elephantrthg4e5sdc

And of course you can increase the security again by changing that to something more like

password=ehu3dva7rthg4e5sdc

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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