I am starting to play with POST request to save in my server the user token so I can send push notifications in Swift (this is the Swift code). This is the PHP file that processes the request (please note that I will improve it using prepare statements to prevent SQL injection):
<?php
error_reporting(E_ALL);
ini_set("display_errors", 1);
// typically there would be much more
// validation done on the request and
// cleaner database handling
// create link to database
$host = "localhost";
$db = "myDatabase";
$dbuser = "admin";
$dbpass = "mypassword";
$now = date("Y-m-d H:i:s");
$dbConnection = mysql_connect($host, $dbuser, $dbpass);
if ($dbConnection) {
mysql_select_db($db, $dbConnection);
} else {
// return error status code
sendAPIResponse(500);
return;
}
// get the post body
$userid = $_REQUEST['user'];
$token = $_REQUEST['token'];
if (empty($userid) || empty($token)) {
sendAPIResponse(400);
return;
}
// determine if user exists
$sql = "SELECT user_id
FROM users
WHERE user_id='".$userid."' LIMIT 1;";
$query = mysql_query($sql, $dbConnection);
$userExists = mysql_fetch_row($query);
// add a 'user' record
if (!$userExists) {
$sql = "INSERT INTO users (user_id)
VALUES ('".$userid."');";
if (!mysql_query($sql, $dbConnection)) {
// return error
sendAPIResponse(400);
return;
}
}
// determine if token already exists
$sql = "SELECT token
FROM user_tokens
WHERE user_id='".$userid."'
AND token='".$token."' LIMIT 1;";
$query = mysql_query($sql, $dbConnection);
$tokenExists = mysql_fetch_row($query);
// add a token for current user
if (!$tokenExists) {
$sql = "INSERT INTO user_tokens (user_id, token, datecreated)
VALUES ('".$userid."','".$token."','".$now."');";
if (!mysql_query($sql, $dbConnection)) {
// return error
sendAPIResponse(400);
return;
}
}
// close the database connection
mysql_close($dbConnection);
// return success
sendAPIResponse(200);
date_default_timezone_set('America/New_York');
function getStatusCodeMessage($status) {
$codes = Array(
100 => 'Continue',
101 => 'Switching Protocols',
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authoritative Information',
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Found',
303 => 'See Other',
304 => 'Not Modified',
305 => 'Use Proxy',
306 => '(Unused)',
307 => 'Temporary Redirect',
400 => 'Bad Request',
401 => 'Unauthorized',
402 => 'Payment Required',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
406 => 'Not Acceptable',
407 => 'Proxy Authentication Required',
408 => 'Request Timeout',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition Failed',
413 => 'Request Entity Too Large',
414 => 'Request-URI Too Long',
415 => 'Unsupported Media Type',
416 => 'Requested Range Not Satisfiable',
417 => 'Expectation Failed',
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Timeout',
505 => 'HTTP Version Not Supported'
);
return (isset($codes[$status])) ? $codes[$status] : '';
}
// Helper method to send a HTTP response code/message
function sendAPIResponse($status = 200, $body = '', $content_type = 'text/html') {
$status_header = 'HTTP/1.1 ' . $status . ' ' . getStatusCodeMessage($status);
header($status_header);
header('Content-type: ' . $content_type);
}
?>
If somebody gets the correct address:
would he be capable of sending a post request adding fake users and token IDs?
Shall I use an API key (not sure is the correct word) to "identify" the user?
$apiKey = $_REQUEST['apiKey'];
if(isset($apiKey)){
if($apiKey == 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxx'){
//then run the code
}
1 Answer 1
If somebody gets the correct address
http://www.myServer.com/api/v1.0/saveToken.php
, would he be capable to send a post request adding fake users and token ids?
Sure, why wouldn't an attacker be able to do that?
You can test this yourself, either by writing a short script, or using a plugin such as tamper data for firefox. Or, as you are using REQUEST
instead of POST
, just pass the values as GET
.
So if you want to avoid this, you need some kind of authentication mechanism (and you obviously need to fix the SQL injection).
Other than the use of mysql_
which is deprecated for a long time, and the SQL injection, your PHP code looks good. I would probably move some of the code to it's own function (such as addUser
, selectUser
, addToken
, etc) to make it even easier to read. And instead of setting the header and status message yourself you could use http_response_code
.
mysql_
as it's deprecated for quite a while, usemysqli_
orpdo
instead. \$\endgroup\$