Skip to content

Reliable, safe and up-to-date guide to secure your web JavaScript projects

Notifications You must be signed in to change notification settings

seguinleo/WebSecurityCheatSheet

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 

Repository files navigation

WebSecurityCheatSheet

📖 Table of contents

This document is a concise guide that aims to list the main web vulnerabilities, particularly JavaScript, and some solutions. However, it is exhaustive and should be supplemented with quality, up-to-date documentation.

This guide is intended for full-stack developers working with JavaScript technologies (React, Vue, etc.) and a Node.js/PHP backend.

.NET, JAVA, Django or Ruby are therefore not included in this guide.

HTTPs (i.e. Apache2)

Redirect all HTTP traffic to HTTPs

Write in /etc/apache2/apache2.conf:

Redirect permanent / <https://domain.com/>

Transport Layer Security (TLS)

General purpose web applications should default to TLS 1.3 (support TLS 1.2 if necessary) with all other protocols disabled. Only enable TLS 1.2 and 1.3. Go to /etc/apache2/conf-available/ssl.conf and write:

SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1

HTTP Strict Transport Security (HSTS)

HTTP Strict Transport Security (HSTS) is a mechanism for websites to instruct web browsers that the site should only be accessed over HTTPs. This mechanism works by sites sending a Strict-Transport-Security HTTP response header containing the site's policy. Write in /etc/apache2/apache2.conf:

Header set strict-transport-security "max-age=31536000; includesubdomains; preload"

Reload Apache and submit your website to https://hstspreload.org/

SSL

Disable all non-secure encryption algorithms. Go to /etc/apache2/conf-available/ssl.conf and write:

SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384

Online Certificate Status Protocol stapling is a crucial technology that enhances both the speed and privacy of SSL/TLS connections. Go to /etc/apache2/conf-available/ssl.conf and write:

SSLUseStapling on
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off
SSLStaplingCache "shmcb:ssl_stapling(32768)" <- before VirtualHost

Apache2

Enable HTTP2

HTTP/2 provides a solution to several problems that the creators of HTTP/1.1 had not anticipated. In particular, HTTP/2 is much faster and more efficient than HTTP/1.1.

sudo a2enmod http2

Enable mod_security

Mod security is a free Web Application Firewall (WAF) that works with Apache2 or nginx.

sudo apt install libapache2-modsecurity

SecRuleEngine On <- /etc/modsecurity/modsecurity.conf

Hide server signature

Revealing web server signature with server/PHP version info can be a security risk as you are essentially telling attackers known vulnerabilities of your system. Write in /etc/apache2/apache2.conf:

ServerTokens Prod
ServerSignature Off

Restrict access to files

Write in /etc/apache2/apache2.conf:

<Directory />
  Options FollowSymLinks
  AllowOverride None
  Require all denied
</Directory>
<Directory /var/www>
  Options -Indexes
  AllowOverride None
  Require all granted
</Directory>

Database

  • Use a strong database password and restrict user permissions
  • Hash all user login passwords before storing them in the database
  • For MySQL/MariaDB databases, use prepared queries to prevent injections
$query = $PDO->prepare("SELECT name FROM users WHERE name=:NameConnect LIMIT 1");
$query->execute([':NameConnect' => $name]);
$row = $query->fetch();
  • For MySQL/MariaDB databases, use mysql_secure_installation
  • For NoSQL databases, like MongoDB, use a typed model to prevent injections
  • Avoid $accumulator, $function, $where in MongoDB
  • Use .env for database and server secrets
  • Encrypt all user data (e.g. AES-256-GCM), store encryption keys in a secure vault like AWS Secrets Manager, Google Secrets Manager or Azure KeyVault

Authorization

  • Deny by default
  • Enforce least privileges
  • Validate all permissions
  • Validate files access
  • Sanitize files upload
  • Require user password for sensitive actions

Cookies

Domain=domain.com; Path=/; Secure; HttpOnly; SameSite=Lax or Strict

Secure: All cookies must be set with the Secure directive, indicating that they should only be sent over HTTPs

HttpOnly: Cookies that don't require access from JavaScript should have the HttpOnly directive set to block access

Domain: Cookies should only have a Domain set if they need to be accessible on other domains; this should be set to the most restrictive domain possible

Path: Cookies should be set to the most restrictive Path possible

SameSite:

  • Strict: Only send the cookie in same-site contexts. Cookies are omitted in cross-site requests and cross-site navigation
  • Lax: Send the cookie in same-site requests and when navigating to your website. Use this value if Strict is too restrictive

PHP

PHP-FPM

PHP-FPM (FastCGI Process Manager) is often preferred over Apache mod_php due to its superior performance, process isolation, and flexible configuration.

sudo apt install php<version>-fpm
sudo a2dismod mpm_prefork
sudo a2enmod mpm_event proxy_fcgi proxy

PHP PDO

PDO (PHP Data Objects) is a Database Access Abstraction Layer that provides a unified interface for accessing various databases.

A secure MySQL database connection with PDO:

$options = [
  PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
  PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
  PDO::ATTR_EMULATE_PREPARES   => false,
];
$dsn = "mysql:host=$host;dbname=$db";
try {
  $PDO = new PDO($dsn, $user, $pass, $options);
} catch (Exception $e) {
  throw new Exception('Connection failed');
  return;
}

