Is POST as secure as a Cookie? - php

While implementing a flash-based uploader, we were faced with an issue: Flash doesn't provide the correct cookies.
We need our PHP Session ID to be passed via a POST variable.
We have come up with and implemented a functional solution, checking for a POST PHPSESSID.
Is POSTing the Session ID as secure as sending it in a cookie?
Possible reason for: Because both are in the http header, and equally possible for a client to forge.
Possible reason against: Because it's easier to forge a POST variable than a Cookie.

It is as secure — forging the POST is equally as easy as the cookie. These are both done by simply setting flags in cURL.
That being said, I think you've got a good solution as well.

If you are able to obtain the session ID from active content in order to POST it, this presumably means that your session cookie is not marked HttpOnly, which one of our hosts claims is otherwise a good idea for defending against cross-site scripting attacks.
Consider instead a JavaScript-based or even refresh-based uploader monitor, which should integrate well enough with everything else that the cookie can be HttpOnly.
On the other hand, if your site does not accept third-party content, cross-site scripting attacks may not be of any concern; in that case, the POST is fine.

I think sending it via GET would also work fine, since you fake anything in a HTTP request (using curl or even flash).
The important thing is what is encrypted in you cookie/post/get parameter and how is it encrypted and checked on the server side.

Really if you are worried about which one is easier to forge, you're worrying about the wrong thing. Simply put, either will be trivial to an experienced attacker. You might keep out the "script kiddies" by choosing one over the other, but those people arern't the ones you need to be worried about. The question you should ask yourself is "what defenses do you have against someone forging an id?" It will happen. If your id is unencrypted, and easy to guess, that's a problem. It will get hacked. Since you are asking which is more secure, I would say that you are concerned.
Here's another thing to consider, since your application is flash, it's susceptable to modification (just like javascript HTML code), because the compiled code is on the attackers machine. They can look through the binary and figure out how the code works, and what it needs to retrieve from the server.

POST data is not an HTTP header, but it is sent as part of the TCP stream which makes it just as easy to read/forge as an HTTP header. If you intercepted an HTTP request it would look something like this:
POST /path/to/script HTTP/1.1
Host: yourdomain.com
User-Agent: Mozilla/99.9 (blahblahblah)
Cookie: __utma=whateverthisisacookievalue;phpsessid=somePHPsessionID
data=thisisthepostdata&otherdata=moredummydata&etc=blah
So as others have said, POST and cookies (and GET data, i.e. query strings) are all easy to spoof, since they're all just text in the same HTTP packet.

I just want to reiterate that both Cookie and Post are equally insecure.

Related

PHP : Posting to SSL - Clarification?

Probably pretty basic question, but I’m a bit confused after reading similar questions and answers so hoping for more clarification.
If I have a non-secure page and have a form which posts to a protected one, will the data be encrypted once submitted?
Example:
http://example.com/login.php
has a form that posts to secure page:
https://example.com/do.php” method=“post”>
.....
Is that enough to make it a secure post or does the initial page have to be secure as well? No ajax or anything, just php...
Anything you post over SSL is secure in transit. But that is not where your problem would be.
If you have an insecure page http://example.com/login.php, an attacker can change the page when a user downloads it, because there is no security (no encryption, no integrity protection, nothing). The attacker can change the form to send the credentials from a login plaintext. Or send it to the attacker's server instead. Or inject any javascript, like for example to send every keystroke to the attacker right as keys are pressed. The attacker has full control over a page downloaded via plain http.
Why would an attacker then bother with the encryption in the next post? He can already have all the info before that post takes place.
So in short, if the original page was downloaded via plain http, there is (almost) no point in making a subsequent request over ssl - anything in the ssl request can be known to the attacker already. (Note that some special cases may be exceptions from this, but in general, this is the case.)
One notable exception is when it's not the request that needs to be protected, but the response - that will be encrypted in an ssl exchange, and I think a different protocol, https vs http will count as a different origin, so it will be harder to get info from the response even if javascript is injected into the original plaintext page. But this is not the case for the supposed functionality of a login.php - that must be served over https.

Without using SSL, what's the most secure way to make an AJAX request to a PHP page?

