Should I validate/sanitize $_SESSION variables in php? - php

I'm building a quiz site, where I store some variables
(time taken to answer, which answer-option was chosen by the user etc etc) in $_SESSIONs after each question - where I put those stats into the DB only after the user finishes the quiz.
I've implemented a few if's to check if those $_SESSION variables are numbers (is_numeric()). Also I validate the length (strlen()) etc.
But is there a reason to do that?
Or is it enough just to real_escape_string() those before storing them
in MySQL?
Also if there would be many users, then won't that put a big load on
the server?

No, since you set them yourself.
Unless of course you deduce them directly from user input in which case the exact same rules that apply to every bit of user input apply.
There is nothing special about $_SESSION variables. You need to sanitize user input when you receive it from the user - regardless if you store it in a database, a session, or so on.
Like JPod suggested - when performing SQL queries - always use prepared queries which mitigate SQL injection.

Related

Is SQL injection possible without passing a variable into a database query in PHP? [duplicate]

This question already has answers here:
Can someone perform a SQL Injection based on session variables in php?
(5 answers)
Is putting a $_SESSION variable straight into SQL a security risk? [duplicate]
(1 answer)
Closed last month.
If I have a user input form, but the data from this is used purely to make comparisons in PHP, can it be subject to a SQL injection risk? I assume not, and that it is only where I want to pick up such data via POST or GET and then put it into a database query that it becomes a risk.
For example.
Lets say I return a dataset using a session variable of user_id created at login.
$sql="SELECT * FROM leads where user_id='".$_SESSION[user_id]."'";
No one can mess with the session variable so I am fine to just use this and a bog standard mysqli_query to return my result set, or so I gather.
I now have a small form with months of the year on a select box, and use echo htmlspecialchars($_SERVER["PHP_SELF"]); to refresh the page on form submission and filter the results of the report which are printed to the HTML page.
if($results = mysqli_query($link, $sql)){
while($row = mysqli_fetch_array($results )) {
if($row["time_stamp"]>$POST["select_box") { Do some other stuff...}
Is there no risk of SQL injection because I am not actually passing the select box value into a database query?
Or Does the mere fact that I am picking up data from a user input, via POST, and performing some kind of action with it expose me to risk?
Yes, this is an SQL injection risk.
You may assume that $_SESSION[user_id] is set by your login system. How confident are you about this? Is there no way an attacker could pollute your session data?
Is the user id guaranteed to be an integer? Or can your user id's be strings? If so, can they have content that would influence the syntax of an SQL query? Like could it contain a quote character?
There's also a hidden bug in your example. $_SESSION[user_id] uses a PHP constant as the key, and it isn't necessarily the same as $_SESSION['user_id'] if the constant has been defined to some string other than 'user_id'. Undefined constants in PHP default to a string value the same as the name of that constant, but if somehow the constant becomes defined to some other string, it could reference a different session variable.
These are admittedly obscure cases. Perhaps the risk is minimal. But why eschew the known solution to SQL injection, which is to use query parameters?
Besides that, you're almost always better off using query parameters instead of concatenating strings and variables. It leads to code that is easier to read and debug, and it's actually better for performance.
Re your comment:
You show comparing the result of the query to your POST data. That's after the query has already executed.
Your POST data cannot affect your SQL query, because you don't interpolate POST data into the SQL query.
I was focused on your use of $_SESSION because that's the only variable that could be involved in SQL injection in your example.
P.S.: Not related to your question, but I think you should use $_POST, not $POST, in your code if you want to reference the superglobal for POST input
This answer is an additional to Bill Karwin's answer which I agree with. However, you made an interesting point, nay, assumption here:
No one can mess with the session variable so I am fine
Oh? How come? This depends heavily that the rest of your PHP code is safe, your production environment is properly secured, dangerous scripts are avoided and system-editing native PHP functions are locked down.
You're server system / PHP system / Session system is probably at risk from a number of other factors such as cookie manipulation, CSRF, XSS, or even file system breach on your website account.
While these issues are massive in themselves, and many of them can lead to MySQL compromise anyway; don't assume just because one door appears locked that all doors are locked.
Your Edit :
... $_SERVER["PHP_SELF"] ...
Server PHP_SELF can be compromised and should not be used.
The fact you're making these assumptions above shows there's a non-zero risk to your system and so you should be using the safest SQL interaction methods you can.

Does a session variable($_SESSION) require any type of sanitiziation

I've got a register form which works without issues, but recently it has been pointed out to me that it's a bad habit for UX , for example, if an account already exists, and I redirect the user back to the registration page, without re-populating the form he filled and only display an error message.
So I quickly figured out a nice way to fix this, if after the initial registration data checks out and an account with the respective e-mail already exists, I could just create a $_SESSION storing the $_POST data, and destroy it after re-populating the user's form.
Now my question is: are $_SESSION variables vulnerable to any type of attack, or I can go ahead and store the raw input data inside the $_SESSION, and escape it with htmlspecialchars() when re-populating the form ?
Variables in session are not vulnerable to attacks within the session. However, using those variables in other places may open up holes. For example, just because you put a get/post variable in session doesn't mean that it magically can be used directly in a query. It could still cause SQL injection issues. When considering stuff like this, you have to think about where the data originated. If it started from some sort of user input, consider it dirty.
The only place this might be a problem is if the data sent is really large and you are just blindly assigning $_SESSION['POST'] = $_POST;. There shouldn't be an issue with overflow or stuff like that. The problem will be more that php has to unserialize the data at the start of a request and reserialize at the end (typically only if a change has happened). This unserialize/serialize takes time (it may be quick, but still). I would suggest just assigning only the values you want to save.
It is hard to say exactly. But I am about 100% sure the answer is no they aren't really vulnerable. That is assuming that you can destroy the session almost immediately. In this case you would create the session, redirect the user back to the old page, check for session vars, set the vars in the correct location (which you could just do with plain text in this case) and then destroy session. The session would only be alive for about 10seconds.. a minute max? and noone would really have enough time to pull from the server. If they are listening to traffic already you are in more trouble this.
Had to move to answer because that was too long...
You may be able to do a check for user name with ajax BEFORE they ever submit however. That would be better. Don't allow them to submit if the email is already existent. Just submit based off keyup or something.
No, session variables are stored on the server through a variety of options such as saved to disk, shared through a redis or memcached store, and so on.
Even if this data were to be compromised I don't really see how sanitation would protect anything or mitigate the negative effects of such an attack.
If you really are worried about such a thing, you can destroy the temp session variable after you're done using it.

Sanitizing PHP Variables, am I overusing it?

I've been working with PHP for some time and I began asking myself if I'm developing good habits.
One of these is what I belive consists of overusing PHP sanitizing methods, for example, one user registers through a form, and I get the following post variables:
$_POST['name'], $_POST['email'] and $_POST['captcha']. Now, what I usually do is obviously sanitize the data I am going to place into MySQL, but when comparing the captcha, I also sanitize it.
Therefore I belive I misunderstood PHP sanitizing, I'm curious, are there any other cases when you need to sanitize data except when using it to place something in MySQL (note I know sanitizing is also needed to prevent XSS attacks). And moreover, is my habit to sanitize almost every variable coming from user-input, a bad one ?
Whenever you store your data someplace, and if that data will be read/available to (unsuspecting) users, then you have to sanitize it. So something that could possibly change the user experience (not necessarily only the database) should be taken care of. Generally, all user input is considered unsafe, but you'll see in the next paragraph that some things might still be ignored, although I don't recommend it whatsoever.
Stuff that happens on the client only is sanitized just for a better UX (user experience, think about JS validation of the form - from the security standpoint it's useless because it's easily avoidable, but it helps non-malicious users to have a better interaction with the website) but basically, it can't do any harm because that data (good or bad) is lost as soon as the session is closed. You can always destroy a webpage for yourself (on your machine), but the problem is when someone can do it for others.
To answer your question more directly - never worry about overdoing it. It's always better to be safe than sorry, and the cost is usually not more than a couple of milliseconds.
The term you need to search for is FIEO. Filter Input, Escape Output.
You can easily confound yourself if you do not understand this basic principle.
Imagine PHP is the man in the middle, it receives with the left hand and doles out with the right.
A user uses your form and fills in a date form, so it should only accept digits and maybe, dashes. e.g. nnnnn-nn-nn. if you get something which does not match that, then reject it.
That is an example of filtering.
Next PHP, does something with it, lets say storing it in a Mysql database.
What Mysql needs is to be protected from SQL injection, so you use PDO, or Mysqli's prepared statements to make sure that EVEN IF your filter failed you cannot permit an attack on your database. This is an example of Escaping, in this case escaping for SQL storage.
Later, PHP gets the data from your db and displays it onto a HTML page. So you need to Escape the data for the next medium, HTML (this is where you can permit XSS attacks).
In your head you have to divide each of the PHP 'protective' functions into one or other of these two families, Filtering or Escaping.
Freetext fields are of course more complex than filtering for a date, but never mind, stick to the principles and you will be OK.
Hoping this helps http://phpsec.org/projects/guide/

Can someone perform a SQL Injection based on session variables in php?

Basically I am making a web application and I am going through the security of it to make my app as robust as I can.
Once you're logged in to my app I track that user based on session variables.
When SQL is performed it takes the users session variable to see who they are for example.
$name = $_SESSION['user_name'];
A example query would be something like this..
$query1 = "SELECT * FROM tableName WHERE userName = '$name'";
From reading online sites say things like I must not use "user input in SQL statements." Am I right in thinking that because I am using session variables the user does not have direct access to the sql statement or is session variables still "user input"?
If not should I just go through the normal SQL Injection prevention methods like...
Input validation (authenticating the data based on length, syntax
etc)
Checking user privileges making sure users have the least
privileges.
ect..
Thanks in advance for any comments anyone makes.
It doesn’t matter where the data came from as in any case you have to ensure that the data is interpreted as intended.
And one of the easiest way to ensure that is using parameterized statements, where the SQL code and parameter values are passed separately so that a parameter value can’t be mistakenly interpreted as SQL.
Prepared statements implement this parameterization, either native or emulated. With them you don’t have to worry about whether a value may be influenced by a user’s input.
Always escape input. What if their name is "David O'Connor" or something.
This name is assumedly user supplied, so do it.
Anyway, you shouldn't be directly issuing SQL queries, a function should be building them for you (or an ORM).
Am I right in thinking that because I am using session variables the user does not have direct access to the sql statement or is session variables still "user input"?
The problem you might have in your example is that the username might be something controller by the user. They might be able to change it or choose it depending on your application requirements.
I think the simplest way to prevent surprises is stop thinking too much and just protected your queries agaisnt SQL Injection.
I'm no expert on PHP, but I think you have prepared statements that will help you dealing with this security issue. Just use it. (it should be a slogan, "prepared statements, just use it." :D)
Any login/create-user page you have should do input validation before writing the userName column in your database and writing $_SESSION['user_name'].
AFTER that, your $_SESSION variable is safe. You have to do validation checks somewhere in the process:
Input -> store in database/session -> use
I recommend at the 1st arrow. Then the code snippets you wrote in the question are perfectly fine.
Am I right in thinking that because I am using session variables the
user does not have direct access to the sql statement
correct. $_SESSION-vars are stored on your server-filesystem and unless you introduce user-input ($_GET & $_POST, for example) into them there is no actual way of manipulation for these. If you generate $_SESSION['user_name'] without actual userdata you're well off. The hard part is getting the username without parsing input - one would be advised to use HTTP-data-filtering frameworks for these kinds of jobs.

user data database structure

I'm running a basic website with some user accounts (no cookies, php session system.).
I'd like to store some data generated by the user only visible for themselves.
For the moment I store the data from all users in one table, with an extra column for identifying (this is an input from php session user-id). (We are talking about max. 50-100 keys per user).
On data request I have an extra parameter (AND "user-id"=x) in the mysql query.
Is this a safe (there is no sensitive data on the site, but the accounts have to be private anyway) way of storing data?
Are there better ways to handle this? (I read about separate databases etc.) and if so, how?
thx,
M.
Is this a safe (there is no sensitive data on the site, but the
accounts have to be private anyway) way of storing data?
There is nothing wrong in having the user-id=x in your mysql query to get the data from the table. But make sure you are not directly reading this value from your query string and appending to the mysql query without doing proper sanitization and cleaning. Otherwise you will be a vicitm of SQL injection.
Are there better ways to handle this? (I read about separate databases
etc.) and if so, how?
I don't see any reasons to have seperate database to handle this. You can use your current database. If needed, you may create additional tables for this. I am not sure what is your db schema and entity relations. So i am not in a position to tell you how to do that. Look into your tables and make sure it is normalized.
If you want the data stored to be seen only by that particular user, You probably want to check in whether the current logged in user id ( get from the session variable ?) is same as of the userId of the db record. May be you can compare with the "CreatedById" field value if you have one.
I believe this link is a must read if "SQL injection" is a new term for you.
http://www.unixwiz.net/techtips/sql-injection.html
Just use the PHP $SESSION.
By using session_set_save_handler you can define your own session storage method, which could be a MySQL database for instance.
The values in a session can not be altered by the user directly (as you can with cookies). So this approach is perfectly safe, so long as you don't expose the PHPSESSID cookie value anywhere.
No way is 100% safe. Your method sounds very insecure but I cannot see your code. If your are cleaning the input correctly to avoid mysql injection and also there is no way for a user to specify a key of another user then you may be ok.

Categories