You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: secure_software_development_fundamentals.md
+16-8Lines changed: 16 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -3487,29 +3487,37 @@ This is true! The problem is not redirection, it is *unvalidated* redirection. O
3487
3487
3488
3488
[Web application]
3489
3489
3490
-
There is a peculiar problem with the HTML **target** attribute that many people are not aware of. Let’s explain the problem, and some partial solutions.
3490
+
There is a peculiar problem with some special uses of the HTML **target** attribute and JavaScript `window.open()` that many web developers are not aware of. Let’s explain the problem and some solutions.
3491
3491
3492
-
In HTML, **<a href=...>** creates a hyperlink. The HTML construct **<a href=... target=...>** creates a hyperlink where, if you click on it, it creates a new “target”. The default value for target is **_self**; if you set **target**, a common one is **target="_blank”** which creates the target in a new tab.
3492
+
In HTML, **<a href=...>** creates a hyperlink. The HTML construct **<a href=... target=...>** creates a hyperlink where, if you click on it, it creates a new named “target”. Using **target="_blank”** creates the target in a new tab. Historically setting **target="_blank”** could be a vulnerability, but the [HTML specification has been modified so **_blank** is no longer a problem](https://html.spec.whatwg.org/#following-hyperlinks) and modern browsers implement this fix.
3493
3493
3494
-
But what many don’t realize is that a value of “**target**” other than the default “**_self**” may, in some cases, create a vulnerability. Because of the way it works, the page being linked to runs in the *same* process as the calling page. As a result, on a click the receiving page gains partial control over the linking page, *even if they are from different origins*. The primary way this happens is through the **window.opener** value. The receiving page can do things like force the *calling* page to navigate to a different page (e.g., **window.opener.location.href = newURL**), provide a new page that looks like the old one (even though it is in a different place), and fool the user into doing something on the “same” page that is not the same at all. A related problem is that the new page may also get “referrer” information that you might not have expected.
3494
+
However, there's a special case you still need to worry about. If you do *all* of these things at the same time you may have a security problem:
3495
3495
3496
-
The same kind of problem can happen in JavaScript. JavaScript’s “**window.open**” has a default target of “**_blank**”; since that is not “**_self**”, the *default value* of **window.open()** is insecure. Again, it will open a window that loads another page that is simultaneously given control over its calling page, *even if* they have different origins.
3496
+
1. Use HTML tag "a" with a named target or use JavaScript **window.open()** with a named target, *and*
3497
+
2. The new page being loaded is from some (other) system that you don't totally trust, *and*
3498
+
3. The named target is something *other* than the safe values **_self** (the default for HTML's a tag), **_blank** (the default for JavaScript's **window.open()**), **_parent**, or **_top**.
3497
3499
3498
-
Of course, if you can trust that other page, that is not a security problem. So using a target value is often not a problem as long as you are referring to your *own* site. But if you are referring to another site, this may be more of a concern - are you sure you can trust it? Even if you trust your own or another site, it might be unwise to allow this - what happens if someone breaks into that part or that other site? Again, there is the principle of least privilege - we don’t want to give privileges if we don’t need to. This can also be a minor performance problem; page performance may suffer due to use of a shared process.
3500
+
Where possible, when loading pages from other sites, don't use named targets (other than the safe ones listed above). If you really must use this unusual circumstance, fix this in HTML by adding **rel="noopener"** to the "a" tag.
3499
3501
3500
-
The simplest solution is to avoid using **target=...** in HTML, and always set **target="_self"** when calling JavaScript **window.open()...** especially for links to user-generated content and external domains. If you decide to use HTML **target=**, also use **rel="noopener noreferrer"**. The “**noopener**” tells the web browser to *not* allow the JavaScript to gain control over the referring window (so **window.opener** won’t give access to it). The ”**noreferrer**” prevents passing on the referrer information to the new tab/window ([*Security Vulnerability and Browser Performance Impact of Target=”_blank”*](https://medium.com/@darrensimio/security-vulnerability-and-browser-performance-impact-of-target-blank-80e5e67db547) by Darren Sim, 2019).
3502
+
Explaining why this odd combination is a security problem is complicated. The underlying problem is that web browsers need to support legacy systems. Fundamentally, when there is a named target, the browser will re-use an existing window by that name, or create one if there aren't any. The browser will then provide that window with an "opener" value set to its requestor. This was a common pattern for older websites to implement pop-ups. This approach is fine if the named window is trusted by the requestor. However, this provides a mechanism for the newer page to manipulate the web page of its caller. This enables, for example, "tabnapping", where the new site tricks the user by controlling another tab. If no countermeasure is taken, the receiving page can do things like force the *calling* page to navigate to a different page (e.g., **window.opener.location.href = newURL**), provide a new page that looks like the old one (even though it is in a different place), and fool the user into doing something on the “same” page that is not the same at all.
3503
+
3504
+
This used to be a more common problem, because at one time this also impacted **_blank**. Today browsers automatically add **rel="noopener"** when **_blank** is the target. The other "safe" named targets (listed above) are from the same origin, so again the problem can't happen. But if you use one of these less-common cases, you must handle it yourself.
3505
+
3506
+
You may see some older documents recommending the use of **rel="noreferrer"**. You don't need to do that any more as long as you don't change the browser's default referrer value. Modern browsers by default now have a setting of "strict-origin-when-cross-origin"; that means that when a different origin is loaded, the new origin sees the domain but *not* the path or other details about the page the user was viewing before. As long as you're happy with that default, or set an even stricter one, you're fine. However, if you set a looser value (and be careful before doing that), **rel="noreferrer"** will prevent that detailed information from getting to the other site in that specific case. You can combine **noopener** and **noreferrer** as **rel="noopener noreferrer"**. You should, in general, try to use secure defaults instead of trying to separately set a secure value on each use.
3507
+
3508
+
A historical discussion of these problems, before the defaults were changed, can be found in [*Security Vulnerability and Browser Performance Impact of Target=”_blank”*](https://medium.com/@darrensimio/security-vulnerability-and-browser-performance-impact-of-target-blank-80e5e67db547) by Darren Sim, 2019.
3501
3509
3502
3510
#### Quiz 4.8: HTML **target** and JavaScript **window.open()**
3503
3511
3504
-
\>\>In an HTML anchor (**<a href=...>**) to another site, if you use **target=...** with a value other than **_self**, be sure to also set “**rel**” to “**noopener noreferrer**” prevent control by that other site of the originating tab. True or False?<<
3512
+
\>\>In an HTML anchor (**<a href=...>**) to another site, if you use **target=...** with a value such as **new_window**, be sure to also set “**rel**” to "**noopener**" or “**noopener noreferrer**” to prevent control by that other site of the originating tab. True or False?<<
3505
3513
3506
3514
(x) True
3507
3515
3508
3516
( ) False
3509
3517
3510
3518
[Explanation]
3511
3519
3512
-
This is true! Yes, this is a weird and subtle point. There is reason to hope that future developments in HTML and JavaScript will close this unexpected security hole, but for now, it is important to know about it.
3520
+
This is true! Yes, this is a weird and subtle point. There has been progress on making this less of a problem; changes to handling of **_blank** have made this much less common. There is reason to hope that future developments in HTML and JavaScript will completely close this unexpected security hole, but for now, we want you to know about it.
0 commit comments