Javascript에서 HTML 엔티티를 이스케이프 처리 하시겠습니까?


177

XML-RPC 백엔드와 통신하는 Javascript 코드가 있습니다. XML-RPC는 다음 형식의 문자열을 반환합니다.

<img src='myimage.jpg'>

그러나 Javascript를 사용하여 문자열을 HTML에 삽입하면 문자 그대로 렌더링됩니다. 이미지가 보이지 않고 문자 그대로 문자열이 표시됩니다.

<img src='myimage.jpg'>

내 생각 엔 HTML-RPC 채널을 통해 HTML이 이스케이프되고 있다고 생각합니다.

Javascript에서 문자열을 이스케이프 해제하려면 어떻게해야합니까? 이 페이지의 기술을 실패했습니다. http://paulschreiber.com/blog/2008/09/20/javascript-how-to-unescape-html-entities/

문제를 진단하는 다른 방법은 무엇입니까?


1
이것을보십시오 : stackoverflow.com/questions/4480757/…
XP1

답변:


177

편집 : Wladimir가 제안한 대로 DOMParser API를 사용해야 합니다. 게시 된 함수에 보안 취약점이 도입 되었으므로 이전 답변을 편집했습니다.

다음 스 니펫은 약간 수정 된 이전 답변의 코드입니다. textarea 대신 divXSS 취약성을 대신 IE9 및 Firefox에서 여전히 문제가됩니다.

function htmlDecode(input){
  var e = document.createElement('textarea');
  e.innerHTML = input;
  // handle case of empty input
  return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
}

htmlDecode("&lt;img src='myimage.jpg'&gt;"); 
// returns "<img src='myimage.jpg'>"

기본적으로 프로그래밍 방식으로 DOM 요소를 만들고, 인코딩 된 HTML을 innerHTML에 할당하고 innerHTML 삽입에서 생성 된 텍스트 노드에서 nodeValue를 검색합니다. 요소를 만들지 만 추가하지 않기 때문에 사이트 HTML은 수정되지 않습니다.

크로스 브라우저 (이전 브라우저 포함)에서 작동하며 모든 브라우저를 수락합니다. HTML 문자 엔티티를 .

편집 :이 코드의 이전 버전은 IE에서 공백 입력이 작동하지 않았습니다. jsFiddle (IE에서보기)에서 . 위의 버전은 모든 입력에서 작동합니다.

업데이트 : 이것은 큰 문자열에서 작동하지 않으며 보안 취약점을 유발합니다. 의견을 참조하십시오.


알겠습니다. '로 변경되었으므로 내 의견을 다시 삭제하겠습니다. thx, 효과가 뛰어납니다. +1
YOU

1
@ S.Mark : &apos;HTML 4 엔티티에 속하지 않습니다. w3.org/TR/html4/sgml/entities.html fishbowl.pastiche.org/2003/07/01/the_curse_of_apos
CMS

2
이 접근 방식의 보안 성이 좋지 않다는 @kender의 노트를 참조하십시오.
Joseph Turian 2009

2
그가 수행 한 열악한 테스트에 대해 @kender에게 내 메모를 참조하십시오.)
Roatin Marth

24
이 함수는 보안 상 위험하므로 DOM에 요소를 추가하지 않아도 JavaScript 코드가 실행됩니다. 입력 문자열을 신뢰할 수있는 경우에만 사용할 수 있습니다. 문제를 설명하고 안전한 솔루션을 제공하는 자체 답변을 추가했습니다 . 부작용으로 여러 텍스트 노드가 존재하는 경우 결과가 잘리지 않습니다.
Wladimir Palant

375

여기에 주어진 대부분의 답변에는 큰 단점이 있습니다. 변환하려는 문자열을 신뢰할 수 없으면 XSS (Cross-Site Scripting) 취약점이 생깁니다 . 허용되는 답변 의 기능에 대해 다음을 고려하십시오.

htmlDecode("<img src='dummy' onerror='alert(/xss/)'>");