php.ini

A hardened template for PHP-FPM, write in /etc/php/<version>/fpm/php.ini:

expose_php               = off
error_reporting          = e_all & ~e_deprecated & ~e_strict
display_errors           = off
display_startup_errors   = off
ignore_repeated_errors   = off
allow_url_fopen          = off
allow_url_include        = off
session.use_strict_mode  = 1
session.use_only_cookies = 1
session.cookie_secure    = 1
session.cookie_httponly  = 1
session.cookie_samesite  = strict
session.sid_length       = > 128

Node.js/npm

  • Always keep all npm dependencies up to date
  • Limit the use of dependencies
  • Use npm doctor to ensure that your npm installation has what it needs to manage your JavaScript packages
  • Use eslint to write quality code
  • To manage user cookies, use express.js and passport.js with JWT tokens

Docker

  • Use official and minimal images
  • Use .dockerignore to hide server secrets
  • Run containers with a read-only filesystem using --read-only flag
  • Avoid the use of ADD in favor of COPY
  • Set a user with restricted permissions in DockerFile
RUN groupadd -r myuser && useradd -r -g myuser myuser
# HERE DO WHAT YOU HAVE TO DO AS A ROOT USER LIKE INSTALLING PACKAGES ETC.
USER myuser

Ubuntu VPS

  • Use a strong passwords for all users
  • Disable root login
  • Create a user with restricted permissions and 2FA or physical key
  • Always update all packages and limit their number
  • Disable unused network ports
  • Change SSH port and use Fail2Ban to prevent DoS and Bruteforce attacks, disable SSH root login in sshd_config
PasswordAuthentication no
PubkeyAuthentication yes
PermitRootLogin no
  • Always make secure backups
  • Log everything
  • Use SFTP instead of FTP
  • Use a firewall like iptables or ufw
  • Use robots.txt to disallow all by default and don't disclose sensitive URLs
User-agent: \*
Disallow: /admin <- don’t do this

HTTP Headers

A hardened template for Apache2 and nginx:

x-content-type-options: "nosniff"
access-control-allow-origin "https://domain.com"
referrer-policy "no-referrer"
content-security-policy "upgrade-insecure-requests; default-src 'none'; base-uri 'none'; connect-src 'self'; font-src 'self'; form-action 'self'; frame-ancestors 'none'; img-src ‘self’; media-src 'self'; object-src ‘none’ ; script-src 'self'; script-src-attr 'none'; style-src 'self'"
permissions-policy "geolocation=(), …"
cross-origin-embedder-policy: "require-corp"
cross-origin-opener-policy "same-origin"
cross-origin-resource-policy "cross-origin"

In addition be sure to remove Server and X-Powered-By headers.

Note

Never use X-XSS-Protection, it is depracated and can create XSS vulnerabilities in otherwise safe websites. X-Frame-Options is depracated and replaced by frame-ancestors 'none'. Always start with default-src 'none', avoid unsafe-inline and unsafe-eval. Use hashes or nonces for inline scripts/styles.

HTML DOM sanitization

Links

Always use rel="noreferrer noopener" to prevent the referrer header from being sent to the new page.

POST vs GET

Never trust user inputs, validate and sanitize all data. Prefer POST requests instead of GET requests and sanitize/encode user form data with a strong regex and URLSearchParams() or encodeURIComponent().

try {
  const data = new URLSearchParams({ name, psswd })
  const res = await fetch('api/connectUser.php', {
    method: 'POST',
    mode: 'same-origin',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    },
    body: data,
  })
  if (!res.ok) {
    //
    return
  }
  //
} catch {
  // 
}

e.innerHTML

Never use innerHTML, use innerText or textContent instead. You can also create your element with document.createElement().

eval() and new Function()

Never use these JavaScript function. Executing JavaScript from a string is an enormous security risk. It is far too easy for a bad actor to run arbitrary code when you use eval().

DOMPurify

DOMPurify sanitizes HTML and prevents XSS attacks. You can feed DOMPurify with string full of dirty HTML and it will return a string (unless configured otherwise) with clean HTML. DOMPurify will strip out everything that contains dangerous HTML and thereby prevent XSS attacks and other nastiness.

import DOMPurify from 'dompurify'

const purifyConfig: {
  SANITIZE_NAMED_PROPS: true,
  ALLOW_DATA_ATTR: false,
  FORBID_TAGS: [
    'dialog', 'footer', 'form', 'header', 'main', 'nav', 'style'
  ]
}

const clean = DOMPurify.sanitize(dirty, purifyconfig)

Analysis tools

Mozilla Observatory

SSLLabs

Cryptcheck

Security Headers

Hardenize

Immuniweb

W3C Validator

Sources and resources

https://developer.mozilla.org/en-US/

https://www.cnil.fr/fr/securiser-vos-sites-web-vos-applications-et-vos-serveurs

https://cyber.gouv.fr/publications/recommandations-de-securite-relatives-tls

https://owasp.org/www-project-top-ten/

https://cheatsheetseries.owasp.org/

https://www.cert.ssi.gouv.fr/

https://phpdelusions.net/

https://www.digitalocean.com/community/tutorials

https://thehackernews.com/

https://portswigger.net/daily-swig/zero-day