Preventing security vulnerabilities in Web Apps

Chirag Goel
DataDrivenInvestor
Published in
11 min readMar 15, 2021

--

In this article, we will be talking about prevention methods to be taken for security concern as discussed in my previous article — Security vulnerabilities in Web Apps

Let’s start with a basic HTTP header set up in order to avoid a security breach. This won’t give 100% protection to your web application, but will at-least circumvent newbies from bounty and hackers to hold up their shorts for a long run.

Security through HTTP header:

1. X-Frame-Options

X-Frame-Options control the way the site can be framed. The following settings are possible:

  • X-Frame-Options: DENY (forbids framing)
  • X-Frame-Options: SAMEORIGIN (allows the site to be framed only in the same origin)
  • X-Frame-Options: ALLOW-FROM https://example.com/ (allows the site to be framed only by websites hosted at example.com, not supported in many browsers)

For modern browsers, this header is replaced by frame-ancestor CSP directive, but it is still a good practice to use both techniques together for compatibility.

X-Frame-Options allow protecting the user from clickjacking attacks which rely on deceiving the user into interacting with content displayed in a hidden iframe embedded in a specially crafted webpage (this attack is also called “UI Redressing”).

2. Cross-Site Scripting Protection (X-XSS)

As the name suggests, the X-XSS header protects against Cross-Site Scripting attacks. XSS Filter is enabled in Chrome, IE, and Safari by default. This filter doesn’t let the page load when it detects a cross-site scripting attack.

Syntax:

X-XSS-Protection: 0X-XSS-Protection: 1X-XSS-Protection: 1; mode=blockX-XSS-Protection: 1; report=<reporting-uri>

3. HTTP Strict Transport Security

HSTS (HTTP Strict Transport Security) header ensures all communication from a browser is sent over HTTPS (HTTP Secure). This prevents HTTPS click-through prompts and redirects HTTP requests to HTTPS.

Before implementing this header, you must ensure all your website page is accessible over HTTPS else they will be blocked.

HSTS header is supported on all the major latest versions of a browser like IE, Firefox, Opera, Safari, and Chrome. There are three parameter configurations.

max-age: Duration (in seconds) to tell a browser that requests are available only over HTTPS.

includeSubDomains: Configuration is valid for subdomain as well.

preload: Use if you would like your domain to be included in the HSTS preload list

4. X-CONTENT-TYPE-OPTIONS

This HTTP header is supported by IE and Chrome and prevents attacks based on MIME-type mismatch. The only possible value is nosniff. If your server returns X-Content-Type-Options: nosniff in the response, the browser will refuse to load the styles and scripts in case they have an incorrect MIME-type. The list with available MIME-types for styles and scripts is as follow:

Styles

  • text/css

Scripts

  • application/ecmascript
  • application/javascript
  • application/x-javascript
  • text/ecmascript
  • text/javascript
  • text/jscript
  • text/x-javascript
  • text/vbs
  • text/vbscript

5. CONTENT-SECURITY-POLICY

Content-Security-Policy is a header, which allows controlling the origins that are used by a web browser to download assets. There are several directives related to various kinds of resources, the most basic being:

  • default-src (covers types of assets that were not set explicitly using other directives)
  • img-src (restricts sources of images)
  • script-src (restricts sources of scripts)
  • connect-src (restricts sources of data that can be obtained)

A server can instruct the browser to whitelist all origins that can be used for dynamic resources. Some of the values that can be used include:

  • ‘none’ (prevents loading from any sources)
  • ‘self’ (allows only same-origin resources)
  • domain (allows loading from a specific domain, e.g. example.com)
  • protocol, e.g. data:, blob: (allows loading resources from specific schemes)

There are two special sources, related to CSS styles and JavaScript:

  • ‘unsafe-inline’ (allows including scripts and styles as in page source — as attributes, or script tags)
  • ‘unsafe-eval’ (allows executing the eval() Javascript function)

6. Public Key Pinning Extension for HTTP (HPKP)

HTTP Public Key Pinning (HPKP) is a security mechanism that allows HTTPS websites to resist impersonation by attackers using miss-issued or otherwise fraudulent certificates. (For example, sometimes attackers can compromise certificate authorities, and then can miss-issue certificates for a web origin.).

The HTTPS web server serves a list of public key hashes, and on subsequent connections clients expect that server to use one or more of those public keys in its certificate chain. Deploying HPKP safely will require operational and organizational maturity due to the risk that hosts may make themselves unavailable by pinning to a set of public key hashes that becomes invalid. With care, host operators can greatly reduce the risk of man-in-the-middle (MITM) attacks and other false authentication problems for their users without incurring undue risk.

pin-sha256A: Base64 encoded Subject Public Key Information (SPKI) fingerprint.

