3

Currently, am I learning about API and how to use them with dynamic websites. I've coded some sample Websites, where I get my data from an API.

I've been using innerHTML to add the content to my page. My teacher used createElement textContent and appendChild to add the content to his page during classes. When asked, he explained that innerHTML is much more unsecure as textContent, as e.g. if the API is unreliable or has been injected with an malicious code, innerHTML can edit the whole HTML, as instead of just the Content with textContent. So did ChaseMoskal try to explain in this comment innerText vs innerHtml vs label vs text vs textContent vs outerText

I get the basic idea, however, explaining with following code example, I feel that both present the same security issues.

var container = document.querySelector("#container");
var json1 = "Link to an image of my house";
var json2 = "Link to an image of my boat";
var jsonMaliciousCode = "maliciousCode3000"

// Create p element with innerHTML
container.innerHTML += "<a href=\""+maliciousCode+"\">" + json1 + "</a>";

// Create p element with textContent, href and appendChild
var innerExample = document.createElement('a');
innerExample.textContent = json2;
innerExample.href = maliciousCode;
container.appendChild(innerExample);

Working example: https://jsfiddle.net/vh8hLhbj/4/

What is it that I don't get or am missing out?

Advena
  • 1,664
  • 2
  • 24
  • 45
  • 1
    Well if you are going to let the user set the href of an element, you will probably want to validate at least the protocol – Bergi Jan 30 '18 at 10:20
  • It's not just insecure, it's also slow and breaks your DOM. – Bergi Jan 30 '18 at 10:21

2 Answers2

3

When you are using innerHTML anything can render inside it and you don't have control over it.

Check the following example.

var codeSnippet = "<div style='height:100px;width:100px;background-color:red' onclick='window.console.log(\"Anything!!!\");'><a href='#'>Click Here</a></div>";

document.getElementById('unsafe').innerHTML = codeSnippet;
document.getElementById('safe').textContent = codeSnippet;
<div id="unsafe">
</div>
<br>
<div id="safe">
</div>
Tushar Vaghela
  • 1,203
  • 1
  • 17
  • 25
  • In your example, you are using textContent and innerHTML in the same way, which is not the way somebody would write with textContent, which makes it difficult to understand your answer. (Refer to my example, as both result with the same content in a different way appropriate to the function) – Advena Jan 30 '18 at 11:15
2

The difference comes from the way your malicious code will be used. Using the following code might show you the difference :

var container = document.querySelector("#container");
var json1 = "Link to an image of my house";
var json2 = "Link to an image of my boat";
var maliciousCode = "javascript:alert('test');\" xxx=\"maliciousCode3000\""

// Create p element with innerHTML
container.innerHTML += "<a href=\""+maliciousCode+"\">" + json1 + "</a>";

// Create p element with textContent, href and appendChild
var innerExample = document.createElement('a');
innerExample.textContent = json2;
innerExample.href = maliciousCode;
container.appendChild(innerExample);

Here's the fiddle: https://jsfiddle.net/vh8hLhbj/6/

You will see the first example shows the popup, whereas the second does not. Imagine if it is some javascript accessing cookies, or watching keyboard input, for example.

Advena
  • 1,664
  • 2
  • 24
  • 45
Katz
  • 165
  • 6
  • Nice example! I can visually see that there's a difference, however, logically I'm struggling when I look at the resulting HTML. Both anchor tags have the same href but act different. How come? `Link to an image of my house` `Link to an image of my boat` – Advena Jan 30 '18 at 11:20
  • 1
    They don't have the same href, though : The first one is: `javascript:alert('test');` The second one is: `javascript:alert('test');" xxx="maliciousCode3000"` The second one is not correct javascript, and would throw an error. – Katz Jan 31 '18 at 08:16
  • I can see now the difference - watching the code with inspector tool, both anchors looked similar. By copy pasting it here, it showed the real difference. Now am I just wondering if you could direct me to understand why .href display \" as &quot ? That would be really helpful! – Advena Jan 31 '18 at 16:13
  • 1
    Because when you use .href, you are basicaly telling the browser : Whatever I put in there goes into the "href" attribute. So the browser encodes all text in the variable to fit inside the attribute. The only way to display a double quote safely inside an attribute is to use the encoded character, which is ". You can try any html code in there, it will get encoded with the & version. Which is actually the answer to your intial question about why this is more secure : Any code in there doesn't get interpreted, it is displayed as plain text. – Katz Feb 01 '18 at 08:33
  • Amazing thanks! I've tried now to change the quotes inside the maliciousCode to " however href is not displaying a double quote, as you mentioned? – Advena Feb 01 '18 at 12:01