Is using href=“[removed]” dangerous in Angular 2+?

2019-08-22 06:01发布

问题:

From the Angular security guide, there's this:

To block XSS attacks, you must prevent malicious code from entering the DOM (Document Object Model). For example, if attackers can trick you into inserting a tag in the DOM, they can run arbitrary code on your website. The attack isn't limited to tags—many elements and properties in the DOM allow code execution, for example, <img onerror="..."> and <a href="javascript:...">. If attacker-controlled data enters the DOM, expect security vulnerabilities.

I've sometimes used <a href="javascript:" (click)="someFunction()">link</a> to target the element with CSS selectors (a:link) without the link referencing a URI, anchor, or running any code.

Is this a dangerous practice? They don't really give an example of how this could be exploited.

And if this is bad practice, then here's my dilemma: If I have a series of links in a nav, some of them ARE HREFs, and some of them bind to JS, but I want them all to look the same and use the same CSS selectors. Is there an easy way to accomplish that?

回答1:

Try adding an empty href for links that has (click)

<a (click)="action()" href>Previous</a>

If it doesn't work, you can try

<a href (click)="doSomething(); $event.preventDefault()">Link</a>
<a href (click)="!!doSomething()">Link</a>
<a href (click)="doSomething(); false">Link</a>


回答2:

What you are doing is fine.

This:

<a href="javascript:" (click)="someFunction()">link</a>

...is not an immediate security risk because you are not templateizing anything in your href.

This:

<a href="javascript:{{someVariable}}" (click)="someFunction()">link</a> 

...is a security risk, because the someVariable value can be something malicious that was entered by a user and will now get executed on click.

That being said, why do you need to use href="javascript:" at all? Just use an Angular (click) event and call preventDefault() on the event object to stop it from doing that behavior you described.

<a (click)="doSomething($event)"><a/>

doSomething(event: any) {
    event.preventDefault();
}

Update

Scott Marcus makes some good points. You really shouldn't use an a element here at all because it requires some workarounds (such as the preventDefault(). The best tool in the toolbox here is a span.

Use it like so:

<span (click)="doSomething()"></span>