💡 Contoh lengkap yang berfungsi tersedia di GitHub:
load-untrusted-documents-safely-python

Cara Lama Sangat Menyakitkan

Anda menulis tiga baris untuk menghasilkan thumbnail dari dokumen yang diunggah. Baris‑baris itu terlihat seperti ini, dan tampak baik:

with signature.Signature(upload_path) as sign:
    save_page_preview(sign, thumbnail_path)

Apa yang dilakukan baris‑baris itu, sebelum GroupDocs.Signature 26.9, adalah mengambil setiap alamat yang ditunjuk dokumen. File Word dapat menyimpan gambar yang tidak terkandung di dalamnya – file menyimpan URL, dan apa pun yang membukanya akan mengunduh URL tersebut. Pada desktop ini adalah fitur. Pada server yang menerima unggahan, ini berarti orang yang mengirimkan file menentukan alamat mana yang diminta infrastruktur Anda.

Serangan ini memiliki nama, server-side request forgery (SSRF), dan tiga bentuk yang layak disebutkan. Alamat internal yang tidak dapat dijangkau dari internet dapat dijangkau dari server Anda, sehingga dokumen yang dirancang dapat membuat layanan Anda mengambil http://169.254.169.254/ atau endpoint admin di localhost. Jalur UNC dapat memaksa host Windows melakukan otentikasi keluar, menyerahkan kredensial ke server yang dikendalikan penyerang. Dan tautan ke host yang tidak pernah menjawab menahan thread pemuatan hingga waktu habis, yang merupakan cara murah untuk menghabiskan pool pekerja dengan dokumen yang tampak tidak berbahaya.

Tidak ada yang merupakan bug dalam pustaka dokumen. Mengikuti tautan adalah apa yang diminta format. Bagian yang tidak nyaman adalah bahwa mematuhi itu adalah default, dalam kode tidak ada yang menandainya dalam tinjauan.

Ada Cara yang Lebih Baik

Pemuat dokumen yang aman adalah perilaku GroupDocs.Signature untuk Python yang menolak melakukan permintaan tersebut. Mulai versi 26.9, LoadOptions.skip_external_resources defaultnya True, sehingga tiga baris yang sama sekarang tidak mengambil apa‑apa dan menampilkan placeholder di tempat gambar yang ditautkan seharusnya.

Perubahan ini adalah default bukan fitur baru – properti tersebut sudah ada. Apa yang diubah pada versi 26.9 adalah arah ketika kode Anda tidak menyebut apa‑apa, yang merupakan satu‑satunya pengaturan yang biasanya digunakan oleh kebanyakan layanan.

Cara Baru: Tiga Mode Muat

Langkah 1 - Pertahankan default untuk apa pun yang tidak terpercaya

Tidak ada LoadOptions sama sekali:

with signature.Signature(source_path) as sign:
    return save_page_preview(sign, preview_path)

Tidak ada yang diminta. Pratinjau lebih kecil daripada seharusnya, dan perbedaan ukuran itu merupakan bukti paling praktis yang tersedia bahwa tidak ada permintaan yang keluar dari mesin.

Langkah 2 - Daftarkan putih host yang memang Anda miliki

Banyak dokumen menautkan ke tempat yang sah: CDN perusahaan, server gambar internal, toko templat. Izinkan itu dan tidak ada yang lain:

load_options = LoadOptions()
load_options.whitelisted_resources = [trusted_address]

with signature.Signature(source_path, load_options) as sign:
    return save_page_preview(sign, preview_path)

Aturan pencocokan memerlukan perhatian. Itu adalah tes substring yang tidak sensitif huruf besar/kecil terhadap alamat sumber daya, yang membuat fragmen pendek berbahaya: github cocok dengan github.attacker.example/payload.png sama mudahnya dengan host yang Anda maksud. Gunakan skema, host, dan jalur – contoh ini mendaftarkan putih raw.githubusercontent.com/groupdocs-signature/.

Langkah 3 - Izinkan semuanya, secara sengaja

Perilaku sebelum versi 26.9, masih tersedia:

load_options = LoadOptions()
load_options.skip_external_resources = False

Masuk akal untuk dokumen yang dihasilkan aplikasi Anda sendiri. Satu jebakan: properti usang load_external_resources memiliki polaritas berlawanan, sehingga skip_external_resources = False menggantikan load_external_resources = True. Menyalin nilai dari properti lama akan membalikkan postur keamanan Anda tanpa ada kesalahan yang memberi tahu.

Perbandingan: Sebelum vs. Sesudah

Dokumen yang sama, jalur kode yang sama, tiga kebijakan muat. Ini adalah ukuran file yang disimpan di folder Result/ contoh, sehingga dapat diperiksa alih‑alih dipercaya:

Mode muat Ukuran pratinjau Permintaan keluar
default (26.9 dan setelahnya) 16,435 bytes tidak ada
host yang didaftarkan putih 51,738 bytes satu, ke alamat yang diizinkan
semua sumber daya (default sebelum 26.9) 51,738 bytes satu per sumber daya yang ditautkan

