I don’t know much when it comes to ajax
, I prefer to carry out the validations in the back-end, I leave to the front-end the pure role of interface, the rest, as validations prefer in the server-side.
I will respond the way I usually do with my requests, not just when it comes to being ajax
.
I use the token
, one token
is generated when the page is called, and added to a input
Hidden type, I send it with ajax
together with the other data, already in the php
me valid that token
several times to see if the token is valid.
I set a small quick example to see that even having knowledge of the system is not possible to hack it, follows the description of each file:
index php.: responsible for displaying the person registration form, the list of registered persons, in it I present a token at the beginning of the page, and assign it in a field of type Hidden, there is also the ajax responsible for sending the data.
<?php
include 'Pessoa.php';
$_SESSION['token'] = crypt("MyAppIDKey" . time() . "MyTokenSecurity");
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Segurança Ajax</title>
<script src="jquery.min.js"></script>
</head>
<body>
<form class="myForm" method="get">
<p>
<label>Nome: </label>
<input type="text" name="nome" />
</p>
<p>
<label>Idade: </label>
<input type="number" name="idade" />
</p>
<p>
<label>E-mail: </label>
<input type="email" name="email" />
</p>
<p>
<input type="hidden" name="token" value="<?php echo $_SESSION['token']; ?>" />
<input type="submit" value="Enviar" />
<input type="reset" value="Limpar" />
</p>
</form>
<div class="result"></div>
<?php if(isset($_SESSION['pessoas']) and !empty($_SESSION['pessoas'])): ?>
<table>
<thead>
<tr>
<th>Nome</th>
<th>Idade</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<?php foreach ($_SESSION['pessoas'] as $pessoa): ?>
<tr>
<td><?php echo $pessoa->getNome(); ?></td>
<td><?php echo $pessoa->getIdade(); ?></td>
<td><?php echo $pessoa->getEmail(); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif;?>
<script>
$(function()
{
$("form.myForm").submit(function()
{
$.ajax(
{
type: "GET",
url: "callMyController.php",
data:
{
nome: $("input[name = nome]").val(),
idade: $("input[name = idade]").val(),
email: $("input[name = email]").val(),
token: $("input[name = token]").val()
},
success: function(result)
{
if(result == "ok")
{
alert("Pessoa cadastrada!");
}
else
{
alert("Erro: " + result);
}
}
});
});
});
</script>
</body>
</html>
callMyController.php: would be yours framework
or standard architecture, but in case I put it not to have to create an architecture, is this file that the ajax
send the request, in it I just validated the token
for the first time and send the array
data GET
for my controller:
<?php
require_once 'MyController.php';
if(isset($_GET['token']) and $_GET['token'] === $_SESSION['token'])
{
$mc = new MyController();
$mc->cadastrar($_GET);
}
else
echo "Erro no acesso";
Mycontroller.php: In this class I have the communication between the vision and the model
, the same validation of token
, I try to put the typed data in the model
(us setters
there are more validations), and finally try to register this person, if I was successful when registering I display a ok
as a return to the ajax
, if I didn’t take the validation exception that was launched:
<?php
require_once 'Pessoa.php';
class MyController
{
private $myModel = null;
public function __construct()
{
$this->myModel = new Pessoa();
}
public function cadastrar($data)
{
if($data['token'] === $_SESSION['token'])
{
try
{
$this->myModel->setNome($data['nome']);
$this->myModel->setEmail($data['email']);
$this->myModel->setIdade($data['idade']);
if($this->myModel->inserirPessoa())
echo "ok";
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
}
}
Pessoa.php: represents the Person object, where I have the attributes present in the form, its getters
and setters
with validations and a method of registering a new person, who in the example just tries to put that person in a array
session representing my database:
<?php
session_start();
session_name(crypt("MyAppIDKey"));
class Pessoa
{
private $nome;
private $email;
private $idade;
public function __construct()
{
if(!isset($_SESSION['pessoas']))
$_SESSION['pessoas'] = array();
}
public function setNome($nome)
{
if(!stripos(mb_strtolower($nome), " and ") and !stripos(mb_strtolower($nome), " or "))
$this->nome = $nome;
else
throw new Exception("Nome inválido");
}
public function setEmail($email)
{
if(filter_var($email, FILTER_VALIDATE_EMAIL))
$this->email = $email;
else
throw new Exception("Email inválido");
}
public function setidade($idade)
{
if(filter_var($idade, FILTER_VALIDATE_INT))
$this->idade = $idade;
else
throw new Exception("Idade inválida");
}
public function getNome()
{
return $this->nome;
}
public function getIdade()
{
return $this->idade;
}
public function getEmail()
{
return $this->email;
}
public function inserirPessoa()
{
try
{
array_push($_SESSION['pessoas'], $this);
return true;
}
catch (Exception $e)
{
throw new Exception($e->getMessage());
}
}
}
Last but not least, I placed a file called php., where I try to hack into the system by adding new data, this would be the action of an insertion attack, where the attacker fills the database with useless information, being able to do even worse things, such as trying a SQL Injection automatic, because normally the invasion is not done from one to a given, but using a repetition structure.
<?php
$_SESSION['token'] = crypt("MyAppIDKey" . time() . "MyTokenSecurity");
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Tentando invadir</title>
<script src="jquery.min.js"></script>
</head>
<body>
<p>
<label>Token: </label>
<input type="text" name="token" value="<?php echo $_SESSION['token']; ?>" />
</p>
<p><a href="#" class="tryHack" >Invadir</a></p>
<div class="result"></div>
<script>
$(function()
{
$("a.tryHack").click(function()
{
$.ajax(
{
type: "GET",
url: "callMyController.php",
data:
{
nome: "dado01",
idade: "15",
email: "[email protected]",
token: $("input[name = token]").val()
},
success: function(result)
{
if(result == "ok")
{
alert("Pessoa cadastrada!");
}
else
{
$("div.result").html(result);
}
}
});
});
});
</script>
</body>
</html>
Remarks:
- Was used the
crypt
for cryptography, could use other methods,
like the md5
(that is not cryptography);
- It could have more validations, as when arriving at
callMyController.php generate another token validation to validate with the controller and in the booster to be generated another in order to
be validated on
model
.
- I used the method
GET
just to make it a little more subject to
invasions in case someone wanted to try to test invasions via URL. Remembering
that the method is recommended POST
for this type of transport
dice.
The way I think about it is you have sessions and a counter on the server, and you have it on the browser. You’ve tried this before?
– Sergio
If the system is well developed it will not be necessary to protect ajax, it should have one or two validations in the backend, and ajax should send and take data to layer before validation and not directly in the persistence layer.
– Leonardo
To protect against automated data entry systems etc just make a token Hidden field with time-based value and encryption, one of the backend validations will be if the token is equal to the input.
– Leonardo
I also think about using Tokens. The application itself returns the token that should "exist" in the Ajax request. If it does not exist, the operation is canceled.
– Wallace Maxters
Just pointing out Q&A != forum
– Guilherme Lautert
Jackson, has a way to modify ajax of your site, is expensive service. Tip use javascript prototype to do this. But why not use PHP? forgets javascript. If you try to make API?
– KingRider
You need to explain what problems you want to deal with, because each case is a case. In principle, the simple answer is "no ajax is possible". But in some cases, you can avoid repetition using nonces (a kind of non-reusable token) controlled by the server (as is done in most of the replay attack lock). The fact is that virtually everything the user can do for the browser can be emulated by a malicious application in the slightest detail. Only captcha and the like to prevent automated attacks, but then impacts usability (and does not prevent "manual attacks").
– Bacco