여기의 문자열에는 이스케이프 처리되지 않은 HTML 태그가 포함되어 있으므로 아무것도 디코딩하는 대신 htmlDecode함수는 실제로 문자열 내에 지정된 JavaScript 코드를 실행합니다.

모든 최신 브라우저 에서 지원되는 DOMParser 를 사용하면이를 피할 수 있습니다 .

function htmlDecode(input) {
  var doc = new DOMParser().parseFromString(input, "text/html");
  return doc.documentElement.textContent;
}

console.log(  htmlDecode("&lt;img src='myimage.jpg'&gt;")  )    
// "<img src='myimage.jpg'>"

console.log(  htmlDecode("<img src='dummy' onerror='alert(/xss/)'>")  )  
// ""

이 함수는 JavaScript 코드를 부작용으로 실행하지 않습니다. 모든 HTML 태그는 무시되며 텍스트 내용 만 반환됩니다.

호환성 참고 사항 : HTML을 파싱 DOMParser하려면 Chrome 30, Firefox 12, Opera 17, Internet Explorer 10, Safari 7.1 또는 Microsoft Edge가 필요합니다. 따라서 지원이없는 모든 브라우저는 EOL을 지나고 있으며 2017 년 현재 야생에서 여전히 볼 수있는 유일한 브라우저는 이전 Internet Explorer 및 Safari 버전입니다 (일반적으로 여전히 귀찮게하기에는 충분하지 않습니다).


19
이 답변은 XSS 취약점을 언급했기 때문에 가장 적합하다고 생각합니다.
Константин Ван

2
Firefox 12.0 이전 DOMParser에는 ( 참조에 따라) 지원하지 않았으며 지원하지 않는 최신 버전의 브라우저가 여전히 있습니다 . 귀하의 참조에 따르면, 여전히 실험 기술이며, stand-in 은 내 접근 방식 에 따라 지적한 바와 같이이 XSS 취약점 (브라우저 공급 업체가 수정해야 함)이 있는 속성을 사용합니다 . "text/html"DOMParser.prototype.parseFromString()DOMParserinnerHTML
PointedEars

4
@PointedEars : 2016 년 Firefox 12에 관심이있는 사람은 누구입니까? 문제는 Internet Explorer 최대 9.0, Safari 최대 7.0입니다. 지원하지 않을 수 있다면 (곧 모든 사람이 될 것입니다) DOMParser가 최선의 선택입니다. 그렇지 않은 경우 처리 엔터티 만 옵션이됩니다.
블라디미르 팔란 트

4
@PointedEars : <script>실행되지 않는 태그는 보안 메커니즘이 아니며,이 규칙은 설정 innerHTML이 동기 스크립트를 부작용으로 실행할 수있는 경우 까다로운 타이밍 문제를 피합니다 . innerHTML웹 페이지가 실제로 인라인 이벤트 핸들러를 설정하려고 할 수 있기 때문에 HTML 코드를 위생 처리하는 것은 까다로운 작업이며 시도조차하지 않습니다. 이것은 단순히 안전하지 않은 데이터, 완전 정지를위한 메커니즘이 아닙니다.
Wladimir Palant

1
@ ИльяЗеленько :이 코드를 타이트한 루프로 사용 하시겠습니까? 아니면 성능이 왜 중요한가요? 귀하의 답변은 XSS에 다시 취약합니다. 정말 가치가 있습니까?
Wladimir Palant

37

jQuery를 사용하는 경우 :

function htmlDecode(value){ 
  return $('<div/>').html(value).text(); 
}

그렇지 않으면 기능 이 우수한 Strictly Software의 Encoder Object를 사용하십시오 htmlDecode().


59
에 의해 생성 된 사용자가 생성 한 콘텐츠를 다른 것보다 내용이 사용하지 (반복하지) 않습니다 사용자. 값에 <script> 태그가 있으면 스크립트의 내용이 실행됩니다!
Malvolio

사이트의 어느 곳에서나 해당 라이센스를 찾을 수 없습니다. 라이센스가 무엇인지 아십니까?
TRiG

