innerHTML Element.prototype.innerHTML 프로퍼티는 요소 노드의 HTML 마크업을 취득하거나 변경할 때 사용합니다. 요소 노드의 innerHTML 프로퍼티를 참조하면 요소 노드의 콘텐츠 영역 내의 모든 HTML 마크업을 문자열로 반환하게 됩니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 <!DOCTYPE html> <html lang ="en" > <head > <meta charset ="UTF-8" /> <meta name ="viewport" content ="width=device-width, initial-scale=1.0" /> <title > temporal</title > <style > .red { color : red; } .blue { color : blue; } </style > </head > <body > <ul id ="list" > <li class ="red" > Apple</li > <li class ="red" > Banana</li > <li class ="red" > Orange</li > </ul > <script > console .log (document .getElementById ('list' ).innerHTML ); </script > </body > </html >
innerHTML 프로퍼티에 문자열을 할당하여 간단히 DOM 조작이 가능합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <!DOCTYPE html> <html lang ="en" > <head > <meta charset ="UTF-8" /> <meta name ="viewport" content ="width=device-width, initial-scale=1.0" /> <title > temporal</title > <style > .red { color : red; } .blue { color : blue; } </style > </head > <body > <ul id ="list" > </ul > <script > document.getElementById('list').innerHTML = '<li class ="red" > Apple</li > <li class ="red" > Banana</li > <li class ="red" > Orange</li > '; </script > </body > </html >
innerHTML 사용의 위험성 요소 노드의 innerHTML 프로퍼티에 할당한 HTML 마크업 문자열을 자바스크립트 엔진에 의해 파싱되어 DOM에 반영됩니다. 문제는 사용자로부터 입력받은 데이터를 innerHTML 프로퍼티에 할당하는 경우 엔진이 해당 라인을 파싱할 때 코드가 실행될 수 있는 위험이 있다는 것입니다. 만약 악의적 목적의 사용자가 input 값으로 악성 코드를 포함시킨다면 엔진이 파싱하는 과정에서 해당 코드가 평가되면서 실행되게 됩니다.
이러한 공격을 크로스 사이트 스크립팅(XSS)라고 합니다.
innerHTML 프로퍼티에 스크립트 태그를 삽입하는 예시 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <body> <form id ="testForm" > <textarea name ="test" id ="test" cols ="30" rows ="10" style ="width: 100%" > </textarea > <button type ="submit" > 결과 보기</button > </form > <div id ="result" style ="border: 5px solid red; height: 40px" > </div > </body> <script > const $form = document .getElementById ('testForm' ); const $textArea = document .getElementById ('test' ); const $result = document .getElementById ('result' ); const secretKey = 'abcd1234ImportantKey' ; $form.addEventListener ('submit' , e => { e.preventDefault (); $result.innerHTML = e.target .test .value ; }); </script >
innerHTML 사용 시 XSS 방어하는 방법 HTML5는 innerHTML 프로퍼티로 삽입된 script 요소 내의 자바스크립트 코드를 실행하지 않습니다. 그러나 위 예시처럼 태그 안의 onerror 등의 프로퍼티를 통해 실행되는 코드들까지는 막을 수 없습니다.
innerHTML 프로퍼티는 DOM 조작을 간편하고 직관적으로 할 수 있다는 장점이 있지만 XSS에 취약한 단점을 가지고 있습니다. 이 단점을 해결하기 위해 HTML 새니티제이션을 사용할 수 있습니다.
HTML 새니티제이션은 사용자로부터 입력받은 데이터에 의해 발생할 수 있는 XSS 공격을 예방하기 위해 잠재적 위험을 제거하는 기능입니다. 보통 DOMpurify 라이브러리 기능 등을 이용해 간편하게 구현이 가능합니다.
1 2 DOMPurify .sanitize ('<img src="/" onerror="alert(document.cookie)>' );