So I've a php form processing file; say a file name process.php with the codes as
<?php
$value = $_POST['string']; //Assume string is safe for database insertion
$result = mysql_query("INSERT into table values {$value}");
if($result) {
return true;
} else {
return false;
}
?>
Ideally, only someone who's logged in to my website shall be allowed to send that POST request to perform that insertion. But here, anyone who know this processing file's path and the request being sent can send any spoof POST request from any domain (if I'm not wrong). This will lead to insertion of unwanted data into the database.
One thing I did is, before the insertion, I checked whether a user is logged in or not. If not, I ignore the POST request. But how exactly should I secure my processing files from exploits?
As it stands this is vulnerable to SQL Injection. Make sure you use a parametrized query library like PDO for inserting the file and the mysql "blob" or "long blob" type. You should never use mysql_query().
You should also keep track of the user's id for user access control. It doesn't look like you have taken this into consideration.
Related
I apologize if this question has been asked before, if it has just link me to it in a comment.
So I've created a web-service for an android/iOS app with php that works like this.
The app sends a request to http://www.example.com/ws/getCookingData.php with 2 $_POST paramaters userID and foodType
The php file then queries the database using those two variables and returns a json_encode result.
My worry is that if someone were to discover my web-service link they could spam it with post requests resulting in 100's of call to my database that are just un-needed
Below is an example of my current getData.php file
<?php
$userID = mysql_escape_string($_POST['userID']);
$foodType = mysql_escape_string($_POST['foodType']);
$mysqli = getDB();
echo json_encode(getDate($mysqli, $userID, $foodType); //mysql database interaction is here
$mysqli->close();
?>
There is nothing here preventing hackers from attempting to post malicious SQL statements into my database
So what I'm wondering is if I added a 3rd parameter to my post request called appID would this be a good solution?
For example if I were to update my getData.php file to below would this be much more secure or is there a vulnerability I'm missing?
<?php
$appID = $_POST['appID'];
if($appID === "hardCodedEquivalentID"){
$userID = mysql_escape_string($_POST['userID']);
$foodType = mysql_escape_string($_POST['foodType']);
$mysqli = getDB();
echo json_encode(getDate($mysqli, $userID, $foodType); //mysql database interaction is here
$mysqli->close();
}
?>
If this is a good solution or there is already an equivalent practice that would achieve what I'm trying to do please let me know
First of all, use mysqli or PDO instead of mysql function which is deprecated. Secondly create a function which will authenticate the user and see whether the user has the permission to access the data. And thirdly try to LIMIT the data to 100 or so if possible.
Hardcoding the appId is not the solution. Create unique Id's for each specific registered user and then match that appId against that particular user. And when their session is expired clear the access token. And at the start of their session, you can login in them and create new access token and can use the same for their entire session.
To answer your first question
My worry is that if someone were to discover my web-service link they
could spam it with post requests resulting in 100's of call to my
database that are just un-needed
If someone wants to DoS you then you can't do much in your code to prevent it but you may try using service like cloudflare. Not worth worrying about it at the beginning.
About
There is nothing here preventing hackers from attempting to post
malicious SQL statements into my database
then just read documentation on PDO
1- Use mysql_real_escape_string()
2- Use str_replace(" ","",$_POST['userID']) and str_replace("%20","",$_POST['userID'])(Because malicious attacks involves in using %20 and space to inject sql query)
3- Add this line to the top of the page, so the script only takes request if its been from your website (That's what I am using too!)
$referrer = $_SERVER['HTTP_REFERER'];
if (strpos($referrer,"yourwebsite.com")) {
} else {
die();
}
I want to check/filter user input. If, for example, the user chosen value does not match what we have on the db, I want the script/query to stop--obviously for security reasons.
Which is correct?
if (!floatval($esc_size || $esc_sizeid) )
{
echo "Invalid Size </br>";
$thread_id = mysqli_thread_id($con);
/* Kill connection */
mysqli_kill($link, $thread_id);
mysqli_close($link);
}
or just simply
exit;
or is there a better, more secure way?
Thanks,
Jen
exit() will stop the script completely. PHP runs server-side and you are in complete control of what code is executed. For that reason, security is not an issue here.
From a user interface perspective, it is much better to put any updates to the db etc. in an if statement that only runs if the user input was valid and if it was not, display a friendly message to the user about what he/she did wrong.
Help! I'm writing some code to update a mySQL database using similar to the code below:-
$.post('http://myURL.com/vote.php?personID=' + personID + '&eventID=123');
The vote.php code takes the querystring values and inserts a record into a database with those values in it.
This kind of code is working fine, but I've realised the problem is that people could just type something like:
http://myURL.com/vote.php?personID=5&eventID=123
into their address bar and essentially spam the app...
Is there a straightforward way I can ensure this doesn't happen? I'm reasonably new to these technologies so not aware of how everything works or fits together, but I'm learning fast so any pointers would be super useful.
It is not a good idea to use GET parameters for data that goes to a database. Generally, you want to use POST parameters which are not visible in the URL. So instead of :
$.post('http://myURL.com/vote.php?personID=' + personID + '&eventID=123');
You would do it like this :
$.post('http://myURL.com/vote.php', { "personID" : personID, "eventID" : 123 });
And in your PHP script, you would access your data with the $_POST array like this :
$personID = $_POST['personID'];
$eventID = $_POST['eventID'];
However, don't forget to properly filter input before saving to the database to prevent bad things like SQL Injection.
This is not a silver bullet : spam will still be possible because any HTTP client will be able to send a post request to your site. Another thing you can look at is Security Tokens to make it even less vulnerable to spam. Or implement a system that limits the number of request/minute/user... but I'm getting too far from the original question.
Correct syntax of $.post is
$.post(url,data_to_send,callback_function)
By using this method your user will never be able to damage your site.Use like
$.post('http://myURL.com/vote.php',{"personID":personID,"eventID":123);
Whether you're using POST or GET, you could always consider signing important fields in your page by using hash_hmac. This prevents people from changing its value undetected by adding a signature that no one else can guess.
This also makes CSRF more difficult, though not impossible due to fixation techniques. It's just yet another technique that can be put in place to make it more difficult for "fiddlers".
The following function adds a salt and signature to a given person id to form a secured string.
define('MY_SECRET', 'an unguessable piece of random text');
function getSecurePersonId($personId)
{
$rnd = uniqid("$personId-", true);
$sig = hash_hmac('sha1', $rnd, MY_SECRET);
return "$rnd-$sig";
}
You would pass the output of getSecuredPersonId() to JavaScript to pass as data in the $.post() or $.get(); posting would be recommended btw.
When the form is submitted your person id would end up in either $_GET['personID'] or $_POST['personID'] depending on the request method. To validate the given value, you run it through this function:
function validateSecurePersonId($securePersonId)
{
if (3 != count($parts = explode('-', $securePersonId))) {
return false;
}
// reconstruct the signed part
$rnd = "{$parts[0]}-{$parts[1]}";
// calculate signature
$sig = hash_hmac('sha1', $rnd, MY_SECRET);
// and verify against given signature
return $sig === $parts[2] ? $parts[0] : false;
}
If the value is properly signed, it will return the original person id that you started out with. In case of failure it would return false.
Small test:
$securePersonId = getSecurePersonId(123);
var_dump($securePersonId);
if (false === validateSecurePersonId($securePersonId)) {
// someone messed with the data
} else {
// all okay
}
I'm creating a script on my main server and will use js/html to call it as an image source, passing the current tumblr page's referrer variable so I can integrate my blog's stats into my main stat-tracking db.
Anyone who looks at the source, of course, will be able to see that this script can accept a url variable via get. I'm not much of a security wonk, but I'm using the following checks on the input to this var, currently:
$previous_referrer = htmlspecialchars($_GET['ref']);
if (filter_var($previous_referrer, FILTER_VALIDATE_URL) && strpos($_SERVER['HTTP_REFERER'], $tumblelog_url)!== FALSE)
I'm guessing it isn't this simple. What other checks should perform to lock it down against injection attacks?
For inserting data safely in a database :
1) Before inserting in DB
Filter data :
Does my data had the expected type/patern (email,url ....)
The main purpose of filtering in first is to avoid processing useless data
Prevent from sql injection :
if inserting a number use function like intval(),floatval()
if inserting string use function like mysql_real_escape_string (for mysql only) or prepared statement.
2) After insertion , before display
Prevent Xss by using function like htmlspecialchars() or htmlentites().
We have some problems with users performing a specific action twice, we have a mechanism to ensure that users can't do it but somehow it still happens. Here is how our current mechanism works:
Client side: The button will be disabled after 1 click.
Server side: We have a key hash in the URL which will be checked against the key stored in SESSIONS, once it matches, the key is deleted.
Database side: Once the action is performed, there is a field to be flagged indicating the user has completed the action.
However, with all these measures, still there are users able to perform the action twice, are there any more safer methods?
Here is the partial code for the database side:
$db->beginTransaction();
// Get the user's datas
$user = $db->queryRow("SELECT flag FROM users WHERE userid = {$auth->getProperty('auth_user_id)}");
if ($user['flag'] != 0) {
$db->rollback();
// Return with error
return false;
}
// Proceed with performing the action
// --- Action Here ---
// Double checking process, the user data is retrieved again
$user = $db->queryRow("SELECT flag FROM users WHERE userid = {$auth->getProperty('auth_user_id)}");
if ($user['flag'] != 0) {
$db->rollback();
// Return with error
return false;
}
// --- The final inserting query ---
// Update the flag
$db->query("UPDATE users SET flag = 1 WHERE userid = {$auth->getProperty('auth_user_id)}");
$db->commit();
return true;
It is good to see that you have taken all measures to defeat the bad guys. Speaking in terms of bad guys:
Client side: This can easily be bypassed by simply disabling javascript. Good to have anyways but again not against bad guys.
Server side: This is important, however make sure that you generate a different hash/key with each submission. Here is a good tutorial at nettutes on how to submit forms in a secure fashion.
Database side: Not sure but I suspect, there might be SQL injection problem. See more info about the SQL Injection and how to possibly fix that.
Finally:
I would recommend to you to check out the:
OWASP PHP Project
The OWASP PHP Project's goal (OWASP PHP Project Roadmap) is to enable developers, systems administrators and application architects to build and deploy secure applications built using the PHP programming language.
Well the JS method and Hash method may be cheated by some notorious guy, but 3rd method seems to be very good in order to protect the redundancy. There must be some programming flaw to get passed this.
Why don't u just check the flag field on the page where you are inserting the values rather than where user performing the action (if you are doing it now)
Pseudocode follows:
<?
$act_id; // contains id of action to be executed
$h = uniqid('');
// this locks action (if it is unlocked) and marks it as being performed by me.
UPDATE actions SET executor = $h WHERE act_id = $act_id AND executor = '';
SELECT * FROM actions WHERE executor = $h;
//
// If above query resulted in some action execute it here
//
// if you want to allow for executing this exact action in the future mark it as not executed
UPDATE actions SET executor = '' WHERE act_id = $act_id;
Important things:
First query should be update claiming
the action for me if it is yet
unclaimed.
Second should be query
grabbing action to execute but only
if it was claimed by me.