소스 헤더에 라이센스가 있으며 GPL입니다.
Chris Fulstow

6
예, 그 기능은 XSS를위한 길을 열어줍니다 : try htmlDecode ( "<script> alert (12) </ script> 123 & gt;")
Dinis Cruz

$ ( '<div />') 의 의미는 무엇 입니까?
에코 양

13

비결은 브라우저의 힘을 사용하여 특수 HTML 문자를 해독하지만 브라우저가 실제 HTML 인 것처럼 결과를 실행할 수 없도록하는 것입니다.이 함수는 정규식을 사용하여 인코딩 된 HTML 문자 (한 문자)를 식별하고 대체합니다. 한 번에.

function unescapeHtml(html) {
    var el = document.createElement('div');
    return html.replace(/\&[#0-9a-z]+;/gi, function (enc) {
        el.innerHTML = enc;
        return el.innerText
    });
}

/\&#?[0-9a-z]+;/gi#은 두 번째 문자로만 나타나야하기 때문에 정규 표현식을 조금 더 밀접하게 일치시킬 수 있습니다 .
TheAtomicOption

이것이 가장 좋은 대답입니다. XSS 취약점을 피하고 HTML 태그를 제거하지 않습니다.
Emmanuel

6

이스케이프를 제거하려는 HTML이 매우 길지 않고 65536자를 초과하지 않는 한 CMS의 대답은 제대로 작동합니다. Chrome에서 내부 HTML은 각각 최대 65536 개의 많은 하위 노드로 분할되므로 연결해야합니다. 이 함수는 매우 긴 문자열에도 작동합니다.

function unencodeHtmlContent(escapedHtml) {
  var elem = document.createElement('div');
  elem.innerHTML = escapedHtml;
  var result = '';
  // Chrome splits innerHTML into many child nodes, each one at most 65536.
  // Whereas FF creates just one single huge child node.
  for (var i = 0; i < elem.childNodes.length; ++i) {
    result = result + elem.childNodes[i].nodeValue;
  }
  return result;
}

자세한 내용은 innerHTML최대 길이에 대한 이 답변을 참조하십시오 : https : //.com/a/27545633/694469


3

질문에 대한 직접적인 대답은 아니지만 RPC가 해당 구조 내부의 이미지 데이터 (예 : URL)와 함께 일부 구조 (XML 또는 JSON 등)를 반환하는 것이 더 좋지 않습니까?

그런 다음 자바 스크립트에서 구문 분석하고 <img>Javascript 자체를 사용하여 빌드 할 수 있습니다.

RPC에서받는 구조는 다음과 같습니다.

{"img" : ["myimage.jpg", "myimage2.jpg"]}

외부 소스에서 오는 코드를 페이지에 삽입하는 것이 안전하지 않기 때문에이 방법이 더 낫습니다. 누군가 XML-RPC 스크립트를 가로 채서 원하지 않는 것을 (아마도 일부 자바 스크립트 ...)


위의 @CMS 접근 방식에 이러한 보안 결함이 있습니까?
Joseph Turian 2009

방금 htmlDecode 기능에 전달 된 다음 인수를 확인했습니다. htmlDecode ( "& lt; img src = 'myimage.jpg'& gt; & lt; script & gt; document.write ( 'xxxxx'); & lt; / script & gt;") <script> </ script> 나쁜 요소 일 수 있습니다. 그리고 여전히 삽입 할 텍스트 대신 구조를 반환하는 것이 좋습니다. 예를 들어 오류를 잘 처리 할 수 ​​있습니다.
켄더

1
방금 시도했지만 htmlDecode("&lt;img src='myimage.jpg'&gt;&lt;script&gt;alert('xxxxx');&lt;/script&gt;")아무 일도 일어나지 않았습니다. 예상대로 디코딩 된 html 문자열을 다시 얻었습니다.
Roatin Marth

2

크리스의 대답은 훌륭하고 우아하지만 가치가 정의되지 않으면 실패합니다 . 단순한 개선만으로도 견고 해집니다.

