Kutipan melarikan diri dalam JavaScript

211

Saya mengeluarkan nilai dari database (tidak benar-benar terbuka untuk entri publik, tetapi terbuka untuk entri oleh pengguna di perusahaan - artinya, saya tidak khawatir tentang XSS ).

Saya mencoba menampilkan tag seperti ini:

<a href="" onclick="DoEdit('DESCRIPTION');">Click Me</a>

DESCRIPTION sebenarnya adalah nilai dari database yang kira-kira seperti ini:

Prelim Assess "Mini" Report

Saya sudah mencoba mengganti "dengan \", tetapi apa pun yang saya coba, Firefox terus memotong panggilan JavaScript saya setelah spasi setelah kata Menilai , dan itu menyebabkan segala macam masalah.

Saya harus mengabaikan jawaban yang jelas, tetapi untuk kehidupan saya, saya tidak bisa mengetahuinya.

Adakah yang mau menunjukkan kebodohan saya?

Berikut ini adalah seluruh halaman HTML (pada akhirnya akan menjadi halaman ASP.NET , tetapi untuk menyelesaikannya, saya mengambil semua yang lain kecuali kode masalah)

<html>
    <body>
        <a href="#" onclick="DoEdit('Preliminary Assessment \"Mini\"'); return false;">edit</a>
    </body>
</html>
Matt Dawdy
sumber
3
Merupakan ide bagus untuk membuat onclicklampiran acara Anda tidak mengganggu dan memindahkan semua informasi basis data Anda ke pulau data. Segala sesuatu akan menjadi lebih bersih dan Anda akan benar-benar mendapatkan semacam kesalahan sintaksis ketika string Anda lolos dengan salah.
Justin Johnson
Anda juga dapat menggunakan metode jquery escape ("string") dan unescape ("string")
Abhiram

Jawaban:

212

Anda harus keluar dari string yang Anda tulis DoEdituntuk menghapus karakter tanda kutip ganda. Mereka menyebabkan onclickatribut HTML ditutup sebelum waktunya.

Menggunakan karakter pelarian JavaScript \,, tidak cukup dalam konteks HTML. Anda perlu mengganti penawaran ganda dengan representasi entitas XML yang tepat &quot;,.

