可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I know this has been asked billions of times, but I'm super paranoid/OCD about the security of my coding. I'm working on a little project. The session data will only contain:
user_id 1
user_name MyUsername
logged_in true
csrf_token 87cc51ee94178df79cccce2aebc45d53
Here's my code. Is it secure enough to use on a small CMS?
session_start();
ini_set('session.cookie_httponly', 'On');
ini_set('session.cookie_secure', 'On');
ini_set('session.use_cookies', 'On');
ini_set('session.use_only_cookies', 'On');
$rand = rand(1, 10);
if ($rand != 1 || $rand != 3 || $rand != 5)
session_regenerate_id();
$user_ip = md5($_SERVER['REMOTE_ADDR']);
$user_agent = md5($_SERVER['HTTP_USER_AGENT']);
if (isset($_SESSION['user_ip'], $_SESSION['user_agent'])) {
$session_user_ip = $_SESSION['user_ip'];
$session_user_agent = $_SESSION['user_agent'];
if ($session_user_ip != $user_ip || $session_user_agent != $user_agent) {
unset($_SESSION);
session_destroy();
die('Error');
}
} else {
$_SESSION['user_ip'] = $user_ip;
$_SESSION['user_agent'] = $user_agent;
}
Then to call the sessions:
$_SESSION['user_id'] = 1;
$_SESSION['user_name'] = 'MyUsername'; // etc.
Extra Info
I'll be using the session data to check if user has permissions to do something. Example: if ( user_has_perm( $_SESSION['user_id'] ) )
Thanks for your help in advance.
回答1:
Session security risks come from three different possibilities:
- Prediction
- Capture
- Fixation
Prediction would mean that someone that's not the user for whom the session was created guessed their session ID. The chances of that happening are almost 0, although they do grow as more users use the site simultaneously.
With your code, you would make that risk even lower because it would only work if the attacker shared the user agent and the ip of the predicted session. But the difference is trivial in this case.
Fixation would mean that an attacker can create a session and then force another user into using their session. In this case it would depend: If the attacker knows that you are doing it and they fake the user agent and ip of the client, they could fixate the session. Or if they share ip and user agent.
And finally we have session hijacking, probably the most common method of the three. In this case an attacker would somehow gain access to the session id of a valid logged in user, and then use it to log in to their account. As with the previous method, this would only work for them if they know that you are checking the ip and user agent, and faked the same ones as the user. The technique you are using is not unique, and some attackers might fake them just in case.
That being said, is it secure? Yes and no
If you are obsessed with security, the answer is always the same: Use SSL
Unless your code is open source, almost anything you do that changes the behavior of the php sessions will be secure enough.
The only exception to that would be really popular sites that will attract the attention of hackers.
There is some very good documentation on this topic available:
- http://phpsec.org/projects/guide/4.html
- PHP Session Security
- http://www.squarefree.com/securitytips/web-developers.html#CSRF
回答2:
I'm not a security expert. However, I humbly doubt that your security enforcements will bring substantial benefits.
If there's one who can steal the session ID of your users, for example by eavesdropping an unencrypted wireless network, I bet he can steal also the username and password your users send to your server when they authenticate. Once he has the access credentials, the attacker can login the day after, or a week after, and will have his "safe" - and 100% valid - session to play with.
I believe there is no session security without channel security. If you use SSL, you ensure that the session ID is sent only via cookies (you're already doing it) and your sessions expire soon, I believe you are reasonably safe, and safer than making these enforcement on an insecure channel.
回答3:
Firstly, you have a mistake in the session regenerate code. The following if will always evaluate to true:
if ($rand != 1 || $rand != 3 || $rand != 5)
If $rand
is not 1, it returns true. If $rand
is 1, then it's not three, and it returns true. You probably meant to use an and
here.
Secondly, you don't need to MD5 the user_ip
, or the user_agent
strings. If someone can access the session data on your server directly, you're so deep in it that hashing that data won't save you.
CLARIFICATION: As SDC and crush point out in the comments, MD5 is good for hashing passwords if you hash it with a salt. This means that your user's passwords are generally still secure, even if a SQL Injection attack succeeds and your database is exposed to the world. However, if your server is compromised, and the salt is compromised, then it becomes possible to generate a set of known hashes, and to attempt a reverse lookup of a specific password. Bottom line? Hash your user passwords, with a salt.
Thirdly, most security holes don't come from spoofing sessions. They come from poor input checking. A book like Essential PHP Security should be a good introduction to the kind of input checking you should do in a PHP project. Failing that, at least read the security section of the PHP Manual. Pay attention to the SQL Injection bit. It's cool!
Finally, I fully agree with the other poster that you should use SSL to secure communication to your website.
回答4:
To be honest, I think you're being over-cautious, but not in a very useful way.
If you're really worried about session security, don't try to do it yourself. Use a PHP security patch like Suhosin. Let it do all the hard work for you. Suhosin is a well-established patch for PHP. It includes stuff that deals with all the ways a PHP session can be hacked. If you've got it installed, then you don't need to be doing anything extra to secure your session. If you don't have it installed, then you definitely can't claim to be super paranoid about security!
So in short, install Suhosin (if you haven't already), and forget about it.
But just for completeness, I'll make a few comments on at your actual code, just to point out a couple of things:
I'm not sure why you think MD5 hashing makes any difference. MD5 hashes can be cracked in seconds, so having them in any kind of security function is completely arbitrary. It may as well be plain text. That said, I don't really see the need for them to be anything other than plain text anyway -- if a hacker has managed to get hold of the session data to be able to read the IP address it contains, then you're already beyond worrying about whether they know the IP address or not.
回答5:
They are just only two major session attacks
1.) Session fixation Attacks.
This can be prevented by using session_regenerate_id()
2.) Session Hijacking:
This can be prevented via data encryption by using SSL Certificates. your site will now run on https and not http.
3.) If you are on a shared server where CloudFare or JailRoot is not implemented. You can show to store your sessions in a database as opposed to default file system storage.
With this three implementations, Let me see that hacker who claims to hack usesrs session...
回答6:
Select image to upload:
";
$res=mysql_query("SELECT `id`, `FirstName`, `LastName`, `Address`,
`Password`, `Repassword`, `Birthday`, `Gender`, `user_image` FROM
`registration`") or die(mysql_error());
while($row=mysql_fetch_array($res))
{
$id=$row['id'];
$firstname=$row['FirstName'];
$user_image=$row['user_image'];
$page.="
$firstname";
}
$page.="
";
$res_post=mysql_query("SELECT post_info.post_info_id,
post_info.id, post_info.post_info_desc, registration.FirstName FROM `post_info`
join `registration` WHERE post_info.id = registration.id order by
post_info.post_info_id desc") or die(mysql_error());
while($row_post=mysql_fetch_array($res_post))
{
$post_id = $row_post ['post_info_id'];
$post_desc = $row_post ['post_info_desc'];
$id = $row_post ['id'];
$FirstName = $row_post ['FirstName'];
$page.="
$FirstName
$post_desc
";
}
$page.="
";
include('include/main_file.php');
?>
回答7:
<?php
session_start();
$con=mysql_connect("localhost","root","");
$seldb=mysql_select_db('myfreind', $con);
$email=$_POST['txtEmail'];
$password=$_POST['txtPass'];
$res=mysql_query("SELECT `id`, `FirstName`, `LastName`, `Address`, `Password`, `Repassword`, `Birthday`, `Gender` FROM `registration` WHERE
`Password`='$password' and `FirstName`='$email'");
$num=mysql_num_rows($res);
if($num==1)
{
$row=mysql_fetch_array($res);
$id=$row['id'];
$firstname=$row['FirstName'];
$_SESSION['id']=$id;
$_SESSION['FirstName']=$firstname;
//echo $_SESSION['id'];
header('Location:main.php');
}else
{
header('Location:index.php?error');
}
?>