function htmlDecode(value) {
   return (typeof value === 'undefined') ? '' : $('<div/>').html(value).text();
}

개선하면 다음과 같이하십시오.return (typeof value !== 'string') ? '' : $('<div/>').html(value).text();
SynCap

2

당신은 환영합니다 ... 메신저 ... 전체 크레딧은 ourcodeworld.com으로 연결됩니다. 아래 링크.

window.htmlentities = {
        /**
         * Converts a string to its html characters completely.
         *
         * @param {String} str String with unescaped HTML characters
         **/
        encode : function(str) {
            var buf = [];

            for (var i=str.length-1;i>=0;i--) {
                buf.unshift(['&#', str[i].charCodeAt(), ';'].join(''));
            }

            return buf.join('');
        },
        /**
         * Converts an html characterSet into its original character.
         *
         * @param {String} str htmlSet entities
         **/
        decode : function(str) {
            return str.replace(/&#(\d+);/g, function(match, dec) {
                return String.fromCharCode(dec);
            });
        }
    };

전체 신용 : https://ourcodeworld.com/articles/read/188/encode-and-decode-html-entities-using-pure-javascript


2

이것은 지금까지 시도한 가장 포괄적 인 솔루션입니다.

const STANDARD_HTML_ENTITIES = {
    nbsp: String.fromCharCode(160),
    amp: "&",
    quot: '"',
    lt: "<",
    gt: ">"
};