Harun
sumber
Benar, tapi bukankah ini yang terjadi? <a href= " Ini harus menjadi WTF sederhana tetapi untuk kehidupan saya, saya tidak bisa melihatnya.
Matt Dawdy
Apakah ada fungsi JavaScript bawaan yang akan lolos dari tanda kutip ganda? Selain dari 'quo "', ganti ('"', '& quot;') Saya tidak dapat menemukan apa pun.
kevin
4
Ini bukan masalah javascript, ini masalah penyandian HTML / XML: Anda tidak dapat memiliki karakter tanda kutip ganda di dalam nilai atribut tanpa menghilangkannya ... jika tidak peramban / pengurai berpikir Anda mengakhiri deklarasi nilai atribut.
Aaron
22
contoh kode pengganti:'mystring'.replace(/"/g, '&quot;');
Joshua Burns
3
dalam komentar sebelumnya ada kutipan tambahan. Kode yang berfungsi adalah 'mystring'.replace (/' / g, '& quot;');
Agustin Lopez
95

&quot; akan bekerja dalam kasus khusus ini, seperti yang disarankan sebelum saya, karena konteks HTML.

Namun, jika Anda ingin kode JavaScript Anda untuk secara independen lolos untuk konteks apapun, Anda bisa memilih untuk encoding JavaScript asli:
'menjadi \x27
"menjadi\x22

Jadi klik Anda akan menjadi:
DoEdit('Preliminary Assessment \x22Mini\x22');

Ini akan berfungsi misalnya juga ketika meneruskan string JavaScript sebagai parameter ke metode JavaScript lain ( alert()adalah metode pengujian yang mudah untuk ini).

Saya merujuk Anda ke duplikat pertanyaan Stack Overflow, Bagaimana cara saya melepaskan string di dalam kode JavaScript di dalam handler onClick? .

tsemer
sumber
2
Terima kasih! Milik Anda adalah jawaban yang lebih benar karena itu adalah JavaScript asli tanpa memandang konteksnya.
scarver2
2
Ini adalah jawaban yang benar, meskipun dalam konteks HTML menggunakan &quot;kehendak, tentu saja, berhasil.
Oliver
Catatan yang &quot;diperlukan dalam nilai input, yaitu, <input value="\x22quoted string\x22">tidak akan berfungsi.
thdoan
@ 10basetom secara alami, JavaScript yang lolos hanya berfungsi dalam konteks JavaScript, seperti event handler ( onclick="..."). Nilai valueatribut tidak sedang diproses dalam konteks JavaScript, hanya dalam konteks HTML.
tsemer
kode pengganti:'mystring'.replace(/"/g, '\\x22').replace(/'/g, '\\x27')
ayam
33
<html>
    <body>
        <a href="#" onclick="DoEdit('Preliminary Assessment &quot;Mini&quot;'); return false;">edit</a>
    </body>
</html>

Sebaiknya lakukan triknya.

orang kristen
sumber
24

Teman-teman, sudah ada unescapefungsi dalam JavaScript yang melakukan unescaping untuk \":

<script type="text/javascript">
    var str="this is \"good\"";
    document.write(unescape(str))
</script>
rohtakdev
sumber
2
Kombinasi "pelarian" / "unescape" melakukan apa yang saya butuhkan. Terima kasih.
Luis R.
8
escape / unescape sudah usang. meskipun encodeURI melakukan lebih dari sekedar mengutip. gotochriswest.com/blog/2011/05/23/escape-unescape-deprecated
chug2k
12

Masalahnya adalah HTML tidak mengenali karakter pelarian. Anda bisa mengatasinya dengan menggunakan tanda kutip tunggal untuk atribut HTML dan tanda kutip ganda untuk klik tersebut.

<a href="#" onclick='DoEdit("Preliminary Assessment \"Mini\""); return false;'>edit</a>
dl.
sumber
5
Astaga. Saya bertanya-tanya mengapa saya terpaksa menggunakan 'untuk atribut di masa lalu. Aku hanya tidak pernah menggali semua itu sedalam itu. Terima kasih.
Matt Dawdy
6

Inilah yang saya lakukan pada dasarnya str.replace(/[\""]/g, '\\"').

var display = document.getElementById('output');
var str = 'class="whatever-foo__input" id="node-key"';
display.innerHTML = str.replace(/[\""]/g, '\\"');

//will return class=\"whatever-foo__input\" id=\"node-key\"
<span id="output"></span>

Ronnie Royston
sumber
2

Jika Anda merakit HTML di Java, Anda dapat menggunakan kelas utilitas yang bagus ini dari Apache commons-lang untuk melakukan semua pelarian dengan benar:

org.apache.commons.lang.StringEscapeUtils
Menyelamatkan dan menghapus String untuk Java, Java Script, HTML, XML, dan SQL.

saya ambil
sumber
Saya menggunakan org.apache.commons.lang3.StringEscapeUtils.escapeEcmaScript (teks) untuk membangun methodExpression di Jawa. Terima kasih.
Harun
1

Saya telah melakukan sampel menggunakan jQuery

var descr = 'test"inside"outside';
$(function(){
   $("#div1").append('<a href="#" onclick="DoEdit(descr);">Click Me</a>');       
});

function DoEdit(desc)
{
    alert ( desc );
}

Dan ini berfungsi di Internet Explorer dan Firefox.

rahul
sumber
5
Tentu saja, karena Anda tidak meletakkannya langsung di atribut. Untuk menggunakan metode Anda, saya harus membuat larik string JS, kemudian melakukan jumlah arbitrer $ ("# divxxx") ... tugas. Kurang optimal, tapi terima kasih atas sarannya.
Matt Dawdy
1

Anda dapat menyalin kedua fungsi tersebut (tercantum di bawah), dan menggunakannya untuk menghindari / menghapus semua kutipan dan karakter khusus. Anda tidak harus menggunakan jQuery atau perpustakaan lain untuk ini.

function escape(s) {
    return ('' + s)
        .replace(/\\/g, '\\\\')
        .replace(/\t/g, '\\t')
        .replace(/\n/g, '\\n')
        .replace(/\u00A0/g, '\\u00A0')
        .replace(/&/g, '\\x26')
        .replace(/'/g, '\\x27')
        .replace(/"/g, '\\x22')
        .replace(/</g, '\\x3C')
        .replace(/>/g, '\\x3E');
}

function unescape(s) {
    s = ('' + s)
       .replace(/\\x3E/g, '>')
       .replace(/\\x3C/g, '<')
       .replace(/\\x22/g, '"')
       .replace(/\\x27/g, "'")
       .replace(/\\x26/g, '&')
       .replace(/\\u00A0/g, '\u00A0')
       .replace(/\\n/g, '\n')
       .replace(/\\t/g, '\t');

    return s.replace(/\\\\/g, '\\');
}
omanosoft
sumber
1

Silakan temukan di kode di bawah ini yang lolos dari tanda kutip tunggal sebagai bagian dari string yang dimasukkan menggunakan ekspresi reguler. Ini memvalidasi jika string yang dimasukkan pengguna dipisahkan dengan koma dan pada saat yang sama bahkan lolos dari setiap kutipan tunggal yang dimasukkan sebagai bagian dari string.

Untuk menghindari tanda kutip tunggal, cukup masukkan garis miring diikuti dengan tanda kutip tunggal seperti: \ ' sebagai bagian dari string. Saya menggunakan validator jQuery untuk contoh ini, dan Anda dapat menggunakan sesuai kenyamanan Anda.

Contoh String yang Valid:

'Halo'

'Halo Dunia'

'Halo Dunia'

'Halo Dunia',' '

'Ini duniaku', 'Tidak dapat menikmati ini tanpa aku.', 'Selamat datang, Pengunjung'

HTML:

<tr>
    <td>
        <label class="control-label">
            String Field:
        </label>
        <div class="inner-addon right-addon">
            <input type="text" id="stringField"
                   name="stringField"
                   class="form-control"
                   autocomplete="off"
                   data-rule-required="true"
                   data-msg-required="Cannot be blank."
                   data-rule-commaSeparatedText="true"
                   data-msg-commaSeparatedText="Invalid comma separated value(s).">
        </div>
    </td>

JavaScript:

     /**
 *
 * @param {type} param1
 * @param {type} param2
 * @param {type} param3
 */
jQuery.validator.addMethod('commaSeparatedText', function(value, element) {

    if (value.length === 0) {
        return true;
    }
    var expression = new RegExp("^((')([^\'\\\\]*(?:\\\\.[^\'\\\\])*)[\\w\\s,\\.\\-_\\[\\]\\)\\(]+([^\'\\\\]*(?:\\\\.[^\'\\\\])*)('))(((,)|(,\\s))(')([^\'\\\\]*(?:\\\\.[^\'\\\\])*)[\\w\\s,\\.\\-_\\[\\]\\)\\(]+([^\'\\\\]*(?:\\\\.[^\'\\\\])*)('))*$");
    return expression.test(value);
}, 'Invalid comma separated string values.');
Dinesh Lomte
sumber
0

Melarikan diri dari ruang kosong juga. Bagi saya sepertinya Firefox mengasumsikan tiga argumen, bukan satu. &nbsp;adalah karakter ruang yang tidak putus-putus. Bahkan jika itu bukan masalah keseluruhan, itu mungkin masih merupakan ide yang bagus.

Hampster
sumber
0

Anda harus menghindari tanda kutip dengan garis miring terbalik ganda.

Ini gagal (dihasilkan oleh json_encode PHP ):

<script>
  var jsonString = '[{"key":"my \"value\" "}]';
  var parsedJson = JSON.parse(jsonString);
</script>

Ini bekerja:

<script>
  var jsonString = '[{"key":"my \\"value\\" "}]';
  var parsedJson = JSON.parse(jsonString);
</script>
Kerbau
sumber
0

Anda dapat menggunakan metode jQuery escape () dan unescape (). Seperti di bawah ini,

Gunakan escape(str);untuk keluar dari string dan pulih kembali menggunakan unescape(str_esc);.

Abhiram
sumber