max-age: The time, in seconds, that the user-agent should remember the host as a Known Pinned Host.

includeSubDomains: An optional directive that signals to the user-agent that the Pinning Policy applies to this Pinned Host as well as any subdomains of the host’s domain name.

report-uri: An optional directive that indicates the URI to which the user-agent should report Pin Validation failures.

7. CORS (Cross Origin Resource Sharing)

Usually web browsers forbids cross-domain requests, due to the same-origin security policy. Cross-origin resource sharing(CORS) is a technique that allow servers to serve resources to permitted origin domains by adding HTTP headers to the server who are respected from web browsers.

Examples of practical use of CORS are cross-domain AJAX requests, or using fonts hosted on a subdomain.

Request Headers:

Origin

  • The Origin header shows the server name where the cross-domain/preflight request originates.

Access-Control-Request-Method

  • The Access-Control-Request-Method header is sent to the server as part of the preflight request and informs it about the HTTP method that will be used in the actual request.

Access-Control-Request-Headers

  • The Access-Control-Request-Headers header is sent to the server as part of the preflight request and informs it about headers that will be used in the actual request.

Security measures based on type of vulnerability:

1. Cross-Site Scripting (XSS)

Prevention: There’s a simple web security solution: don’t return HTML tags to the client. This has the added benefit of defending against HTML injection, a similar attack whereby the attacker injects plain HTML content (such as images or loud invisible flash players) — not high-impact but surely annoying (“please make it stop!”). Usually, the workaround is simply converting all HTML entities, so that <script> is returned as &lt;script&gt;. The other often employed method of sanitization is using regular expressions to strip away HTML tags using regular expressions on < and >, but this is dangerous as a lot of browsers will interpret severely broken HTML just fine. Better to convert all characters to their escaped counterparts.

To protect your users against XSS, make sure that you never inject unknown user input into the page. Remember to use the escape syntax for those parts of the HTML document that you’re putting untrusted data. Use HTML and JavaScript escapes before putting untrusted data into HTML and JavaScript data values. Besides that don’t forget to use CSS escape. It’s recommended to avoid using sources to get rid of JavaScript security issues.

Most web-apps make use of cookies to store various kinds of information about the user session such as user preferences, last visited pages, shopping cart, authentication tokens etc. Developers often forget to set the secure and http flags on these cookies. These flags are not true by default but must be explicitly set to true to ensure that the information is only going out via encrypted messages (https) and cannot be accessed via client-side scripts thus preventing cross-site scripting attacks.

Commonly used main prevention methods include:

  • Data validation
  • Filtering
  • Escaping

2. SQL Injection

Prevention: The good news is that protecting against injection is “simply” a matter of filtering your input properly and thinking about whether an input can be trusted. But the bad news is that all input needs to be properly filtered unless it can unquestionably be trusted (but the saying “never say never” does come to mind here).

In a system with 1,000 inputs, for example, successfully filtering 999 of them is not sufficient, as this still leaves one field that can serve as the Achilles heal to bring down your system. And you might think that putting an SQL query result into another query is a good idea, as the database is trusted, but if the perimeter is not, the input comes indirectly from guys with malintent. This is called Second Order SQL Injection in case you’re interested.

Since filtering is pretty hard to do right (like crypto), what I usually advise is to rely on your framework’s filtering functions: they are proven to work and are thoroughly scrutinized. If you do not use frameworks, you really need to think hard about whether not using them really makes sense in your server security context. 99% of the time it does not.

Attacks such as SQL-injection and buffer overflow can easily be prevented if both size and content of user input are validated properly. Validating against a whitelist(allowed characters) is preferable to validating against a blacklist(disallowed characters). I have seen developers invariably re-inventing these and missing out on many corner cases. Hence, I recommend using a standard validation library such as ESAPI or Apache commons validator. For SQL, it is preferable to use parameterized statements and stored procedures instead of using dynamically generated queries. Parameterized statements safely treat all user-supplied input as the literal representation of those strings instead of treating them as part of a SQL query thus preventing injection attacks.

3. Server-side JavaScript Injection (SSJI)

Prevention: We’re talking about the high risk of vulnerabilities. Besides that, remember that if user’s input is required for a server-side command, then it should be properly validated.

4. File Inclusion and Directory Traversal

Prevention: The best way to check whether your website and web applications are vulnerable to directory traversal attacks is by using a Web Vulnerability Scanner. A Web Vulnerability Scanner crawls your entire website and automatically checks for directory traversal vulnerabilities. It will report the vulnerability and how to easily fix it. Besides directory traversal vulnerabilities a web application scanner will also check for SQL injection, Cross-site Scripting and other web vulnerabilities.

5. Cross-Site Request Forgery