So, it's impossible to do AJAX requests securely without using SSL. I get it. You can either view-source the data that's being sent via Javascript, or you can directly access the PHP page by spoofing headers, yada yada.
But let's say this web app doesn't particularly require true security, and instead it's just a sort of game to keep most reverse-engineers at bay. What sort of hurdles should I employ?
I'm not looking for some ridiculously over-the-top Javascript implementation of an encryption algorithm. I want simplicity as well as mild security... if that isn't contradictory by nature. So, what would you guys recommend?
For example, I'm running a contest where if a user clicks an image successfully (jQuery), it passes their userid and a timestamp to a PHP page, both MD5 salted by random data and then encoded with MIME. The PHP page then validates this userid and timestamp, then returns a winning "code" in the form of another salted MD5 hash. I'm also employing multiple header checks to help ensure the request is from a valid location. Am I missing anything, or is that about all I can do? It seems like someone could just fire the jQuery click event and ruin the whole thing, but I don't see how I can prevent that.
I'll be awarding the answer to anyone who comes up with an ingenious faux-security mechanism! Or... just whomever tells me why I'm stupid this time.
I believe header checks can be easily fooled. Doesn't hurt though.
Since your algorithm is exposed on the client side, the user can simply send the appropriate data to your server with an automated script to fool your server into thinking it was clicked.
In addition to that, you have to watch out for session hijacking. A user can essentially submit this ajax request on behalf of someone else, especially if they have the algorithm. Does your application have different behavior for certain users? If so, then the session hijacking could turn into priviledge escalation issue.
It is not necessarily true that you need to encrypt the payload with SSL in your case in order to build a secure application. From what you've described, there is no sensitive data being sent over the wire.
Ensure that you have some basic silly checks on the server side to check for automated or malicious behavior. For example, if you find that the header information is missing, you may want to have some sort of flag/alert that someone is toying with the response. Another place you may want to do this is the pattern of requests.
A more secure model is to have the server assign the user some session token that they cannot reverse-engineer. This session token ideally should begin with the timestamp instead of the username to promote the avalanche effect of the salted hashing algorithm.
Since it seems like your application deals with prizes and potentially money, I would invest some more time in securing this app. Hope these tips have helped you.

How to Implement Generic CSRF Tokens with JQuery AJAX?

I am currently developing jquery code that sends data to the server via ajax that is then inserted into the database based on the request parameters.
However, I am rather concerned that this could be abused by CSRF attacks which would make things rather insecure. I have tried to research this and only find answers for specific frameworks such as django and rails where I am only after a generic implementation for use with PHP.
I have read that you can use the JQuery.ajaxsend() function to implement the code so that a token is sent with EVERY AJAX request however I have no idea how this can be implemented as JavaScript obviously has no access to the PHP session variables. Would the use of cookies be secure enough?
Basically I need to be able to check the origin of the request to ensure that the request is genuine and not a forged request used to take advantage of the system.
If anyone can point me in the right direction that would be most appreciated!
Well, do know that $.ajax seems to send the cookies, including the PHP session cookie, with its request. Using that feature changes your attack from CSRF to session hijacking, but it's a start. Next, run your service over SSL if you can to avoid the session hijacking.
I'm sure there are other ways to do this as well, but for vanilla PHP, this seems to work. Someone correct me if I'm wrong, please.
Here's how it's done in Django, but there's nothing that's framework specific (besides setting the CSRF token in the cookie as 'csrftoken'): https://docs.djangoproject.com/en/1.3/ref/contrib/csrf/#ajax

Security questions about cookies and javascript

Ok, i have always wondered if these 2 actions are possible:
To manipulate cookies. I mean, if i login for example into facebook it will save a cookie in my browser. Could i edit it in anyway? I think so since it is set into MY browser and not set locally.
To manipulare a javascript script. I mean, since javascript is read by the browser and every user can read the language, could it be edited? For example, let's say i have an ajax call that send data strings like user=basic or something (it's just an example), could someone change it to user=admin?
I hope this kind of things are not possible or i am pretty much f****d!
In that case, I'm sorry to say you are pretty much f****d.
You must always assume that everything on the client side can be manipulated by some evil hacker. This includes cookies and JavaScript.
Firefox makes this extra easy, using the Edit Cookies extension for cookies, and Firebug to edit JavaScript (and HTML and CSS).
Both users and javascript can manipulate cookie data. However, broswers have optional (maybe default) protection against setting cookie data cross-domain.
I think modifying cookies should be pretty easy, as they're stored locally. I checked and in firefox there's a bunch of sqlite files that seem to have that. I don't know much about sqlite, but it seems that modifying them should not be a problem (especially since you could get to the browser source code in this case and see how it interacts with them :) )
I'm not sure about javascript modification, it most surely can be done by messing around with low level HTTP stuff (intercepting request and sending bogus responses with the modified code). Anti cross-site scripting policies helps a little, but I wouldn't rely on them much, there should be security checks server based to be safer.
Yes/No, your domain can only manipulate cookies set by your domain. Your JS script, being on youdomain.com or localhost cannot edit a cookie set by facebook.com. Think about it, Internet would have imploded by now if you could do that.
However, users can edit their cookies at will.
Yes.
Yes and yes, and there are even tools specifically designed to make doing so easy. Getting security right is hard, and unfortunately it's something that greener web developers often completely miss.
The only thing you can really safely store in a cookie is a login token. Basically, each time your user logs in, generate something like a GUID. Save the GUID to a column in the user's record (like LoginToken or whatever) and then set their cookie to the same GUID. When they logout, clear the record's LoginToken. Then when a request comes in, you can just query your database for the user who has a LoginToken equal to the value in the cookie. It's safe to assume that by holding the token, the requestor is in fact the user represented by the token.
If a malicious user edits their cookie, they'll get nothing more than logged out, since you'd treat a not-found token the same as no token at all.
On the server, once you check a token, you then determine if that user has admin rights (usually by looking at their record).
As far as being able to modify script, that's just a fact of life. Your server code has to assume that every request is malicious. Before you do anything, verify their token and verify that they're allowed to do what they're requesting.
2 things:
Validate the data client-side for usability, but also do it server-side to prevent someone from tampering with the data
Encrypt cookies to make it harder to manipulate

