Thursday, April 21, 2011

session tracking for users

I want to make it hard for a hacker to get my users information. I will use this method I found on the page I mentioned yesterday.
http://phpsec.org/projects/guide/4.html
This page also uses this great article about securing sessions:
http://shiflett.org/articles/the-truth-about-sessions

First I will check to see if the user identifier is stored in the session. If it is then they are logged in since I will only set this variable after they successfully enter their user name and password. When they login successfully I store the IP address and their browser agent and a secret string of text that can be the same for all users or I could use a combination of username and random characters. This second identifier will be passed in the URL so the attacker would need more than just the sessionid to impersonate them. Is this secure?
Then a hacker will have to steal the session_id and impersonate them and have the same IP address and browser agent string converted to a sha1 fingerprint and store it in the url. So this would be an example:
sha1("Mozilla/5.0 GeckoSECRET_PHRASE78.0.23.128")
this is: 3fb195ec6fe52981918b9065b8362a0efed8858f
then when you are logged in you would be at: http://example.com/admin.php?secret_fingerprint=3fb195ec6fe52981918b9065b8362a0efed8858f
This script can be included in any page. I call it validate_login.php
if(!isset($_SESSION)) session_start();
//starts the database connection
require_once("includes/db.php");
//stores the log function
require_once("includes/functions.php");
$phpself = $_SERVER['PHP_SELF'];
//the user_identifier will be a 13 character random string of text like DA3591BAC915 that is stored for each user to identify them with something besides the primary key
if(isset($_SESSION['USER_IDENTIFIER'])){
if ($_GET['secret_fingerprint'] != sha1($_SERVER['HTTP_USER_AGENT'] . "SECRET_PHRASE" . $_SERVER['REMOTE_ADDR'])){
/* Make them login again */
include('login.php');
exit();
}
} else if(isset($_POST['submitlogin'])){
$user = mysql_real_escape_string($_POST['user']);
$password = sha1(mysql_real_escape_string($_POST['password']));

//authenticate user
$sql = "SELECT user_identifier FROM user WHERE user = '$user' AND password = '$password'";

$result = @mysql_query($sql);
if(!$result) {echo "There was an error";log(mysql_error($con)." sql: $sql ");exit();}
if(mysql_num_rows($result) == 0){echo "You need to user the right user or password";include('login.php'); exit();}
$row = @mysql_fetch_array($result);
$_SESSION['USER_IDENTIFIER'] = $row[0];

//only pass this in the url so it has to exist in a GET parameter for the user to be allowed to stay logged in
$secret_fingerprint = sha1($_SERVER['HTTP_USER_AGENT'] . "SECRET_PHRASE" . $_SERVER['REMOTE_ADDR']);

//send them to the page that requested to login
header('Location: ' . $_SERVER['PHP_SELF'] . '?secret_fingerprint='.$secret_fingerprint);
exit();
} else {
//they aren't logged in yet : show the login form here
include('login.php');
exit();
}

Here is an example page that requires the use of above authentication plus has a logout link and a link to another page. When we go to another page we have to include the secret finger print that has their IP address and browser hashed with an sha1 hash or they will not be authenticated and will have to log in again.
This page is admin.php
<?php
include('validate_login.php');
?>
<h1>You are logged in now</h1>
<a href="logout.php?logout=1&to=<?php echo $phpself;?>">Log off</a><br />
Go to another secure page on the <a href="anotherpage?secret_fingerprint=<?php $_GET['secret_fingerprint'];?>">site</a>.


This also has a logout link that logs the user out. Here is a good logout script:
logout.php
<?php
if(!isset($_SESSION)) session_start();
if(isset($_GET['logout'])){
session_destroy();
unset($_SESSION);
$to = $_GET['to'];

//send them to the page they were being sent to
header('Location: http://'.$_SERVER['SERVER_NAME'].':/'.$to);
exit();
}


Here is the login script login.php:
<form action="<?php echo $phpself;?>" method="post">
<p><label>Email<br /><input type="text" value="<?php if(isset($_POST['user'])) echo $_POST['user'];?>" name="user"></label></p>
<p><label>Password<br /><input type="password" name="password"></label></p>
<p><label><input type="checkbox" name="rememberme"> Remember Me</label></p>
<input type="submit" value="Log In" name="submitlogin"></p>
</form>
<a href="#">Lost your password?</a>


If you need a registration script just leave a comment.

Wednesday, April 20, 2011

Jquery selectors are cool

http://www.codylindley.com/jqueryselectors/
These are very useful for web programming with javascript Jquery.
You can use these kinds of Jquery selectors to loop through all the elements that match many different kinds of selectors such as class, id, or just first or last or nth or parent or child.
So you can actually do things not just to children but to parents of an element too.