Prevention: Store a secret token in a hidden form field that is inaccessible from the 3rd party site. You of course always have to verify this hidden field. Some sites ask for your password as well when modifying sensitive settings (like your password reminder email, for example), although I’d suspect this is there to prevent the misuse of your abandoned sessions (in an internet cafe for example).

6. Denial of Service (DoS)

Prevention: One way of mitigating a DDoS attack is by using load balancing. Load balancing is a technique to redirect incoming traffic to multiple servers. However, this can only be used if we have multiple servers at our disposal. In that case, if the attacked server goes down, traffic can be redirected to other servers. But, this is not full-proof solution. If the attacker targets our domain instead of a single server, then every time one server goes down, the requests (and hence the attack) will be transferred to other servers. And in the end, the attack will crash all the servers.

The other way is by using NGINX’s (or any server’s) rate limiting feature. Using this feature we can control the maximum incoming traffic from a source, and any additional traffic can be throttled to prevent the server from going down. This requires the source(s) of DDoS attacks to be identified so that the traffic from it/them can be filtered out. Read more

7. Security misconfiguration (Directory Listing)

Prevention: Have a good (preferably automated) “build and deploy” process, which can run tests on deploy. The poor man’s security misconfiguration solution is post-commit hooks, to prevent the code from going out with default passwords and/or development stuff built in.

8. Preventing account spoofing and take-over

Prevention: Users perform operations using their authentication token which they obtain upon login. Applications should always extract the userId from the token and compare it with the userId of the account being operated upon. This ensures that you cannot use user A’s token — though valid — to perform operations on user B’s account.

9. Failure to encrypt sensitive data.

Prevention:

  • In transit: Use HTTPS with a proper certificate and PFS (Perfect Forward Secrecy). Do not accept anything over non-HTTPS connections. Have the secure flag on cookies.
  • In storage: This is harder. First and foremost, you need to lower your exposure. If you don’t need sensitive data, shred it. Data you don’t have can’t be stolen. Do not store credit card information ever, as you probably don’t want to have to deal with being PCI compliant. Sign up with a payment processor such as Stripe or Braintree. Second, if you have sensitive data that you actually do need, store it encrypted and make sure all passwords are hashed. For hashing, the use of bcrypt is recommended. If you don’t use bcrypt, educate yourself on salting and rainbow tables.

And at the risk of stating the obvious, do not store the encryption keys next to the protected data. That’s like storing your bike with a lock that has the key in it. Protect your backups with encryption and keep your keys very private. And of course, don’t lose the keys!

If we talk about handling secrets such as database passwords, don’t ever check them into your Version Control System (VCS) as plain text. To store such precious info in VCS, you can encrypt them using such apps as git-crypt or git-secret. Another handy tool is Vault. It allows you to store and control access to your tokens, passwords, and other secret data.

10. Insufficient protection

Prevention: On the server-side, authorization must always be done. Yes, always. No exceptions or vulnerabilities will result in serious problems.

11: Using components with known vulnerabilities

Prevention:

  • Exercise caution. Beyond obviously using caution when using such components, do not be a copy-paste coder. Carefully inspect the piece of code you are about to put into your software, as it might be broken beyond repair (or in some cases, intentionally malicious — web security attacks are sometimes unwittingly invited in this way).
  • Stay up-to-date. Make sure you are using the latest versions of everything that you trust, and have a plan to update them regularly. At least subscribe to a newsletter of new security vulnerabilities regarding the product.

12. Insufficient protection

Prevention: On the server-side, authorization must always be done. Yes, always. No exceptions or vulnerabilities will result in serious problems.

Better three hours too soon than a minute too late - William Shakespeare

Web App Security — (Chirag Goel)

REFERENCES:

  1. https://medium.com/@engineerchirag/security-vulnerabilities-for-web-apps-4e944b5d7548
  2. https://www.owasp.org/index.php/OWASP_Secure_Headers_Project#rp
  3. https://www.future-processing.pl/blog/improving-security-of-your-web-application-with-security-headers/

Wrapping up

Few measures you should start applying before it’s too late:

  1. Avoid poor coding practices.
  2. Devote more time to quality assurance through manual and automated tests.
  3. Review and verify third-party software/ Open-Source Software Components.
  4. Determine what business data is the most sensitive.

Woo! We are done with the security measures & cool tricks to avoid security breaches.

Was this article helpful for you? Let me know in the comments below if you have any questions or thoughts! I’d love to hear them :)

Thanks for reading. Did this article help you in any way? If I did, I hope you consider sharing it you might just help someone who felt the same way you did before reading the article. Thank you.

Sharing makes you bigger than you are. The more you pour out, the more life will be able to pour in.

--

--

Senior Software Engineer @Microsoft | Blogger | Youtuber | Mentor | Entrepreneur. I’m the intersection of Technology, Business and Design.