Preventing web browsers from doing what attackers tell them to
Security Headers
Kurt explains how using security headers can provide extra protection from malicious content and web attacks.
If you remember when web apps were simple and hosted on a single site, you are by definition old; however, you probably also know that when apps are networked, the whole is greater than the sum of its parts.
For example, suppose you have two separate web apps, such as your retirement fund web site and a mortgage calculation web site, that are useful apps on their own. However, if you link these apps together, allowing users to specify their income and how much they currently pay for rent/mortgage and then calculate what kind of mortgage they can afford, then the whole thing is much more useful because they can figure out whether it's better to put money into their retirement fund or their mortgage payments and test various financial scenarios. You could also tie these into additional applications and sites, like your mutual funds, your tax calculations, and so on for even more functionality.
Of course, all this functionality comes at a cost: complexity. And, this added complexity gives attackers more avenues of approach. For example, an attacker could embed a copy of your bank's website using an iframe
within a hostile site that they control. This hostile site could have JavaScript that records all your key presses, so when you log in to your bank site, the password is sent to the attacker. Within an application, an attacker also can exploit cross-site scripting (XSS) to embed malicious JavaScript or content into a page to redirect the form data when you hit Submit. So, what's the solution? Layering more security (and complexity) onto the whole mess, of course!
Strict-Transport-Security
Strict-Transport-Security
is one of the simplest and most effective of the new security headers. HTTP Strict Transport Security (HSTS) allows you to specify that a domain (and optional subdomains) should only be served over HTTPS instead of HTTP. The idea is that when a user accesses your website from a safe location the first time (e.g., they register from home), you send them an HSTS header saying "user HTTPS for at least the next year." Then, when the user accesses your site from a coffee shop, for example, their browser only allows access to it via HTTPS, preventing man-in-the-middle attacks. In Apache, you can add the following header to serve HSTS headers for this site and all subdomains that are valid for 180 days:
Header set Strict-Transport-Security "max-age=15552000; includeSubDomains"
HSTS headers should only be served over HTTPS; so, to get people from your HTTP site to your HTTPS site, I recommend using a redirect. Alternatively, you can get whitelisted in some browsers (well, in Google Chrome [1]), which is ideal because then clients will always be protected.
X-Frame-Options
To prevent framing by hostile sites, you can specify which sites are allowed to put your content within an iframe
. The problem is that this action is handled on the client side, and not all browsers support X-Frame-Options
or all the capabilities they provide [2].
In that case, your best bet is either to set it and hope for the best or to do browser detection and use some JavaScript to see whether the window is "on top." Note, however, that you won't easily be able to allow it to be framed by specific sites and blocked by others (which is easy with X-Frame-Options
).
X-Frame-Options
has three settings: Deny
, which means no framing is allowed at all; Allow-From
, which lets you list specific sites and URLs that can embed the page in an iframe
; and SAMEORIGIN
, which allows anything from the same origin (basically the same domain) to embed it within an iframe
.
SAMEORIGIN
makes it easy to protect the content but still allow embedding by other pages on your site. This occurs at the risk that a page that doesn't need to embed the content has an XSS vulnerability that can be tricked into doing so. The XSS can then be used to inject JavaScript that copies the keystrokes, for example. If possible, you should use Deny
for any content that should never be embedded and use Allow-From
specifically to allow resources to be embedded as needed.
Access-Control-* Headers
With the modern tendency to combine web applications across multiple domains and organizations, you need to allow a web page on site A to trigger a request to site B (e.g., for an image or form). Traditionally, this behavior has led to a lot of security problems. For example, attackers can get users to visit a hostile site or load hostile content (e.g., by serving it over an ad network) and then trigger their web browser to load elements from another site, such as their bank, or their email service. Here, however, you run into a chicken-and-egg problem.
If you visit site A, and it tells you to load a resource from site B, how does your web browser know whether this action is allowed? Even if site B has a security policy with data served via HTTP headers that will let you know whether your browser is allowed to make the request, how do you know whether you are supposed to do so? The solution is that your web browser makes a "preflight" request, using the OPTIONS
request method (as opposed to GET
, POST
, TRACE
, and so on) for the resource, at which time site B's security policy is served via HTTP headers. Your web browser then processes these headers and decides whether or not it is allowed to make the request.
A large number of Access-Control-
* headers [3] are available that you can send (Table 1). Basically, you can control which URLs are allowed to make requests, how the request can be made, whether the client can send credentials when making the request, which headers the client can use, and more.
Table 1
Various Access-Control-* Options
Access-Control-* Header | Function |
---|---|
|
URI that may access this resource (e.g., |
|
Headers the browser is allowed to access |
|
How long it can be cached by the browser |
|
Whether or not credentials can be used in the request |
|
Methods allowed to be used by the browser (e.g., GET, POST, etc.) |
|
Which headers can be used when making the request |
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.
News
-
So Long Neofetch and Thanks for the Info
Today is a day that every Linux user who enjoys bragging about their system(s) will mourn, as Neofetch has come to an end.
-
Ubuntu 24.04 Comes with a “Flaw"
If you're thinking you might want to upgrade from your current Ubuntu release to the latest, there's something you might want to consider before doing so.
-
Canonical Releases Ubuntu 24.04
After a brief pause because of the XZ vulnerability, Ubuntu 24.04 is now available for install.
-
Linux Servers Targeted by Akira Ransomware
A group of bad actors who have already extorted $42 million have their sights set on the Linux platform.
-
TUXEDO Computers Unveils Linux Laptop Featuring AMD Ryzen CPU
This latest release is the first laptop to include the new CPU from Ryzen and Linux preinstalled.
-
XZ Gets the All-Clear
The back door xz vulnerability has been officially reverted for Fedora 40 and versions 38 and 39 were never affected.
-
Canonical Collaborates with Qualcomm on New Venture
This new joint effort is geared toward bringing Ubuntu and Ubuntu Core to Qualcomm-powered devices.
-
Kodi 21.0 Open-Source Entertainment Hub Released
After a year of development, the award-winning Kodi cross-platform, media center software is now available with many new additions and improvements.
-
Linux Usage Increases in Two Key Areas
If market share is your thing, you'll be happy to know that Linux is on the rise in two areas that, if they keep climbing, could have serious meaning for Linux's future.
-
Vulnerability Discovered in xz Libraries
An urgent alert for Fedora 40 has been posted and users should pay attention.