Help me to secure this form process. 200+ SQLi possibilities
Posted: Thu Dec 31, 2009 12:17 pm
Hello Gurus, I have been working on a web application for a few months now and the site is nearly complete. I now find myself worrying and trying to fix security issues within the application. I understand the basics about never trusting information from the user and it must always be cleaned, i have also tried to use a token system. I would just like some help on this one script because I ran a web vulnrability scanner and found 3 very weak pages. So if you can help me fix one i can fix the other two.
So here is the form where users input data:
Nothing out of the ordinary there I dont think, I dont know if that is the correct way to generate a form token as i learnt off tutorials.
Now the data is sent to proofsend.php and this is where the security issues are, i will just paste the whole code its pretty ashamful i guess:
As you can see i have used a function to filter the data, this is something i learned as i was learning php and before i even knew about mysql_real_escape string. Would it be better to scrap the function validating the post data and replace it with mysql_real_escape_string?
Now for the vulnrabilities i need help fixing in this script.
1) SQLi: There are about 200+ different types input not just using (JyI%3D) of SQLi what can be used on this script here are the variables effected though:
The POST variable userproof_id has been set to JyI%3D.
The POST variable amountworkers has been set to JyI%3D.
The POST variable proof has been set to JyI%3D.
The POST variable Id has been set to %00'. (Where is Id =/)
The POST variable job_id has been set to '.
The POST variable createuser_id2 has been set to '.
So I presume my function fails horribly to clean the data? mysql_real_escape_string should be used maybe?
2)SQLi Cookies:
The Cookie variable user_name has been set to %00'. (A cookie i created)
The Cookie variable __utmc has been set to %2527. (Not my cookie i think its forum cookie)
The Cookie variable phpbb3_q529l_k has been set to %00'. (Not my cookie i think its forum cookie)
Need some guidence on this as i dont even know how cookie manipulation can be prevented.
3) SQLi Headers:
The HTTP header referer has been set to \'.
The HTTP header user-agent has been set to '.
The HTTP header x-forwarded-for has been set to '.
The HTTP header accept-language has been set to \".
There is more but you get the drift, how can i prevent a SQLi from injecting the headers? This sounds like the worst one.
Thats the exploits!(you will be glad if your reading)
Im not asking for my script to be rewritten by you, I just care about the security and would like the knowledge to fix these security issues.
So here is the form where users input data:
Code: Select all
<?php
session_start();
function generateToken($seed='mysupermagnificentkey')
{
$token = md5($seed.mktime());
$_SESSION['token']=$token;
return $token;
}
generateToken();
?>
Code: Select all
<form method="POST" action="proofsend.php">
<textarea rows="10" name="proof" cols="60"></textarea></b></p>
<!--hidden values saving information about the current user -->
<input name="userproof_id" type="hidden" value="<? echo $_SESSION['user_id'] ;?>">
<!--hidden values saving information about the job information -->
<input name="createuser_id2" id="createuser_id2" type="hidden" value="<? echo $row['createuser_id'] ;?>" />
<input name="perperson" id="perperson" type="hidden" value="<? echo $row['perperson'] ;?>" />
<input name="job_id" id="job_id" type="hidden" value="<? echo $my_id ;?>" />
<input name="title" type="hidden" value="<? echo $row['title'] ;?>">
<input name="amountworkers" id="amountworkersn" type="hidden" value="<? echo $row['amountworkers'] ;?>" />
<input type="submit" value="Submit Proof" name="submit"></p>
</form>
Now the data is sent to proofsend.php and this is where the security issues are, i will just paste the whole code its pretty ashamful i guess:
Code: Select all
<?php
// Check the form token
if(isset($_POST['job_id']) && isset($_POST['userproof_id']) && isset($_POST['proof']) && isset($_POST['title']) && isset($_POST['perperson']) && isset($_POST['amountworkers']) && isset($_POST['createuser_id2']))
{
if($_POST['token'] != $_SESSION['token'])
{
die('Token is invalid');
}
// token is now valid, process rest of form
$tbl_name = 'proof';
//Function definition
function onlyLetters($str){
$text = str_replace("\n", "xyxy", $str);
$pattern = '/[^0-9a-zA-Z-. ]*/';
$text = preg_replace($pattern, '', $text);
return str_replace("xyxy", "\n", $text);
}
function onlyNumbers($str){
$pattern = '/[^0-9.]*/';
return preg_replace($pattern, '', $str);
}
// Get and strip values from form
$job_id=onlyLetters($_POST['job_id']);
$userproof_id=onlyLetters($_POST['userproof_id']);
$proof=onlyLetters($_POST['proof']);
$title=onlyLetters($_POST['title']);
$perperson=onlyLetters($_POST['perperson']);
$createuser_id2=onlyLetters($_POST['createuser_id2']);
$query = "SELECT proof.* FROM proof WHERE proof.userproof_id ='$_SESSION[user_id]' and proof.job_id =$job_id";
$result = mysql_query($query);
$num_rows = mysql_num_rows($result);
if ($num_rows != 0){die("You have already completed this job. Please try another job.");
}else{
// Get and strip values from form again ... probably not needed.
$job_id=onlyLetters($_POST['job_id']);
$userproof_id=onlyLetters($_POST['userproof_id']);
$proof=onlyLetters($_POST['proof']);
$title=onlyLetters($_POST['title']);
$perperson=onlyLetters($_POST['perperson']);
$createuser_id2=onlyLetters($_POST['createuser_id2']);
// Insert data into mysql
$sql="INSERT INTO $tbl_name(job_id, userproof_id, proof, title, perperson, createuser_id2, date)VALUES('$job_id', '$userproof_id', '$proof','$title','$perperson','$createuser_id2',NOW())";
$result=mysql_query($sql);
// message to creator
$title = "A worker has completed your job.";
$to = "$createuser_id2";
$message =
"We are happy to inform you that a worker has completed your job. Please head over to the My Jobs section in the employers menu to view the proof submitted, once there you can approve or deny the proof given depending on if the worker has done what is required. \n <br />
<br />
Please note if you mark a workers proof as unexceptable when the proof is what is required your account will be deleted and IP banned.<br />
<br />
If you have any problems dont hesitate to contact us by using the report feature on the My Account page or through forums.";
// now insert message into database
$sql2 = "INSERT INTO messages SET `to` = '".$to."', `title` = '".$title."', `message` = '".$message."', `created` = NOW()";
$result = mysql_query($sql2)
or die('Invalid query: ' . $sql2 . ' - Error is ' . mysql_error());
// run process, update values in the database.
$sql = "SELECT `fulldata`.*
FROM `fulldata`
WHERE fulldata.job_id = $job_id";
$result = mysql_query($sql)
or die('Invalid query: ' . $sql . ' - Error is ' . mysql_error());
$sql = "UPDATE `fulldata`
SET amountworkers = amountworkers - 1
WHERE fulldata.job_id = $job_id";
$result = mysql_query($sql)
or die('Invalid query: ' . $sql . ' - Error is ' . mysql_error());
$sql = "UPDATE `fulldata`
SET amountcomplete = amountcomplete + 1
WHERE fulldata.job_id = $job_id";
$result = mysql_query($sql)
or die('Invalid query: ' . $sql . ' - Error is ' . mysql_error());
// is the job complete now?
$workers = mysql_real_escape_string($_POST['amountworkers']);
if ($workers == 1)
{
$sql = "UPDATE `fulldata`
SET completedjob = 1
WHERE fulldata.job_id = $job_id";
$result = mysql_query($sql)
or die('Invalid query: ' . $sql . ' - Error is ' . mysql_error());
}
// if successfully insert data into database, displays message "Successful".
if($result){
echo "Your proof has now been sent to the employer, When approved you will recieve money.";
echo "<BR>";
echo "<a href='/jobs.php'>Click here to go back to miniworkers</a>";
echo "$workers";
}
else {
echo "ERROR";
}
}
?>
Now for the vulnrabilities i need help fixing in this script.
1) SQLi: There are about 200+ different types input not just using (JyI%3D) of SQLi what can be used on this script here are the variables effected though:
The POST variable userproof_id has been set to JyI%3D.
The POST variable amountworkers has been set to JyI%3D.
The POST variable proof has been set to JyI%3D.
The POST variable Id has been set to %00'. (Where is Id =/)
The POST variable job_id has been set to '.
The POST variable createuser_id2 has been set to '.
So I presume my function fails horribly to clean the data? mysql_real_escape_string should be used maybe?
2)SQLi Cookies:
The Cookie variable user_name has been set to %00'. (A cookie i created)
The Cookie variable __utmc has been set to %2527. (Not my cookie i think its forum cookie)
The Cookie variable phpbb3_q529l_k has been set to %00'. (Not my cookie i think its forum cookie)
Need some guidence on this as i dont even know how cookie manipulation can be prevented.
3) SQLi Headers:
The HTTP header referer has been set to \'.
The HTTP header user-agent has been set to '.
The HTTP header x-forwarded-for has been set to '.
The HTTP header accept-language has been set to \".
There is more but you get the drift, how can i prevent a SQLi from injecting the headers? This sounds like the worst one.
Thats the exploits!(you will be glad if your reading)
Im not asking for my script to be rewritten by you, I just care about the security and would like the knowledge to fix these security issues.