How to write secure code
SQL Injection
aka N°1 OWASP TOP 10
SQL Injection
public function findUser($id) {
$qb = $this->createQueryBuilder('user')
->where('g.id = '.$id);
return $qb->getQuery()->getResult()
}
public function findUser($id) {
$qb = $this->createQueryBuilder('user')
->where('g.id = :id')
->setParameter('id', $id);
return $qb->getQuery()->getResult()
}
SQL Injection
public function findInfo($table) {
$qb = $this->_em->createQueryBuilder()
->select('info')
->from($table);
return $qb->getQuery()->getResult()
}
public function findInfo($table) {
$authorizedTables = ['product', 'category']
if (!in_array($table, $authorizedTables) {
throw new ItsATrapException();
}
$qb = $this->_em->createQueryBuilder()
->select('info')
->from($table);
return $qb->getQuery()->getResult()
}
Input validation
public function listAction(Request $request) {
$keywords = $request->get('keywords');
/** @var UserRepository $repository */
$repository = $this->getDoctrine()
->getRepository(User::class);
return $repository->searchUsers($keywords);
}
Input validation
public function listAction(Request $request) {
$keywords = $request->get('keywords');
if (strlen($keywords) < 3) {
throw new Exception();
}
/** @var UserRepository $repository */
$repository = $this->getDoctrine()
->getRepository(User::class);
return $repository->searchUsers($keywords);
}
XSS
alert()
XSS
<a href="{{ user_link }}"> Click me </a>
What if user_link comes from an input of the user ?
<a href="javascript:alert('XSS')"> Click me </a>
How to fix it ?
Whitelist used protocol (http, https, mailto)
XSS
const rawHtml ="
<span style="color: red">
This should be red
</span>
"
<span v-html="rawHtml"></span>
This should be red
const rawHtml ="<img src='toto' onerror=alert(1)//>"
const sanitizedHtml = DOMPurify.sanitize(rawHtml)
//"<img src='toto'//>"
XSS
With TWIG :
- ⚠️ "{{ toto | raw }}"⚠️
- ⚠️ "{{ autoescape false }}"⚠️
- Use HTMLPurifierBundle to purify HTML
CSRF
CSRF
Example :
- Click here to receive a free IPhone X !
<form action="https://www.facebook.com/settings?tab=deleteAccount"
method="POST"
>
<img src="http://arnaque.com/pigeon.jpg"/>
<button type= "submit">
Win a free IPhone X !
</button>
</form>
CSRF
The different possibilities :
User/Feature | AJAX | FORM |
---|---|---|
User Ajax | ✅ | - |
User Form | - | ✅ |
Attaquant Ajax | CORS | CORS |
Attaquant Form | Header | Token |
CSRF
When and how you should protect your users:
- Ajax request that can modify server data (POST, PUT, DELETE, PATCH...)
- Form with method POST
CSRF
Why it works:
- Vue automatically sends the header : X-Requested-With: XMLHttpRequest
- The annotation triggers a Symfony event listener on the request that checks if the header is here.
- The header cannot be added by an ajax request cross domains so if it's here it is not an attack
What's more
Vertical Access Control (@Security annotation)
Horizontal Access Control (Voters in Symfony)
File Upload
Authentication
Forced HTTPS
Dojo Sécu
By Louis Pinsard
Dojo Sécu
- 630