Peretasan Google Translation API

Sebagai bagian dari Google Cloud-nya, Google menawarkan Google Translation API dengan struktur biaya berbasis penggunaan. Ada juga API tidak berdokumen yang dapat digunakan tanpa kunci , tetapi menolak untuk bekerja setelah beberapa permintaan. Saat menggunakan fungsi terjemahan situs web Google Chrome, terlihat bahwa halaman dapat diterjemahkan dengan kualitas yang sangat baik tanpa batasan yang nyata.


Rupanya model NMT tingkat lanjut sudah digunakan di sini. Namun API manakah yang digunakan Google Chrome secara internal untuk menerjemahkan konten, dan bisakah Anda juga mengakses API ini secara langsung - bahkan di sisi server? Untuk menganalisis lalu lintas jaringan, kami merekomendasikan alat seperti Wireshark atau Telerik Fiddler , yang juga dapat menganalisis lalu lintas terenkripsi. Namun Chrome bahkan memberikan permintaan yang dikirimkannya saat menerjemahkan halaman secara gratis: permintaan tersebut mudah dilihat melalui Chrome DevTools:

Jika Anda melakukan terjemahan, tangkap permintaan POST penting ke https://translate.googleapis.com melalui "Salin> Salin sebagai cURL (bash)" dan jalankan di alat seperti Postman , misalnya, Anda dapat mengirim permintaan lagi tanpa masalah:

Arti dari parameter URL juga sebagian besar sudah jelas.:

KunciContoh nilaiBerarti
anno3Mode anotasi (mempengaruhi format pengembalian)
kliente_libInformasi klien (bervariasi; melalui antarmuka web Google Translate nilainya adalah "webapp"; memengaruhi format balasan dan pembatasan laju)
formathtmlFormat string (penting untuk menerjemahkan tag HTML)
v1.0Nomor versi Google Terjemahan
kunciAIzaSyBOti4mM-6x9WDnZIjIeyEU21OpBXqWBgwKunci API (lihat di bawah)
logldvTE_20200210_00Versi protokol
sldeBahasa sumber
tlenBahasa target
spnmtModel ML
tc1tidak diketahui
sr1tidak diketahui
tk709408.812158Token (lihat di bawah)
Mode1tidak diketahui

Beberapa header permintaan juga disetel - tetapi ini sebagian besar dapat diabaikan. Setelah secara manual membatalkan pilihan semua header, termasuk yang berasal dari agen pengguna , masalah encoding ditemukan saat memasukkan karakter khusus (di sini saat menerjemahkan " Hello World "):

Jika Anda mengaktifkan kembali agen pengguna (yang umumnya tidak membahayakan), API mengirimkan karakter yang dikodekan UTF-8:

Apakah kita telah mencapai tujuan dan memiliki semua informasi untuk menggunakan API ini di luar Google Chrome? Namun, jika Anda mengubah string yang akan diterjemahkan (kolom data q dari permintaan POST) dari, misalnya, "Hello World" menjadi "Hello World ! ", Anda akan menerima pesan kesalahan.:

Sekarang kita melakukan terjemahan lain dari string yang telah dimodifikasi ini di dalam Google Chrome menggunakan fungsi terjemahan situs web dan menemukan bahwa, selain parameter q , parameter tk juga telah berubah (semua parameter lainnya tetap sama).:

Jelas, ini adalah token yang bergantung pada string, yang strukturnya tidak mudah dilihat. Saat Anda memulai terjemahan situs web, file berikut dimuat:

  • 1 file CSS: translateelement.css
  • 4 grafik: translate_24dp.png (2x), gen204 (2x)
  • 2 file JS: main_de.js , element_main.js

Kedua file JavaScript dikaburkan dan dikecilkan. Alat seperti JS Nice dan de4js sekarang membantu kami membuat file ini lebih mudah dibaca. Untuk men- debugnya secara langsung, kami merekomendasikan Ekstensi Chrome Requestly, yang menggabungkan file jarak jauh secara lokal dengan cepat:

Sekarang kita dapat men-debug kode ( CORS harus diaktifkan terlebih dahulu di server lokal). Bagian kode yang relevan untuk membuat token tampaknya tersembunyi di file element_main.js di bagian ini:

b7739bf50b2edcf636c43a8f8910def9

Di sini teks di-hash dengan bantuan beberapa pergeseran bit . Namun sayangnya kami masih kehilangan satu bagian dari teka-teki: Selain argumen a (yang merupakan teks yang akan diterjemahkan), argumen lain b diteruskan ke fungsi Bp () - semacam benih yang tampaknya berubah dari waktu ke waktu dan itu juga termasuk mengalir ke hashing. Tapi dari mana asalnya? Jika kita melompat ke pemanggilan fungsi Bp () , kita menemukan bagian kode berikut:

b7739bf50b2edcf636c43a8f8910def9

Fungsi Hq dideklarasikan sebelumnya sebagai berikut:

b7739bf50b2edcf636c43a8f8910def9

Deobfuscater meninggalkan beberapa sampah di sini; setelah kita mengganti String.fromCharCode('...') dengan string masing-masing, menghapus a() yang sudah usang dan menyatukan pemanggilan fungsi [c(), c()] , kita mendapatkan:

b7739bf50b2edcf636c43a8f8910def9

