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

  • 540