I have used this kind of selector to get the id or other information from the first td in each row of a table. And to change the background color of the rows as you pass through them too.

PHP session variables securit

PHP stores information in sessions to keep track of what user someone has logged in as. The session variables has a session_id that can be taken through sniffing or man in the middle attacks. After they take your session_id they can apply it to their own computer and then they will be you until you log out and your session is destroyed. I would like to test these theries out to see how to make it impossible for this to work. I can track the user in one browser and not let them use that session_id in another browser. tracking IP addresses don't work because AOL changes your IP address every time you go to a new page.

Here are some links I am studying right now.
http://blogs.sitepoint.com/notes-on-php-session-security/
http://phpsec.org/projects/guide/4.html
http://blogs.sitepoint.com/php-security-blunders/

I think eventually I will want to go to a more secure method and not store anything other than a sessionid that is stored in the database that stores the other information that would normally be stored in a session variable like username, full name, if they are an employee and what page they are on or other information.
Read this page for information on how to use sessions in a database:
http://www.oracle.com/technetwork/articles/mclaughlin-phpid1-091467.html

Tuesday, April 12, 2011

A fun little MySQL puzzle

I was looking for a way to convert a column in the database that has things like this: M1.1 and M1.2 all the way up to M1.15 into something like this:
M1.01 and M1.02 all the way up to M1.09 and M1.1 (for 10) and M1.15 for any above 10.

I used mysql like this
SELECT item as `the item to fix`,
SUBSTRING_INDEX(item,'.',1) as `the part to the left of the period`,
SUBSTRING_INDEX(item,'.',-1) as `the part to the right of the period`,
if(SUBSTRING_INDEX(item,'.',-1) < 10,
CONCAT(SUBSTRING_INDEX(item,'.',1),'.','0',SUBSTRING_INDEX(item,'.',-1))
,
if(SUBSTRING_INDEX(item,'.',-1) = 10,
CONCAT(SUBSTRING_INDEX(item,'.',1),'.',1)
,
item
)
) as `the fixed value`
FROM `data` where item like '%.%'


SUBSTRING_INDEX gets the text to the left of the first occurrence of the '.' if you use a 1 for the 3rd parameter and it gets the text to the right of the last occurrence of the '.' if you set the 3rd parameter to a -1.
Cool little puzzle that took 10 minutes to solve.

Getting web request with GET request in Excel

I found a cool easy way to do a GET request to any website and use any parameters needed.
One method to get code from a webpage and use it is here:
http://scriptorium.serve-it.nl/view.php?sid=40
and another I use is here:
Function testHttpGet()
Dim oHttp As Object
Set oHttp = CreateObject("Microsoft.XMLHTTP")
MyUrl = "http://10.0.21.130/test.php?name=mikeqq"
oHttp.Open "GET", MyUrl, False
oHttp.send
'MsgBox oHttp.Status
If oHttpPost.Status < 300 Then
SomeVar = oHttpPost.responseText
MsgBox SomeVar
End If
End Function

Just put this code in a module in Excel and then call it from in the spreadsheet somewhere. So now I can have excel give and get commands from a PHP script and could even act like a cron job by executing every once in a while!

Mysql Master - Slave replication server

I put together an Ubuntu 10.10 server with MySQL on it. I did it in VmWare Player and made it so what ever inserts I put in the master computer database gets put into the slave instantly. I'm going to try doing lots of inserts to see how long till it catches up. I can use PHP to programatically decide what SQL queries go to which database.
A great article I found this in is here
http://www.oracle.com/technetwork/articles/dsl/white-php-part2-355138.html

Friday, April 8, 2011

Dynamic caching of webpages

I read an interesting article on Oracles site on how to scale PHP pages for high traffic to scale web applicatons
I can see how this would be powerful. I have made php pages before that are very complex and if there were thousands of people coming every minute it would kill the sever unless it only had to load a certain page once every hour or so. Then if there are any updates they will only be updated and seen by everyone visiting once an hour instead of the instant they appear.

instead of having to run php all the time you just run it once an hour and write the content to a textfile with the name of the file being the url of the file plus any variables or get parameters that make the page unique or look different. All requests for the next hour will just read a text file with the webpage in it.
I will try an example in php and put it here.

<?php
$timeout = 60; // One Hour is 3600
$file = 'C:/Users/mike/Desktop/webhome/cachingtest/tempcache/'.sha1($_SERVER['REQUEST_URI']);
if (file_exists($file) && (filemtime($file) + $timeout) > time()){
//only show the cached copy of the page
readfile($file);
exit();
} else {
// Setup saving and let the page execute:
ob_start();
register_shutdown_function(function (){
Global $file;
$content = ob_get_flush();
file_put_contents($file, $content);
});
}
?>
<h2>Testing saving the current page from cache and only loading a fresh copy after a certain time limit has passed.</h2>