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
-
Systemd Fixes Bug While Facing New Challenger in GNU Shepherd
The systemd developers have fixed a really nasty bug amid the release of the new GNU Shepherd init system.
-
AlmaLinux 10.0 Beta Released
The AlmaLinux OS Foundation has announced the availability of AlmaLinux 10.0 Beta ("Purple Lion") for all supported devices with significant changes.
-
Gnome 47.2 Now Available
Gnome 47.2 is now available for general use but don't expect much in the way of newness, as this is all about improvements and bug fixes.
-
Latest Cinnamon Desktop Releases with a Bold New Look
Just in time for the holidays, the developer of the Cinnamon desktop has shipped a new release to help spice up your eggnog with new features and a new look.
-
Armbian 24.11 Released with Expanded Hardware Support
If you've been waiting for Armbian to support OrangePi 5 Max and Radxa ROCK 5B+, the wait is over.
-
SUSE Renames Several Products for Better Name Recognition
SUSE has been a very powerful player in the European market, but it knows it must branch out to gain serious traction. Will a name change do the trick?
-
ESET Discovers New Linux Malware
WolfsBane is an all-in-one malware that has hit the Linux operating system and includes a dropper, a launcher, and a backdoor.
-
New Linux Kernel Patch Allows Forcing a CPU Mitigation
Even when CPU mitigations can consume precious CPU cycles, it might not be a bad idea to allow users to enable them, even if your machine isn't vulnerable.
-
Red Hat Enterprise Linux 9.5 Released
Notify your friends, loved ones, and colleagues that the latest version of RHEL is available with plenty of enhancements.
-
Linux Sees Massive Performance Increase from a Single Line of Code
With one line of code, Intel was able to increase the performance of the Linux kernel by 4,000 percent.