Gambar yang ditautkan berukuran 35,303 byte dari perbedaan itu. Saya tidak mempercayai pengaturan tersebut sampai dua angka itu dibandingkan berdampingan, dan saya menyarankan hal yang sama: membaca kembali properti memberi tahu Anda apa yang Anda konfigurasikan, bukan apa yang dilakukan proses.

Apa yang Dianggap sebagai Sumber Daya Eksternal?

Lebih sempit daripada yang diperkirakan orang, itulah mengapa peningkatan biasanya tidak menimbulkan masalah. Gambar yang ditautkan bukan yang tersemat, bidang INCLUDEPICTURE, gambar yang ditautkan dalam presentasi dan spreadsheet, serta gambar dan lembar gaya yang direferensikan oleh SVG. Konten tersemat tidak diubah, karena sudah berada di dalam file dan tidak diperlukan permintaan untuk merendernya.

Perbedaan itu adalah seluruh batas keamanan. Dokumen hanya dapat membuat server Anda menghubungi jika ia menyimpan alamat alih‑alih byte, jadi pertanyaannya untuk setiap korpus hanyalah berapa banyak file yang menautkan bukan yang tersemat. Jika tidak ada, default baru tidak menambah beban dan Anda dapat memperbarui tanpa membaca lebih lanjut.

Contoh Dunia Nyata: Unggahan yang Ditandatangani

Kasus di mana perubahan default ini diperlukan. Sebuah dokumen datang dari luar, dan Anda perlu menambahkan tanda tangan padanya:

with signature.Signature(source_path) as sign:
    options = QrCodeSignOptions("Approved by GroupDocs.Signature")
    options.encode_type = QrCodeTypes.QR
    options.left = 400
    options.top = 50
    options.width = 120
    options.height = 120

    result = sign.sign(output_path, options)

Tidak ada sumber daya eksternal yang diminta saat dokumen dimuat, ditandatangani, atau disimpan. Output yang ditandatangani mempertahankan tautannya, sehingga pengguna yang membukanya di Word nanti masih melihat gambar yang terresolusi di mesin mereka sendiri. Melewatkan adalah kebijakan sisi server, bukan penyuntingan dokumen – yang justru membuatnya aman diterapkan pada file yang Anda tangani atas nama orang lain.

Apa Lagi yang Berubah Saat Anda Memperbarui?

Untuk kebanyakan layanan, tidak ada yang terlihat, yang layak disebutkan secara jelas karena default keamanan yang mengubah perilaku di mana‑mana tidak akan lolos tinjauan pembaruan. Penandatanganan, verifikasi, dan pencarian tidak terpengaruh. Pengecualian adalah pratinjau yang dulu menampilkan gambar yang ditautkan dan kini menampilkan placeholder – perubahan yang menjalankan tugasnya. Daftarkan putih host jika itu milik Anda, terima jika tidak.

Perlu disebutkan secara terpisah: SVG. SVG dapat merujuk gambar dan lembar gaya melalui URL, referensi tersebut adalah sumber daya eksternal menurut aturan yang sama, dan SVG merupakan format unggahan umum serta vektor SSRF yang umum. Layanan yang menerima avatar SVG dan merendernya di sisi server adalah contoh sistem yang dilindungi oleh perubahan ini.

Satu Detail Python: Bagaimana Pratinjau Ditulis

PreviewOptions menerima dua pabrik stream alih‑alih path, dan callable Python biasa sudah cukup:

def create_page_stream(page_data):
    return open(preview_path, "wb")

def release_page_stream(page_data, page_stream):
    page_stream.close()

preview_options = PreviewOptions(create_page_stream, release_page_stream)
preview_options.preview_format = PreviewOptions.PreviewFormats.PNG
sign.generate_preview(preview_options)

Satu membuat stream per halaman, yang lain melepaskannya. Dokumen contoh memiliki satu halaman, sehingga satu file ditulis; untuk input multi‑halaman, sertakan nomor halaman dalam nama atau setiap halaman akan menimpa yang sebelumnya.

Kesimpulan

Default telah diubah sehingga perilaku berisiko memerlukan keputusan eksplisit dan yang aman tidak memerlukan apa‑apa. Pertahankan default untuk input yang tidak terpercaya, daftarkan putih secara ketat di mana host Anda terlibat, dan ingat bahwa penandatanganan tidak pernah memerlukan jaringan sama sekali.

Jika Anda menginginkan pemeriksaan yang lebih kuat daripada ukuran file, arahkan dokumen uji ke host yang Anda kontrol dan perhatikan log aksesnya saat pratinjau berjalan. Ukuran memberi tahu apakah byte tiba; log akses memberi tahu apakah ada permintaan sama sekali, dan keduanya berbeda tepat pada kasus yang penting – host yang didaftarkan putih namun tidak dapat dijangkau terlihat sama dengan yang diblokir hanya dari output.

Menjalankan contoh pada salah satu dokumen Anda sendiri memakan waktu satu menit dan memberi tahu Anda, dalam tiga ukuran file, tepat apa yang layanan Anda ambil atas nama pengirim file.

Sumber Daya Tambahan