Is it a good practice to store error messages in SESSION? For example after a redirect. Passing in through url isnt a solution for me...
I am wondering if it is a good solution... because..
Would a concurent submit of user cause problem? (A long time-taking post, while ajax content is obtained from another tab) that may mess up the session! Or that is impossible to happen?
If user makes a request and it fails for some reason to display the page then the message may be shown at an irrelevant page!
So? Any alternatives??
For example when using POST/redirected/get pattern
When storing error messages in the session, you must take care, that two request dont overwrite the other ones message, before it is displayed. And you must take care, that a page, that should display a message, only displays its own message.
You should show errors, when they occur and not redirect before. Also there is no reason to redirect in such a situation.
Is it a good practice to store error messages in SESSION? For example after a redirect.
Not in general. Session data should be data that matters for a significant period, errors are generally a result of a single request and the details don't need to persist.
Storing that sort of data in a session is just an invitation to race conditions.
why dont you assign them an specific id like error_id=2 and send them through url?
or is this also not possible in you case?
you could also send an error id through session...
It is not uncommon to store error messages in session, especially in cases where there can be multiple redirects. Zend framework has something like flash messenger which kind of does that.
Anything that is in session would stay in session until you destroy it or session times out. The best practice is store the error messages in session, then when the page is loaded where the error message needs to be displayed, your code would get the messages from the session and display them if they exist. After the error messages are displayed you would need to delete them from the session, otherwise each time the user goes to this page they would see the same error messages popping up again and again.
The best approach is to display and delete.
I believe you should not run into any problem ever if you use this approach. The reason is that if an incorrect form is submitted it would always have errors in it and it will always try to store those error messages in session and display them accordingly does not matter how many times they have added/deleted in session. I hope this all makes sense.
Also when you store session error messages you need to store them smartly so that the backend knows that these error messages are stored for which form.
Focus on the user! All your development efforts want to provide the best UX possible.
The first question is, why do you need messages at all?
In case of a successful request, you want the user to know that his request was successfully executed.
In case of an erroneous request, you can distinguish: if the request may be altered by the user to turn into a successful request, then show a helpful error message (e.g. a simple form submission). If the request may not be altered by the user, be as informative as possible why the request failed (e.g. "Couldn't execute as service XY is not available. Please contact support etc.").
Easy: Erroneous request that may be altered:
In case of an erroneous request where the user may alter the request, don't save it in the session and directly render the page where the user may correct his request.
Difficult: Successful request or erroneous request that may not be altered:
Here you may generally want the user to not be able to execute the exact same request again after hitting F5 or taking similar actions, hence you redirect the user. In this case I personally favor the solution with a flash messages component (see Symfony Docs or Zend Docs for an example). In general, this technique does not lead to race conditions if your applications meets these assumptions:
Your HTTP requests fired from the browser are executed fast. A user does not have a real chance of firing a second request in the meantime.
Your AJAX calls either do not influence the flash messages - or, if you return structured data (XML, JSON) you may include a special section for flash messages, that are then being rendered by Javascript.
Now, to minimize error rates you can do the following:
Store the timestamp when you added the flash message. Don't display old messages (e.g. > 1 minute). A mobile user may loose connection and then retry. What state does he expect the application to be in?
Don't ever let the HTTP requests between your user and your server take long. If you need to perform long computations, try offloading things to a background worker and show the status of processing to the user.
Summing up: If you have general good practices concerning your HTTP communication in place, then the user is unlikely able to mess up flash messages. Weigh the pros and cons and focus on the user, not the complexity of your implementation, as there are methods to cope with that.
Generally speaking:
Try to put as much on the client-side (javascript and cookies) and try to store as less as possible on the server-side.
This includes the SESSION variable, which in the best scenario should contain only user id.
If the message is after redirect, you could add a request variable that could index the message and to show it that way.
Instead of storing in a session, you could pass an error code in the URL that you would then use to look up the error. I've user bare-bones exception classes for this kinda thing:
class MyException extends Exception
{
const USER_NOT_FOUND = 'The requested user was not found';
// ...
}
Then your redirected url would be something like /controller/action/error/USER_NOT_FOUND and you'd use that to look up the message:
echo constant('MyException::' . $error);
You don't need to use an Exception class for this, but it allows you to keep things really tidy
if ($errorState) {
throw new MyException(
MyException::USER_NOT_FOUND
);
}
Related
I asked a similar question before, and the answer was simply:
if JavaScript can do it, then any client can do it.
But I still want to find out a way do restrict AJAX calls to JavaScript.
The reason is :
I'm building a web application, when a user clicks on an image, tagged like this:
<img src='src.jpg' data-id='42'/>
JavaScript calls a PHP page like this:
$.ajax("action.php?action=click&id=42");
then action.php inserts rows in database.
But I'm afraid that some users can automate entries that "clicks" all the id's and such, by calling necessary url's, since they are visible in the source code.
How can I prevent such a thing, and make sure it works only on click, and not by calling the url from a browser tab?
p.s.
I think a possible solution would be using encryption, like generate a key on user visit, and call the action page with that key, or hash/md5sum/whatever of it. But I think it can be done without transforming it into a security problem. Am I right ? Moreover, I'm not sure this method is a solution, since I don't know anything about this kind of security, or it's implementation.
I'm not sure there is a 100% secure answer. A combination of a server generated token that is inserted into a hidden form element and anti-automation techniques like limiting the number of requests over a certain time period is the best thing I can come up with.
[EDIT]
Actually a good solution would be to use CAPTCHAS
Your question isn't really "How can I tell AJAX from non-AJAX?" It's "How do I stop someone inflating a score by repeated clicks and ballot stuffing?"
In answer to the question you asked, the answer you quoted was essentially right. There is no reliable way to determine whether a request is being made by AJAX, a particular browser, a CURL session or a guy typing raw HTTP commands into a telnet session. We might see a browser or a script or an app, but all PHP sees is:
GET /resource.html HTTP/1.1
host:www.example.com
If there's some convenience reason for wanting to know whether a request was AJAX, some javascript libraries such as jQuery add an additional HTTP header to AJAX requests that you can look for, or you could manually add a header or include a field to your payload such as AJAX=1. Then you can check for those server side and take whatever action you think should be made for an AJAX request.
Of course there's nothing stopping me using CURL to make the same request with the right headers set to make the server think it's an AJAX request. You should therefore only use such tricks where whether or not the request was AJAX is of interest so you can format the response properly (send a HTML page if it's not AJAX, or JSON if it is). The security of your application can't rely on such tricks, and if the design of your application requires the ability to tell AJAX from non-AJAX for security or reliability reasons then you need to rethink the design of your application.
In answer to what you're actually trying to achieve, there are a couple of approaches. None are completely reliable, though. The first approach is to deposit a cookie on the user's machine on first click, and to ignore any subsequent requests from that user agent if the cookie is in any subsequent requests. It's a fairly simple, lightweight approach, but it's also easily defeated by simply deleting the cookie, or refusing to accept it in the first place.
Alternatively, when the user makes the AJAX request, you can record some information about the requesting user agent along with the fact that a click was submitted. You can, for example store a hash (stored with something stronger than MD5!) of the client's IP and user agent string, along with a timestamp for the click. If you see a lot of the same hash, along with closely grouped timestamps, then there's possibly abuse being attempted. Again, this trick isn't 100% reliable because user agents can see any string they want as their user agent string.
Use post method instead of get.Read the documentation here http://api.jquery.com/jQuery.post/ to learn how to use post method in jquery
You could, for example, implement a check if the request is really done with AJAX, and not by just calling the URL.
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
// Yay, it is ajax!
} else {
// no AJAX, man..
}
This solution may need more reflexion but might do the trick
You could use tokens as stated in Slicedpan's answer. When serving your page, you would generate uuids for each images and store them in session / database.
Then serve your html as
<img src='src.jpg' data-id='42' data-uuid='uuidgenerated'/>
Your ajax request would become
$.ajax("action.php?action=click&uuid=uuidgenerated");
Then on php side, check for the uuid in your memory/database, and allow or not the transaction. (You can also check for custom headers sent on ajax as stated in other responses)
You would also need to purge uuids, on token lifetime, on window unload, on session expired...
This method won't allow you to know if the request comes from an xhr but you'll be able to limit their number.
I have a website that's written in PHP and uses intense level of JS coding. One of my clients has a very strange error. The site is empty and nothing is displayed. I can not reproduce the error in spite i use the same browser, the same OS and have much the same addons and firewall and antivirus.
So i would like to catch every one PHP and JS error or warning and put it in the error log (best - to database). Is there any ready, simple solution to acomplish this? I address this question to experienced web-developers.
Or is there any way to dump every data about user session while the error occurs that is easy to acomplish by no-tech user? I see it this way: when the user has this error, he clicks something (for example in extension or something) and this sends all session, error informations to me so I can figure out what is going on. Do you know any solution of this kind?
mplungjan's idea is good.
I would also ask the client to view the source of the page and send that to me to make sure it looks OK.
Your web server (e.g. apache) should keep a log file of every single PHP request and tell you whether errors occurred.
I don't know if there is a way to report javascript errors back to your server. If you were able to catch the error and send an AJAX request in your error handler to get logged on your server, that would work. But I think that some javascript errors (like syntax errors?) can not be caught with catch. I would ask the client to open the javascript console (or whatever it is called in his browser) and tell me all the errors he sees. You should eliminate all the errors eventually, and a good strategy to do that would be to focus on the first error that occurred.
I would run the page through a w3c validator to see if it is valid HTML/CSS.
Also, you should try the universal technique of simplifying the code down to the simplest possible thing that should work but doesn't work. That will either let you find the problem or produce something that is so small and simple that you can post it to Stack Overflow.
You need to differ between two types of errors: Client-side and Server-side.
A blank page can be both, but I would think most likely this is server-side.
For server-side errors you can log every error and even add own information like the session by registering your own error handler. You then can log errors into the database and append the session and request information as well as providing a backtrace. This will enable you to obtain more information.
For client side, David Grayson's answer has a suggestion.
I use jquery POST calls to fetch data to display in various sections of my websites.
Usually, they POST to a single 'ajax_handler.php' page which reads the requested parameters and returns the relevant data. Typical parameters might be 'get_order_details',123
How could I stop users posting to the script to try and retrieve data which they should not be able to? I know I can verify that data belongs to the currently logged in user, for instance, but how could I stop users 'guessing' that there might be a handler for 'get_some_info'?
Since users could even run javascript straight from the URL this seems to be a major security problem to me as the client would have access to SESSION and COOKIE data (which I would otherwise use for security).
I guess I could start by naming each of my handler identifiers with a random string, but I'd prefer not to compromise the legibility of my code.
Naming your handlers with a random string is security through obscurity and while it might slow someone down, it won't stop them.
The best thing to do is to store a session or database checksum each time a page is accessed. Then also send that same checksum along with the POST content. When the form is submitted, through AJAX or otherwise, you compare the checksums. If they don't match then you know the user wasn't on the appropriate page and is trying to access the handler through some other method.
For each user, you can store within your database which data he should be able to view and which he shouldn't. Each time you get a request, e.g get_order_details, you should call a function which does your security checking to make sure both that the user is logged in, and that he has access to the 'get_order_details' method or any other method he is trying to access.
What you're trying to do is fundamentally antithetical to how the Internet works. You can't and shouldn't attempt to limit the way users make requests to your services. This is an extremely outdated and backwards way of thinking. Instead of trying to limit the ways in which users can use your service, be thankful that they're using your service in the first place.
All you can do is make sure that the user is authenticated and has access to the record they're requesting. If you're using a system which has no authentication, and you want to prevent users from "guessing" the ID of the next record, don't use sequential IDs. Use randomly generated strings as your identifier. Make them sufficiently long that it will be difficult for users to stumble upon other records.
I currently check every GET and POST variable with isset() and throw exceptions when isset() returns false.
Example 1:
if(!isset($_GET['some_var']))
throw new Exception('GET variable [some_var] is not set.');
$someVar = $_GET['some_var'];
Example 2:
if(!isset($_GET['some_num']))
throw new Exception('GET variable [some_num] is not set.');
if(!ctype_digit($_GET['some_num']))
throw new Exception('GET variable [some_num] is not a number.');
$someNum = $_GET['some_num'];
In my production application I have a global exception handler that posts exceptions and errors to a log file and then redirects to a generic apology page.
Is this an okay practice? Are descriptive exception and error messages such as the ones above security risks (is it possible that a hacker would be able to read the exception notice and then use that information to manipulate my scripts)?
Thanks!
Logging errors and suppressing output is exactly what you should be doing. Error reporting can be nasty..
In OWASP top 10 for 2007 there is Information Leakage and Improper Error Handling, however this was removed in 2010. By setting dispaly_errors=On in your php.ini you become vulnerable to CWE-200. The full path of your web application will be divulged to the attacker. To make matters worse, by having error reporting enabled it makes it easier to find SQL injection by looking for sql error messages.
When combining this on a PHP/MySQL application you can perform a very serious attack
$vuln_query="select name from user where id=".$_GET[id];
If
http://localhost/vuln_query.php?id=1 union select "<?php eval($_GET[e])?>" into outfile "/path/to/web/root/backdoor.php"
Which makes this full query:
select name from user where id=1 union select "<?php eval($_GET[e])?>" into outfile "/path/to/web/root/backdoor.php"
I would make sure display_errors=Off and that file FILE privileges have been revoked to your web application's MySQL user account.
Displaying detailed errors to a user can be a security risk. Since in this case, they're only being written to a log file and the only data the user gets is a generic page which reveals nothing, you can be as descriptive as you like and you reveal nothing unless the log is compromised.
"is it possible that a hacker would be able to read the exception notice and then use that information to manipulate my scripts?"
Maybe.
Typically, you want to give the least amount of information possible to the end user in an error condition. In this case, if you tell someone a particular get variable doesn't exist, then they might try supplying random values to that variable to see how the app behaves.
Of course, you also have to balance this against the needs of your real users. If the variable is one that they would normally have control over, then giving the response about a problem with the value is perfectly acceptable.
UPDATE
Having recently run into a spate of web API's that seem to think throwing generic error messages is the way to go I want to update this slightly.
It is critical that web API's give an appropriate amount of information back to the consuming system so that they can figure out what's wrong and fix it.
In one recent case for a payment processing API their documentation was simply wrong. The test transaction data that they showed consistently returned with "Server Error 500" and we had no recourse but to get one of their developers on the phone and painstakingly step through each and every element in their XML. Out of 50 elements, only one had the same name as what was in their "developer documents"
In another integration we were given "Server Error 402". -- This one was NOT a payment gateway. Although never referenced in their doc's, apparently that message meant that a JSON parameter was missing. Incidentally, it was a parameter not referenced in their docs and again required time with their developer to identify it.
In both of the above cases it would have been incredibly helpful if the error message had responded with an example of a valid document post. Similar to how the old Unix/DOS commands would come back with the help info when you passed bad parameters. I really don't want to talk to other programmers. I know their time is expensive and they would much rather do something other than answer a support call; but more to the point, if I'm working at 10:00PM and need an answer RFN then waiting until a programmer can get on the phone the next day is rarely an option.
Usually it is considered insecure to print out PHP system error messages on a production server instead of silently logging it.
Though I can't find anything dangerous in the generic apologies page.
So it's not a complicated matter at all, but was wondering how the Stackoverflow community would tackle this.
I wrote a facebook-style wall type thing where users enter their "status", it gets processed via jQuery Post and upon success returns a success message.
Prepending the new message to the Wall Stream would make sense, however, if another user had entered a message before the submission it would fail to show the correct time sequence...
I guess my question is this.
Should I query the latest Wall Messages inside the PHP file and echo back the entire result? That way when jQuery receives the callback it can delete whatever is in the Wall Stream and update with the new content?
I am assuming a bit on the details and purpose of your app but I probably would not bother doing anything fancy. Typing a status is pretty quick and the probability someone else beat you to the race is somewhat of an edge case yet adds complexity and a database performance hit. Also the error of showing the wrong time sequence in my opinion is forgivable in the rare case that it does occur and the user notices. There's probably bigger fish to fry somewhere else in your app.
If the nature of the app or site makes correctness important, then a possible solution is to post the id of the most recent message that has already been loaded on the client side so that the server can respond with the contents/details of messages posted after that id so the new messages can be rendered for the client. I would post an id instead of a timestamp so that there's no need for synchronization between client and server time.
Perhaps, you could pass a timestamp of last status update back to server and return all changes since that, so you could prepend all that is new.