Is there a way to verify the integrity of javascript files at the client?

I'm working on what aims to be a secure method of user registration and authentication using php and javascript but not ssl/tls.
I realise this may well be considered an impossible task that's been tried 1000 times before but I'm going to give it a go anyway. Every example I see online that claims to do it seems to have some huge fatal flaw!
Anyway, my current problem is verifying javascript at the client. The problem being that if my sha1 implementation in javascript is modified by some man-in-the-middle it's not secure at all. If I could just verify that the received javascript has not been tampered with then I think I can pull this off.
The real problem though, is that the only way to do things on the client side is javascript. Simple: write a javascript to verify the integrity of the other javascript files. Nope! Man-in-the-middle can just modify this file too.
Is there a way around this?
To secure your JavaScript, you must examine it in an guaranteed untampered environment. Since you can't create such an environment in the browser this is not possible. Your best option is to download the JavaScript via HTTPS. That isn't safe but better. Possible attack vectors left:
A virus can modify the browser to load some malicious JavaScript for every page
A keylogger can monitor what the user is typing
A proxy can act as a man-in-the-middle for an HTTPS connection. The proxy will actually decode what you send via HTTPS and encode it again (with a different certificate) for the browser.
A proxy can add iframes to the pages you send
Matt
I believe (despite the naysayers) that what you're asking is not impossible, merely extremely difficult. What you're asking is that code that is completely accessible to abuse nevertheless permits the user to identify herself to the server, and vice versa. One possible way is to use a zero-knowledge proof, which will leak no information to the eavesdropper (Eve). For example, the server might provide javascript that draws a representation of a graph that combines user provided information of no value to Eve on its own with server-provided information also of no value. The javascript may have been modified, but will either fail to provide the correct graph (at which point the user WALKS AWAY) or succeed. In the latter case, the user similarly provides 'zero-knowledge' evidence that they have an isomporphic representation of the graph; again, this either succeeds or fails. Also look at the SRP protocol, but the problem with this is that it's a patent minefield. See Practical Cryptography by Ferguson and Schneier. Jo
There's no way around it. As you said: if you cannot verify the source a man-in-the-middle attacker can replace anything the client receives, i.e. anything the client interprets and executes.
You say your only issue is a man in the middle modifying the javascript you use to perform a SHA1. I therefore guess you are using username + SHA1 of password for login....
That is completely insecure even with no Javascript tampering. Even though a man in the middle may not know the plain password if the javascript is not modified, he will know the hash, and he can perfectly use that hash to perform a login on his own by just replaying it.
Even if you include a salt / nonce, the man in the middle could still be able to use those tokens at the moment, and even steal the account by performing a password / email change.
Even ignoring this, and assuming you could actualy get around all that + actually get a javascript to test the integrity of a second javascript, how would you prevent that "verification script" from being tampered too? You keep depending on a script sent over an unsecure channel to assure security on such data (and could recursively go on for ever having a script that checks the integrity of a script that checks the integrity of a script...) all being perfectly tampered since they are sent over an unsecure channel.
The only way to do this would be to be able to build yourself a secure channel on top of http, which would need some client-side extras (a Firefox plugin / an ActiveX extension), but having native support for https that's just absurd.
as they are in the client you cannot access them.
This is the nature of the web pages...
try using important things in server side...
If your security architecture somehow requires functions to run in Javascript, then your security is flawed.
with JavaScript one can protect from passive network attacks (such as eavesdropping WiFi traffic), but you cannot protect yourself from active network attacks where the intruder is capable of controlling your HTTP response header and body data.
If you don't want to pay for the SSL certificate, you can create a self-signed certificate instead. However, this will only prevent passive network attacks, but is a lot easier than some hacky JavaScript implementations you ever create.
Essentially you need a CA signed SSL certificate to prevent active network attacks (a man in the middle).
You can only verify the integrity of Javascript files at the client if, and only if, server and client previously share a secret. That is most often not the case on the Internet. If such a secret is not available, then any attempt to verify transferred Javascript can be broken. It is a catch 22 situation.
Most often, people want to ensure JS integrity because it makes them feel like they can delegate security checks on the client side. In cryptography, there is a fundamental rule that should not be broken: never trust remote user input. Always double-check.
SSL/TLS can make middle-man attacks harder to achieve, but it is not watertight.

Categories