Adalah baik ketika ada seseorang yang lebih berpengalaman dalam tim yang akan menunjukkan apa dan bagaimana melakukan, apa yang menyapu dan menyudutkan apa, dan di mana untuk mengunduh gambar sepeda terbaik untuk tahun 2007 di DVD. Kisah ini adalah tentang bagaimana harapan itu dinyatakan sah, apa hasilnya, dan bagaimana krisis itu diatasi.
Ini terjadi pada saat, setelah, menurut saya, pengalaman yang biasa-biasa saja dalam pengembangan, saya sedang mencari tempat di mana Anda dapat berevolusi (atau bermutasi) dari non-junior menjadi bahkan junior yang percaya diri. Dalam cara-cara misterius Tuhan tempat seperti itu ditemukan, sebuah proyek melekat pada tempat itu, dan pemrogram "sekolah tua", yang menulis lebih banyak daripada anak perempuan daripada kariernya dalam sistem. “Hebat! Proyek, dan oleh karena itu ada uang untuk RFP, mentornya terpasang, kita hidup! ” Saya berpikir, tetapi kemudian, seperti dalam deskripsi horor yang khas, para pahlawan dalam kegelapan menghadapi horor yang mengerikan ...
Hal pertama yang pertama:
1. Ukuran penting
Kami memulai pengembangan pada mesin php yang dulu eksklusif, yang digunakan untuk menyimpan data (di sini Anda mungkin berpikir MySQL \ PostgreSQL \ SQLite \ MongoDB \ Sesuatu-lain-tetapi-tentu-dengan-akhiran DB-jika tidak- guys-tidak mengerti, tetapi mereka tidak menebak) api-gateway.
“Haha, menggunakan php, apakah kamu memasang api-gateway lain untuk itu, dan menyimpan data di dalamnya? Bukankah lebih mudah untuk bekerja dengan api langsung dari js-code? Atau gunakan DBMS + PHP? " - Tanyakan pembaca berpengalaman. Dan dia akan benar. Tetapi pada saat itu, saya, yang belum melihat spesies itu, tidak berpikir begitu, yah, siapa tahu, orang-orang keren mungkin melakukan itu, dan para programmer "jadul" tahu lebih baik.
Seperti yang saya jelaskan lebih lanjut:
- Gateway = keamanan, tidak ada yang akan masuk dan keluar begitu saja
- Gateway = penyimpanan data aman, Anda tidak bisa masuk ke dalamnya, + backup
- Gateway = kecepatan, bekerja dengan cepat dan tanpa kegagalan, teruji oleh waktu
- Sudut pandang otoritatif dari programer "old-school" adalah bahwa php Anda penuh dengan lubang, aplikasi web apa pun diretas secara default, jadi tidak ada yang menyimpan data di sebelahnya
Fitur khas dari gerbang api adalah bahwa data json ditransmisikan dalam permintaan dapatkan. Ya, ya, benda-benda json yang sangat indah itu, dikenai url-encoding, dan dimasukkan ke dalam string kueri. Dan semuanya akan baik-baik saja, ketika tiba-tiba suatu hari ... lamanya permintaan diterima tidak lagi cukup. Bodoh, json yang dikodekan-url, kanalya, tidak cocok di sana! Programmer "old-school", menggaruk kepalanya, bertanya:
“Apa yang akan kita lakukan? Json kami telah berkembang, tetapi kami belum menyadarinya ... "
"Yah, uh, mungkin kalau begitu kita akan mempostingnya di pos?" Saya menyarankan, jadi sepertinya lebih benar.
"Oke, lulus untuk mengirim."
Itu atas nomor satu.
2. Manajemen waktu dan cadangan
Untuk memasukkan fungsi baru ke dalam proyek, itu perlu untuk diterapkan
permintaan CRUD yang sesuai di gateway, itulah yang sebenarnya dilakukan oleh kawan “sekolah lama” kami. Masalahnya adalah dia melakukan ini setiap 3 hari sekali, membagikan "Selesai, periksa." Cek pada waktu menunjukkan bahwa tidak semuanya bekerja, misalnya, mendapatkan daftar tidak apa-apa, menambahkan item baru tidak ok. Butuh beberapa waktu untuk memperbaiki dan memperbaiki, setelah itu dimungkinkan untuk melepaskan fungsionalitas dalam akses massal. Proposal untuk melakukan implementasi kueri di gateway sendiri, karena setidaknya lebih cepat, ditolak, karena "sulit di sana, Anda tidak akan menemukannya." Hasil dari pendekatan ini adalah penutupan pekerjaan "pada diriku sendiri". Jika, misalnya, perlu untuk memperbaiki sesuatu secara massal dalam database, maka, memilih antara menunggu 3 hari dan pelaksanaan koreksi sendiri melalui kueri - saya memilih opsi ke-2. Pelanggan tidak suka menunggu, pengantar baru terbang stabil. Salah satu dari pengantar tersebut, yaitu pembubuhan tanda untuk pengguna tanda, dipercayakan kepada saya untuk diimplementasikan, ada satu jam untuk segala sesuatu tentang segala sesuatu, pihak berwenang sedang menunggu laporan yang indah. Di sini menanti kita atas nomor dua-s.
Faktanya adalah bahwa format data json yang ditransmisikan dalam permintaan hanya menyiratkan beberapa bidang yang diperlukan, yang lainnya sewenang-wenang, struktur yang jelas dan final tidak ada. Misalnya, untuk menambahkan pengguna, saya memberikan json formulir:
POST /api/users { "email":"ivanov@mail.ru", "password":"myEmailIsVeryBig", "name_last":"", "name_first":"", "name_middle":"", "birth":"01.01.1961", // , - "living_at":"., .3 .4 .24", "phone_num":"+70000000000" }
Bagian opsional yang dikirim dalam permintaan tambah / perbarui disimpan dan diberikan secara keseluruhan (saya akan memberi tahu tentang bagaimana ini diterapkan di bawah). Intinya adalah, waktu tidak berhenti, akan perlu untuk menyelesaikan masalah - untuk memperbarui pengguna, letakkan label mereka. Tapi jangan mendorong seluruh struktur setiap saat? Harus memeriksa! Saya mengujinya sendiri - saya hanya mengirim satu bidang dalam permintaan pembaruan, memeriksa, bidang muncul, sisa data ada di tempat. Intinya kecil - loop dan perbarui sisanya.
Script itu mengembang pelan, menerima dan mengirimkan data, dan semuanya tampak berjalan dengan baik ... ketika tiba-tiba - panggilan. "Kami tidak melihat nama pengguna di sistem!" - melaporkan dari ujung kawat itu. “Ayo! Ya berhasil! ” - Hawa dingin yang tidak menyenangkan berlari melintasi punggungku. Penyelidikan lebih lanjut menunjukkan bahwa memang, nama "" ditunjukkan dalam nama, meskipun semua data lain ada di tempat. Apa yang harus dilakukan dalam situasi seperti itu? Sebarkan cadangan!
Programmer "Kamerad" old-school ", akan ada masalah! Perlu cadangan! Kapan relevan terbaru dilakukan? " - Saya bertanya.
"Uhh ... Aku akan melihat sekarang .... Tidak, tidak ada bakapa. "
Situasi diselamatkan oleh fakta bahwa beberapa jam sebelumnya saya menyelesaikan dan menguji modul dengan laporan, saya memiliki kotak csv dengan semua data yang diperlukan, pesanan dikembalikan dalam waktu satu jam lagi.
Kurangnya dokumentasi yang dapat dipahami, deskripsi algoritma operasi, pemeriksaan validitas input, dan yang paling penting - backup database - atas nomor dua-s.
Sejak itu, cadangan mulai dihapus setiap hari.
3. Sangat mencolok
Shaky, tetapi pekerjaan itu bergerak, masalah terselesaikan, beberapa lebih cepat, beberapa lebih lambat, ketika tiba-tiba ... pelanggan menyadari bahwa sistem tidak dipahami oleh server orang lain, dan untuk sikap seperti itu terhadap PD dan mengatur kegiatan ZI di ISPD mereka tidak akan membelai kepala. Anda perlu mentransfer server ke diri Anda sendiri.
Mengapa sistem tidak ditransfer pada awalnya? Kepemimpinan memiliki satu gairah - sentralisasi. Manajemen memimpikan sistem yang akan melakukan segalanya! Apakah Anda perlu melampirkan anak ke sekolah? Anda masuk ke sistem, di kantor khusus, di sana Anda mengirimkan aplikasi. Anda perlu, katakanlah, memesan pizza - Anda masuk ke sistem, ke kantor khusus lain, melamar pizza. Mungkin Anda ingin berkomunikasi dengan wanita cantik? Melayani Anda adalah kabinet khusus ketiga - Anda juga mengirimkan aplikasi di sana, dan seterusnya tanpa batas.
Keuntungan - satu login dan kata sandi untuk semuanya, data disimpan dengan aman dan aman di gateway. Bahkan ada backup. Dan, ingatlah, tidak ada yang akan mengambil sistem ini dari kami! Dan bahkan jika itu menghilangkannya - selanjutnya apa? Semua sama, mereka tidak akan mengerti sistem perlindungan terhadap programer "old-school" - semuanya rumit di sana.
VDS dengan sistem diturunkan, dikaitkan dengan pelanggan, mereka menyebarkannya, semua orang menari dan bernyanyi, cantik!
Dan kemudian gelombang keingintahuan dan kecurigaan menutupi saya.
Jika aplikasi web kita penuh dengan lubang, lalu di mana datanya? Apakah Anda benar-benar tetap di server lain? Dan jika mereka memutuskan untuk menutup sistem dari luar, maka semuanya akan runtuh?
Pemeriksaan sederhana menunjukkan bahwa data, serta prosesor gateway itu sendiri, berada di server yang sama. Dan, tidak, mereka tidak ditransfer ke sana karena transfer server, mereka selalu ada di sana.
Sekarang saya memiliki pengembangan "sekolah tua" yang sangat rahasia, yang saya mulai selidiki. Tentu saja, rekayasa balik keren dalam gaya artikel dari majalah Hacker, dengan ollydbg, offset, dan hal-hal keren lainnya tidak berhasil, jadi saya membagikan apa yang saya miliki.
Pengembangan itu sendiri diimplementasikan dalam python, hanya ada file .pyc yang dapat dengan mudah didekompilasi kembali menjadi kode yang dapat dibaca. Terus terang, butuh banyak waktu, sebanyak 25 menit, untuk mencari tahu cara kerjanya.
Jadi, sistem kompleks yang dikembangkan oleh pemrogram "sekolah tua", yang hanya bisa dimengerti oleh beberapa orang, terdiri dari:
- Script diproses oleh Apache, yang sebenarnya menerima permintaan. Apa yang dilakukan skrip ini? Membuka koneksi ke port localhost tertentu dan melewati permintaan di sana dengan semua datanya. Itu saja. Minat lebih lanjut.
- Bagian server yang memproses permintaan dari skrip. Logika tindakannya cukup menarik. Pertama, tidak ada manipulasi data dalam kode, dan tidak ada permintaan dalam database, sebagai gantinya, fungsi database dalam PL \ SQL dipanggil. Semua logika, cek, dan sebagainya, semuanya diletakkan dalam fungsi basis data. 50% dari skrip adalah kamus yang berisi nama permintaan, fungsi yang terkait dengannya, dan nama-nama parameter fungsi yang harus sesuai dengan data yang diteruskan di baris dapatkan-permintaan. Data JSON, jika perlu, diteruskan sebagai parameter terpisah. Fitur organisasi bagian server adalah koneksi cadangan selama otentikasi pengguna. Jika login dan kata sandi ditemukan dalam database, ID sesi dibuat, dan contoh koneksi terbuka dilipat ke dalam kamus (dan terbunuh oleh batas waktu 10 menit sehingga tidak akan terbunuh - ada metode khusus untuk memperpanjang umur sesi), kuncinya adalah ID sesi, yang langsung di dalam database tidak disimpan. Bagaimana tepatnya ID sesi dikaitkan dengan data pengguna? Lagi pula, apakah ada permintaan untuk data di mana ID pengguna tidak dikirim? Ini berfungsi, yang berarti ada sesuatu yang salah di sini.
Perkembangan yang sangat sulit diberikan kepada kesadaran dengan kesulitan dan tidak terburu-buru untuk mengungkapkan rahasia lama yang telah hilang dari para penguasa masa lalu.
Luar biasa (Pergi ke> Definisi, terima kasih kepada PhpStorm untuk memahami PL \ SQL), tidak dapat dipahami oleh pikiran orang awam yang menderita Pengetahuan Sejati tentang Peradaban yang Hilang dari Programmer Sekolah Lama tetap diperoleh. Secara umum, ketika terhubung, tabel sementara dihasilkan dalam fungsi verifikasi data otentikasi, di mana id pengguna disimpan.
Ini baru permulaan, daftar indikatif dari kerentanan serius yang ditemukan:
- DDoS menggunakan otentikasi massal (koneksi dicadangkan, dan, oleh karena itu, bertumpu pada batas koneksi DBMS, yang, mengingat kemungkinan memperpanjang waktu hidup sesi, memungkinkan untuk sepenuhnya mengisi memori dengan koneksi, dan pekerjaan pengguna baru dalam sistem tidak mungkin dilakukan);
- kurangnya perlindungan terhadap brute force (jumlah upaya login gagal tidak terdeteksi, tidak disimpan, tidak dicentang;
- kurangnya kontrol atas tindakan dengan entitas (misalnya, daftar dokumen yang diminta oleh pengguna dikeluarkan dengan mempertimbangkan organisasi yang dilampirkan pengguna, dan jika Anda tahu ID dokumen, Anda dapat berhasil menyelesaikan permintaan untuk memperbarui / menghapus dokumen, dan daftar pengguna baik bahkan tanpa kata sandi, yang, secara kebetulan, disimpan dalam database secara jelas, tanpa hashing, dapat diterima oleh siapa saja).
Dan masalah serius lainnya bukanlah skema penyimpanan data yang diformalkan. Seperti yang dijanjikan sebelumnya, saya berbicara tentang menyimpan "semua bidang" dari JSON. Tidak, mereka tidak disimpan sebagai baris di tabel. Mereka dibagi menjadi pasangan nilai kunci dan disimpan dalam tabel terpisah. Misalnya, untuk pengguna ada 2 tabel - pengguna, dan users_data (kunci string, nilai string) - di mana data sebenarnya disimpan. Hasil dari pendekatan ini adalah peningkatan waktu dengan sampel kompleks dari database.
Sebenarnya ini sudah cukup untuk membuat dan mengimplementasikan keputusan untuk mentransfer sistem ke api baru, dapat dimengerti, didokumentasikan, dan didukung.
Akhlak
Mungkin sistem ini adalah "Legacy", dan programmer "old-school" yang menciptakannya adalah inti dari Legacy.
Namun demikian, kesimpulannya adalah sebagai berikut:
- Jika Anda diberi tahu "itu sulit, Anda tidak akan mengerti" - itu berarti ada bagian atas yang lengkap
- Jika mereka dihancurkan oleh otoritas, maka ada sesuatu yang najis
- Percaya, tetapi verifikasi - keamanan bukan negara, keamanan adalah proses yang berkelanjutan, oleh karena itu lebih baik untuk memverifikasi kualitas yang dinyatakan kenyataan daripada untuk mengetahui nanti bahwa semua pengguna tiba-tiba menjadi "Ivanov Ivanov Ivanitch", tetapi tidak ada bacaps.