const replaceHtmlEntities = plainTextString => {
    return plainTextString
        .replace(/&#(\d+);/g, (match, dec) => String.fromCharCode(dec))
        .replace(
            /&(nbsp|amp|quot|lt|gt);/g,
            (a, b) => STANDARD_HTML_ENTITIES[b]
        );
};

"가장 포괄적 인"? 실제로 포괄적 인 테스트 스위트 에 대해 실행 해 보셨습니까 ?
Dan Dascalescu

1

나는이 기능을 완벽하게 완성하지는 않지만 철저하게 진행할만큼 미쳤습니다.

function removeEncoding(string) {
    return string.replace(/&Agrave;/g, "À").replace(/&Aacute;/g, "Á").replace(/&Acirc;/g, "Â").replace(/&Atilde;/g, "Ã").replace(/&Auml;/g, "Ä").replace(/&Aring;/g, "Å").replace(/&agrave;/g, "à").replace(/&acirc;/g, "â").replace(/&atilde;/g, "ã").replace(/&auml;/g, "ä").replace(/&aring;/g, "å").replace(/&AElig;/g, "Æ").replace(/&aelig;/g, "æ").replace(/&szlig;/g, "ß").replace(/&Ccedil;/g, "Ç").replace(/&ccedil;/g, "ç").replace(/&Egrave;/g, "È").replace(/&Eacute;/g, "É").replace(/&Ecirc;/g, "Ê").replace(/&Euml;/g, "Ë").replace(/&egrave;/g, "è").replace(/&eacute;/g, "é").replace(/&ecirc;/g, "ê").replace(/&euml;/g, "ë").replace(/&#131;/g, "ƒ").replace(/&Igrave;/g, "Ì").replace(/&Iacute;/g, "Í").replace(/&Icirc;/g, "Î").replace(/&Iuml;/g, "Ï").replace(/&igrave;/g, "ì").replace(/&iacute;/g, "í").replace(/&icirc;/g, "î").replace(/&iuml;/g, "ï").replace(/&Ntilde;/g, "Ñ").replace(/&ntilde;/g, "ñ").replace(/&Ograve;/g, "Ò").replace(/&Oacute;/g, "Ó").replace(/&Ocirc;/g, "Ô").replace(/&Otilde;/g, "Õ").replace(/&Ouml;/g, "Ö").replace(/&ograve;/g, "ò").replace(/&oacute;/g, "ó").replace(/&ocirc;/g, "ô").replace(/&otilde;/g, "õ").replace(/&ouml;/g, "ö").replace(/&Oslash;/g, "Ø").replace(/&oslash;/g, "ø").replace(/&#140;/g, "Œ").replace(/&#156;/g, "œ").replace(/&#138;/g, "Š").replace(/&#154;/g, "š").replace(/&Ugrave;/g, "Ù").replace(/&Uacute;/g, "Ú").replace(/&Ucirc;/g, "Û").replace(/&Uuml;/g, "Ü").replace(/&ugrave;/g, "ù").replace(/&uacute;/g, "ú").replace(/&ucirc;/g, "û").replace(/&uuml;/g, "ü").replace(/&#181;/g, "µ").replace(/&#215;/g, "×").replace(/&Yacute;/g, "Ý").replace(/&#159;/g, "Ÿ").replace(/&yacute;/g, "ý").replace(/&yuml;/g, "ÿ").replace(/&#176;/g, "°").replace(/&#134;/g, "†").replace(/&#135;/g, "‡").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&#177;/g, "±").replace(/&#171;/g, "«").replace(/&#187;/g, "»").replace(/&#191;/g, "¿").replace(/&#161;/g, "¡").replace(/&#183;/g, "·").replace(/&#149;/g, "•").replace(/&#153;/g, "™").replace(/&copy;/g, "©").replace(/&reg;/g, "®").replace(/&#167;/g, "§").replace(/&#182;/g, "¶").replace(/&Alpha;/g, "Α").replace(/&Beta;/g, "Β").replace(/&Gamma;/g, "Γ").replace(/&Delta;/g, "Δ").replace(/&Epsilon;/g, "Ε").replace(/&Zeta;/g, "Ζ").replace(/&Eta;/g, "Η").replace(/&Theta;/g, "Θ").replace(/&Iota;/g, "Ι").replace(/&Kappa;/g, "Κ").replace(/&Lambda;/g, "Λ").replace(/&Mu;/g, "Μ").replace(/&Nu;/g, "Ν").replace(/&Xi;/g, "Ξ").replace(/&Omicron;/g, "Ο").replace(/&Pi;/g, "Π").replace(/&Rho;/g, "Ρ").replace(/&Sigma;/g, "Σ").replace(/&Tau;/g, "Τ").replace(/&Upsilon;/g, "Υ").replace(/&Phi;/g, "Φ").replace(/&Chi;/g, "Χ").replace(/&Psi;/g, "Ψ").replace(/&Omega;/g, "Ω").replace(/&alpha;/g, "α").replace(/&beta;/g, "β").replace(/&gamma;/g, "γ").replace(/&delta;/g, "δ").replace(/&epsilon;/g, "ε").replace(/&zeta;/g, "ζ").replace(/&eta;/g, "η").replace(/&theta;/g, "θ").replace(/&iota;/g, "ι").replace(/&kappa;/g, "κ").replace(/&lambda;/g, "λ").replace(/&mu;/g, "μ").replace(/&nu;/g, "ν").replace(/&xi;/g, "ξ").replace(/&omicron;/g, "ο").replace(/&piρ;/g, "ρ").replace(/&rho;/g, "ς").replace(/&sigmaf;/g, "ς").replace(/&sigma;/g, "σ").replace(/&tau;/g, "τ").replace(/&phi;/g, "φ").replace(/&chi;/g, "χ").replace(/&psi;/g, "ψ").replace(/&omega;/g, "ω").replace(/&bull;/g, "•").replace(/&hellip;/g, "…").replace(/&prime;/g, "′").replace(/&Prime;/g, "″").replace(/&oline;/g, "‾").replace(/&frasl;/g, "⁄").replace(/&weierp;/g, "℘").replace(/&image;/g, "ℑ").replace(/&real;/g, "ℜ").replace(/&trade;/g, "™").replace(/&alefsym;/g, "ℵ").replace(/&larr;/g, "←").replace(/&uarr;/g, "↑").replace(/&rarr;/g, "→").replace(/&darr;/g, "↓").replace(/&barr;/g, "↔").replace(/&crarr;/g, "↵").replace(/&lArr;/g, "⇐").replace(/&uArr;/g, "⇑").replace(/&rArr;/g, "⇒").replace(/&dArr;/g, "⇓").replace(/&hArr;/g, "⇔").replace(/&forall;/g, "∀").replace(/&part;/g, "∂").replace(/&exist;/g, "∃").replace(/&empty;/g, "∅").replace(/&nabla;/g, "∇").replace(/&isin;/g, "∈").replace(/&notin;/g, "∉").replace(/&ni;/g, "∋").replace(/&prod;/g, "∏").replace(/&sum;/g, "∑").replace(/&minus;/g, "−").replace(/&lowast;/g, "∗").replace(/&radic;/g, "√").replace(/&prop;/g, "∝").replace(/&infin;/g, "∞").replace(/&OEig;/g, "Œ").replace(/&oelig;/g, "œ").replace(/&Yuml;/g, "Ÿ").replace(/&spades;/g, "♠").replace(/&clubs;/g, "♣").replace(/&hearts;/g, "♥").replace(/&diams;/g, "♦").replace(/&thetasym;/g, "ϑ").replace(/&upsih;/g, "ϒ").replace(/&piv;/g, "ϖ").replace(/&Scaron;/g, "Š").replace(/&scaron;/g, "š").replace(/&ang;/g, "∠").replace(/&and;/g, "∧").replace(/&or;/g, "∨").replace(/&cap;/g, "∩").replace(/&cup;/g, "∪").replace(/&int;/g, "∫").replace(/&there4;/g, "∴").replace(/&sim;/g, "∼").replace(/&cong;/g, "≅").replace(/&asymp;/g, "≈").replace(/&ne;/g, "≠").replace(/&equiv;/g, "≡").replace(/&le;/g, "≤").replace(/&ge;/g, "≥").replace(/&sub;/g, "⊂").replace(/&sup;/g, "⊃").replace(/&nsub;/g, "⊄").replace(/&sube;/g, "⊆").replace(/&supe;/g, "⊇").replace(/&oplus;/g, "⊕").replace(/&otimes;/g, "⊗").replace(/&perp;/g, "⊥").replace(/&sdot;/g, "⋅").replace(/&lcell;/g, "⌈").replace(/&rcell;/g, "⌉").replace(/&lfloor;/g, "⌊").replace(/&rfloor;/g, "⌋").replace(/&lang;/g, "⟨").replace(/&rang;/g, "⟩").replace(/&loz;/g, "◊").replace(/&#039;/g, "'").replace(/&amp;/g, "&").replace(/&quot;/g, "\"");
}

이렇게 사용 :

let decodedText = removeEncoding("Ich hei&szlig;e David");
console.log(decodedText);

인쇄물: Ich Heiße David

추신 : 이것은 1 시간 반 정도 걸렸습니다.


0

JavaScript에서 HTML 엔티티 *를 이스케이프 해제하려면 작은 라이브러리 html-escaper를 사용할 수 있습니다 .npm install html-escaper

import {unescape} from 'html-escaper';

unescape('escaped string');

또는 Lodash 또는 Underscore 에서 사용하는 경우 unescape기능 하십시오.


*이 기능은 모든 HTML 엔티티를 포함하지만,하지 않는 것이)하시기 바랍니다 참고 만 가장 일반적인 것들, 즉 &, <, >, ', ". 모든 HTML 엔티티 이스케이프 처리하려면 사용할 수 있습니다 그가 라이브러리를.


-1

나는 이것을 내 프로젝트에서 사용한다 : 다른 답변에서 영감을 얻었 지만 여분의 안전한 매개 변수를 사용하면 장식 된 캐릭터를 다룰 때 유용 할 수 있습니다

var decodeEntities=(function(){

    var el=document.createElement('div');
    return function(str, safeEscape){

        if(str && typeof str === 'string'){

            str=str.replace(/\</g, '&lt;');

            el.innerHTML=str;
            if(el.innerText){

                str=el.innerText;
                el.innerText='';
            }
            else if(el.textContent){

                str=el.textContent;
                el.textContent='';
            }

            if(safeEscape)
                str=str.replace(/\</g, '&lt;');
        }
        return str;
    }
})();

그리고 그것은 다음과 같이 사용할 수 있습니다 :

var label='safe <b> character &eacute;ntity</b>';
var safehtml='<div title="'+decodeEntities(label)+'">'+decodeEntities(label, true)+'</div>';

-1

여기에있는 다른 모든 대답에는 문제가 있습니다.

jQuery를 사용하는 것을 포함하여 document.createElement ( 'div') 메소드는 전달 된 모든 자바 스크립트 (보안 문제)를 실행하고 DOMParser.parseFromString () 메소드는 공백을 제거합니다. 문제가없는 순수한 자바 스크립트 솔루션은 다음과 같습니다.

function htmlDecode(html) {
    var textarea = document.createElement("textarea");
    html= html.replace(/\r/g, String.fromCharCode(0xe000)); // Replace "\r" with reserved unicode character.
    textarea.innerHTML = html;
    var result = textarea.value;
    return result.replace(new RegExp(String.fromCharCode(0xe000), 'g'), '\r');
}

TextArea는 특별히 실행 코드를 피하기 위해 사용됩니다. 다음을 통과합니다.

htmlDecode('&lt;&amp;&nbsp;&gt;'); // returns "<& >" with non-breaking space.
htmlDecode('  '); // returns "  "
htmlDecode('<img src="dummy" onerror="alert(\'xss\')">'); // Does not execute alert()
htmlDecode('\r\n') // returns "\r\n", doesn't lose the \r like other solutions.

1
아니요, 다른 태그를 사용해 문제가 해결 되지 않습니다 . 이것은 여전히 ​​XSS 취약점 htmlDecode("</textarea><img src=x onerror=alert(1)>")입니다. Sergio Belevskij의 답변에서 이미이 문제를 지적한 후에 이것을 게시했습니다.
Wladimir Palant

설명하신 문제를 재현 할 수 없습니다. 이 JsFiddle에 코드가 있으며 실행할 때 경고가 표시되지 않습니다. jsfiddle.net/edsjt15g/1 살펴볼 수 있습니까? 어떤 브라우저를 사용하고 있습니까?
EricP

2
Firefox를 사용하고 있습니다. 크롬은 실제로이 시나리오를 다르게 처리하므로 코드가 실행되지 않습니다-그러나 의존해서는 안됩니다.
블라디미르 팔란

-1
var encodedStr = 'hello &amp; world';

var parser = new DOMParser;
var dom = parser.parseFromString(
    '<!doctype html><body>' + encodedStr,
    'text/html');
var decodedString = dom.body.textContent;

console.log(decodedString);

@Wladimir Palant (AdBlock Plus의 저자)는 이미 4 년 전에 DOMParser에 대한 답변을 제공했습니다 . 답변을 게시하기 전에 이전 답변을 읽었습니까?
Dan Dascalescu

-7

맨 위의 답변만큼 80 % 생산적인 변형이 있습니다.

벤치 마크 참조 : https://jsperf.com/decode-html12345678/1

성능 테스트

console.log(decodeEntities('test: &gt'));

function decodeEntities(str) {
  // this prevents any overhead from creating the object each time
  const el = decodeEntities.element || document.createElement('textarea')

  // strip script/html tags
  el.innerHTML = str
    .replace(/<script[^>]*>([\S\s]*?)<\/script>/gmi, '')
    .replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gmi, '');

  return el.value;
}

태그를 남겨 두어야하는 경우 두 .replace(...)호출 을 제거하십시오 (스크립트가 필요없는 경우 첫 번째 호출을 남길 수 있음).


6
축하합니다, 실제로는 중요하지 않은 성능 승리를 위해 가짜 살균 논리로 취약점을 숨겼습니다. decodeEntities("</textarea '><img src=x onerror=alert(1) \">")Firefox에서 전화 해보십시오 . 정규식으로 HTML 코드를 삭제하려고 시도하지 마십시오.
Wladimir Palant
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.