Atau bahkan lebih mudah:

b7739bf50b2edcf636c43a8f8910def9

Fungsi yq sebelumnya didefinisikan sebagai:

b7739bf50b2edcf636c43a8f8910def9

Jadi benihnya sepertinya ada di objek global google.translate._const._ctkk , yang tersedia saat runtime. Tapi di mana penempatannya? Setidaknya itu juga tersedia di awal di file JS lain yang dimuat sebelumnya main_de.js . Kami menambahkan yang berikut ini di awal:

b7739bf50b2edcf636c43a8f8910def9

Di konsol kami benar-benar mendapatkan benih saat ini:

Ini meninggalkan Google Chrome sendiri, yang tampaknya menyediakan benih, sebagai opsi terakhir. Untungnya, kode sumbernya (Chromium, termasuk komponen Terjemahan) adalah sumber terbuka dan oleh karena itu tersedia untuk umum. Kami menarik repositori secara lokal dan menemukan panggilan fungsi TranslateScript :: GetTranslateScriptURL di file translate_script.cc di folder components / translate / core / browser:

b7739bf50b2edcf636c43a8f8910def9

Variabel dengan URL ditentukan dengan pasti di file yang sama:

b7739bf50b2edcf636c43a8f8910def9

Jika sekarang kita memeriksa file element.js lebih dekat (setelah deobfuscation lebih lanjut), kita menemukan entri hard set c._ctkk - objek google.translate juga disetel sesuai dan pemuatan semua aset yang relevan (yang telah kita temukan sebelumnya) dipicu:

b7739bf50b2edcf636c43a8f8910def9

Sekarang kunci parameter tetap untuk dipertimbangkan (dengan nilai AIzaSyBOti4mM-6x9WDnZIjIeyEU21OpBXqWBgw). Tampaknya itu adalah kunci API browser umum (yang juga dapat ditemukan di beberapa hasil Google ). Sudah diatur di Chromium di file translate_url_util.cc di folder komponen / terjemahkan / inti / browser:

b7739bf50b2edcf636c43a8f8910def9

Kunci dibuat di google_apis / google_api_keys.cc dari nilai dummy:

b7739bf50b2edcf636c43a8f8910def9

Namun, pengujian menunjukkan bahwa panggilan API berfungsi dengan baik tanpa parameter kunci ini. Eksperimen dengan API sekarang mengembalikan kode status 200 pada panggilan yang berhasil. Jika batas tercapai, kode status 411 dikembalikan dengan pesan " Permintaan POST memerlukan header Content-length ". Oleh karena itu, disarankan untuk juga menyertakan header ini (yang secara otomatis diatur sebagai Header Sementara di Postman).

Format pengembalian dari string yang diterjemahkan tidak biasa jika ada beberapa kalimat dalam satu permintaan. Kalimat individual diapit oleh tag i- / b-HTML:

Selain itu, Google Chrome tidak mengirim seluruh HTML ke API, tetapi menyimpan nilai atribut seperti href dalam permintaan (dan sebagai gantinya menyetel indeks sehingga tag nantinya dapat ditetapkan di sisi klien):

Jika Anda mengubah nilai klien kunci POST dari te_lib (Google Chrome) di webapp ( situs web Google Terjemahan ), Anda mendapatkan string terjemahan terakhir:

Masalahnya adalah Anda lebih cenderung mengalami pembatasan kecepatan daripada melalui te_lib (sebagai perbandingan: dengan webapp ini dicapai setelah 40.000 karakter, dengan te_lib tidak ada pembatasan kecepatan). Jadi kita perlu melihat lebih dekat bagaimana Chrome mengurai hasilnya. Kami akan menemukannya di sini di element_main.js:

b7739bf50b2edcf636c43a8f8910def9

Jika Anda mengirim seluruh kode HTML ke API, atribut akan tertinggal dalam respons yang diterjemahkan. Oleh karena itu, kami tidak harus meniru seluruh perilaku penguraian, tetapi hanya mengekstrak string terjemahan terakhir dari respons. Untuk melakukannya, kami membuat pengurai tag HTML kecil yang membuang tag <i> terluar termasuk kontennya dan menghapus tag <b> terluar. Dengan pengetahuan ini (setelah menginstal dependensi dengan composer require fzaninotto / faker vielhuber / stringhelper ) sekarang kita dapat membangun versi sisi server dari API terjemahan:

b7739bf50b2edcf636c43a8f8910def9

Di bawah ini adalah hasil pengujian awal yang dilakukan pada lima sistem berbeda dengan bandwidth dan alamat IP berbeda:

KarakterKarakter per permintaanDurasiTingkat kesalahanBiaya melalui API resmi
13.064.662~25003:36:170%237,78 €
24.530.510~25011:09: 13h0%446,46 €
49.060.211~25020:39: 10j0%892,90 €
99.074.487~100061: 24: 37h0%1803,16 €
99.072.896~100062: 22: 20h0%1803,13 €
Σ284.802.766~ Ø550Σ159: 11: 37h0%€5183,41

Catatan: Entri blog ini termasuk semua skrip ditulis untuk tujuan pengujian saja. Jangan menggunakan script untuk penggunaan produktif, bukan bekerja dengan resmi API Google Terjemahan .

Kembali