Kondisi ras dalam aplikasi web

TL; DR Artikel ini menjelaskan tentang trik kondisi lomba yang tidak populer yang tidak biasa digunakan dalam serangan jenis ini. Berdasarkan hasil penelitian kami, kami membuat kerangka kerja kami sendiri untuk serangan racepwn.

Vasya ingin mentransfer 100 dolar yang dia miliki di akunnya, Petya. Dia pergi ke tab transfer, mengarahkan nama panggilan Petin ke dalam bidang dengan jumlah dana yang perlu ditransfer - angka 100. Selanjutnya, klik pada tombol transfer. Data kepada siapa dan berapa banyak yang dikirim ke aplikasi web. Apa yang bisa terjadi di dalam? Apa yang perlu dilakukan oleh programmer agar semuanya berfungsi dengan benar?

  • Anda perlu memastikan bahwa jumlahnya tersedia untuk Vasya untuk transfer.

Penting untuk mendapatkan nilai saldo pengguna saat ini, jika kurang dari jumlah yang ingin ditransfer, beri tahu dia tentang hal itu. Mengingat fakta bahwa situs kami tidak memberikan pinjaman dan tidak boleh masuk ke saldo minus.

  • Kurangi jumlah yang akan ditransfer dari saldo pengguna

Penting untuk menuliskan saldo pengguna saat ini dengan pengurangan jumlah yang ditransfer. Itu 100, menjadi 100-100 = 0.

  • Tambahkan ke saldo pengguna, Petya, jumlah yang ditransfer.

Petya, sebaliknya, adalah 0, menjadi 0 + 100 = 100.

  • Tampilkan pesan kepada pengguna bahwa ia berhasil!

Saat menulis program, seseorang menggunakan algoritma paling sederhana, yang ia gabungkan menjadi satu plot, yang akan menjadi skrip program. Dalam kasus kami, tugas programmer adalah menulis logika transfer uang (poin, kredit) dari satu orang ke orang lain dalam aplikasi web. Dipandu oleh logika, Anda dapat membuat algoritma yang terdiri dari beberapa pemeriksaan. Bayangkan kita baru saja menghapus semua yang tidak perlu dan menyusun kodesemu.

 (. >= _)  .=.-_ .=.+_ ()  () 

Tetapi semuanya akan baik-baik saja jika semuanya terjadi secara bergantian. Tetapi sebuah situs dapat melayani banyak pengguna secara bersamaan, dan ini tidak terjadi dalam satu utas, karena aplikasi web modern menggunakan multiprosesing dan multithreading untuk pemrosesan data paralel. Dengan munculnya multithreading, program memiliki kerentanan arsitektur lucu - kondisi ras (atau kondisi ras).

Sekarang bayangkan algoritma kami bekerja secara bersamaan 3 kali.

Vasya masih memiliki 100 poin pada keseimbangannya, hanya saja entah bagaimana ia beralih ke aplikasi web dalam tiga utas pada saat yang sama (dengan jumlah waktu minimum di antara permintaan). Ketiga aliran memeriksa apakah pengguna adalah Petya, dan memeriksa apakah Vasya memiliki saldo yang cukup untuk transfer. Pada saat itu ketika algoritma memeriksa saldo, itu masih sama dengan 100. Setelah verifikasi selesai, 100 dikurangkan dari saldo saat ini 3 kali dan Pete ditambahkan.

Apa yang kita miliki Vasya memiliki saldo negatif di akunnya (100 - 300 = -200 poin). Sementara itu, Petya memiliki 300 poin, meskipun pada kenyataannya, itu harus 100. Ini adalah contoh khas dari eksploitasi kondisi ras. Ini sebanding dengan kenyataan bahwa beberapa orang lulus sekaligus. Di bawah ini adalah screenshot dari situasi ini dari 4lemon



Kondisi balapan dapat di aplikasi multi-utas, serta di basis data di mana mereka bekerja. Tidak harus dalam aplikasi web, misalnya, ini adalah kriteria umum untuk peningkatan hak istimewa dalam sistem operasi. Meskipun aplikasi web memiliki karakteristik sendiri untuk operasi yang sukses, yang ingin saya bicarakan.

Operasi Kondisi Balap Khas


Seorang hacker memasuki hookah, pencarian dan bar, dan kepadanya - Anda memiliki kondisi balapan! Omar Ganiev

Dalam kebanyakan kasus, perangkat lunak multithreaded digunakan sebagai klien untuk memeriksa / mengoperasikan kondisi balapan. Misalnya, Burp Suite dan alat Penyusupnya. Mereka menempatkan satu permintaan HTTP untuk pengulangan, menginstal banyak aliran dan menghidupkan banjir. Seperti misalnya di artikel ini . Atau yang ini . Ini adalah cara yang cukup berhasil, jika server memungkinkan penggunaan beberapa utas ke sumber dayanya, dan seperti yang mereka katakan dalam artikel di atas, jika tidak berhasil, coba lagi. Tetapi kenyataannya adalah bahwa dalam beberapa situasi, ini mungkin tidak efektif. Terutama jika Anda ingat bagaimana aplikasi tersebut mengakses server.

Apa yang ada di server


Setiap utas membuat koneksi TCP, mengirim data, menunggu respons, menutup koneksi, membuka lagi, mengirim data, dan sebagainya. Pada pandangan pertama, semua data dikirim secara bersamaan, tetapi permintaan HTTP itu sendiri mungkin tidak tiba secara serentak dan tidak konsisten karena sifat lapisan transport, kebutuhan untuk membuat koneksi aman (HTTPS) dan menyelesaikan DNS (tidak dalam kasus sendawa) dan banyak lapisan abstraksi yang meneruskan data sebelum dikirim ke perangkat jaringan. Ketika datang ke milidetik, ini bisa memainkan peran kunci.

Pemipaan HTTP


Anda dapat mengingat HTTP-Pipelining, di mana Anda dapat mengirim data menggunakan soket tunggal. Anda dapat melihat sendiri bagaimana cara kerjanya menggunakan utilitas netcat (Anda memiliki GNU / Linux, kan?).

Bahkan, Anda perlu menggunakan linux karena berbagai alasan, karena ada tumpukan TCP / IP yang lebih modern, yang didukung oleh kernel sistem operasi. Server kemungkinan besar juga ada di sana.

Misalnya, jalankan nc google.com 80 dan masukkan baris di sana

 GET / HTTP/1.1 Host: google.com GET / HTTP/1.1 Host: google.com GET / HTTP/1.1 Host: google.com 

Dengan demikian, dalam satu koneksi, tiga permintaan HTTP akan dikirim, dan Anda akan menerima tiga respons HTTP. Fitur ini dapat digunakan untuk meminimalkan waktu antar permintaan.

Apa yang ada di server


Server web akan menerima permintaan secara berurutan (kata kunci), dan memproses respons sesuai urutan prioritas. Fitur ini dapat digunakan untuk menyerang dalam beberapa langkah (bila perlu secara berurutan melakukan dua tindakan dalam jumlah waktu minimum) atau, misalnya, untuk memperlambat server pada permintaan pertama untuk meningkatkan keberhasilan serangan.
Trik - Anda dapat mencegah server memproses permintaan Anda dengan memuat DBMS-nya, terutama jika INSERT / UPDATE digunakan. Permintaan yang lebih berat dapat "memperlambat" muatan Anda, dengan demikian, kemungkinan besar Anda akan memenangkan perlombaan ini.

Membagi permintaan HTTP menjadi dua bagian


Pertama, ingat bagaimana permintaan HTTP dihasilkan. Seperti yang Anda ketahui, baris pertama adalah versi metode, jalur dan protokol:

GET / HTTP/1.1

Berikutnya adalah tajuk sebelum jeda baris:

Host: google.com
Cookie: a=1

Tetapi bagaimana server web tahu bahwa permintaan HTTP telah berakhir?

Mari kita lihat sebuah contoh, masukkan nc google.com 80 , dan di sana

GET / HTTP/1.1
Host: google.com
GET / HTTP/1.1
Host: google.com
, setelah Anda menekan ENTER, tidak ada yang terjadi. Klik lagi - Anda akan melihat jawabannya.

Yaitu, agar server web menerima permintaan HTTP, dua umpan baris diperlukan. Kueri yang valid terlihat seperti ini:

GET / HTTP/1.1\r\nHost: google.com\r\n\r\n

Jika ini adalah metode POST (jangan lupa tentang Panjang Konten), maka permintaan HTTP yang benar adalah seperti ini:

POST / HTTP/1.1
Host: google.com
Content-Length: 3

a=1


atau

POST / HTTP/1.1\r\nHost: google.com\r\nContent-Length: 3\r\n\r\na=1

Coba kirim permintaan serupa dari baris perintah:

 echo -ne "GET / HTTP/1.1\r\nHost: google.com\r\n\r\n" | nc google.com 80 

Akibatnya, Anda akan menerima respons, karena permintaan HTTP kami selesai. Tetapi jika Anda menghapus karakter terakhir, Anda tidak akan mendapatkan jawaban.

Faktanya, banyak server web hanya perlu menggunakan \ n sebagai transfer, jadi penting untuk tidak menukar \ r dan \ n, jika tidak, trik lebih lanjut mungkin tidak berfungsi.

Apa yang diberikannya? Anda dapat secara bersamaan membuka banyak koneksi ke sumber daya, mengirim 99% dari permintaan HTTP Anda dan membiarkan byte terakhir tidak terkirim. Server akan menunggu sampai Anda mencapai umpan baris terakhir. Setelah itu jelas bahwa bagian utama dari data telah dikirim, kirim byte terakhir (atau beberapa).

Ini sangat penting ketika menyangkut permintaan POST yang besar, misalnya, saat pengunggahan file diperlukan. Tetapi bahkan dalam permintaan kecil ini masuk akal, karena memberikan beberapa byte jauh lebih cepat daripada kilobyte informasi secara bersamaan.

Tunda sebelum mengirim bagian kedua dari permintaan


Menurut penelitian Vlad Roskov , perlu tidak hanya untuk membagi permintaan, tetapi juga masuk akal untuk membuat penundaan beberapa detik antara mengirim bagian utama dari data dan yang terakhir. Dan semua karena server web mulai menguraikan permintaan bahkan sebelum mereka menerimanya secara keseluruhan.



Apa yang ada di server


Misalnya, saat menerima tajuk permintaan HTTP, nginx akan mulai menguraikannya, meng-cache permintaan yang rusak. Ketika byte terakhir tiba, server web akan mengambil permintaan yang diproses sebagian dan mengirimkannya langsung ke aplikasi, sehingga mengurangi waktu pemrosesan permintaan, yang meningkatkan kemungkinan serangan.

Bagaimana menghadapinya


Pertama-tama, ini tentu saja merupakan masalah arsitektur, jika Anda mendesain aplikasi web dengan benar, Anda dapat menghindari balapan semacam itu.

Biasanya, metode kontrol serangan berikut digunakan:


Operasi memblokir akses ke objek yang terkunci di DBMS sampai tidak diblokir. Yang lain berdiri dan menunggu di sela-sela. Penting untuk bekerja dengan kunci dengan benar, bukan untuk memblokir sesuatu yang berlebihan.


Transaksi tertib (serializable) - memastikan bahwa transaksi akan dilakukan secara berurutan, namun, ini dapat memengaruhi kinerja.


Ambil sesuatu (mis. Dlld). Pada saat memanggil fungsi, entri dengan kunci dibuat, jika itu tidak mungkin untuk membuat entri, maka sudah ada dan kemudian permintaan terputus. Di akhir pemrosesan permintaan, catatan dihapus.

Dan secara umum, saya menyukai video karya Ivan the Hard worker tentang kunci dan transaksi, sangat informatif.

Fitur sesi dalam kondisi balapan


Salah satu fitur sesi mungkin itu sendiri mengganggu eksploitasi ras. Misalnya, dalam PHP, setelah session_start (), file sesi terkunci, dan pembukaan kunci hanya terjadi di akhir skrip (jika tidak ada panggilan ke session_write_close ). Jika skrip lain yang menggunakan sesi dipanggil saat ini, ia akan menunggu.

Untuk menghindari fitur ini, Anda dapat menggunakan trik sederhana - untuk mengautentikasi sebanyak yang diperlukan. Jika aplikasi web memungkinkan Anda membuat banyak sesi untuk satu pengguna, kumpulkan saja PHPSESSID dan buat setiap permintaan sebagai pengidentifikasi sendiri.

Jarak ke server


Jika situs tempat Anda ingin beroperasi, kondisi balapan di-host di AWS - bawa mobil dalam AWS. Jika di DigitalOcean - bawa ke sana.

Ketika tugasnya adalah untuk mengirim permintaan dan meminimalkan interval pengiriman di antara mereka, kedekatan langsung ke server web tidak diragukan lagi akan menjadi nilai tambah.

Lagi pula, ada perbedaan ketika melakukan ping ke server 200 dan 10 ms. Dan jika Anda beruntung, Anda bahkan dapat berakhir di server fisik yang sama, maka itu akan sedikit lebih mudah untuk terbang :)

Untuk meringkas


Untuk kondisi balapan yang sukses, Anda dapat menerapkan berbagai trik untuk meningkatkan kemungkinan sukses. Kirim beberapa permintaan tetap hidup dalam satu, memperlambat server web. Pecah permintaan menjadi beberapa bagian dan buat penundaan sebelum mengirim. Kurangi jarak ke server dan jumlah abstraksi ke antarmuka jaringan.

Sebagai hasil dari analisis ini, bersama dengan Michail Badin, kami mengembangkan alat RacePWN

Ini terdiri dari dua komponen:

  • Pustaka perpustakaan, yang mengirimkan banyak permintaan HTTP ke server dalam waktu singkat dan menggunakan sebagian besar fitur dari artikel

  • Utilitas racepwn, yang menerima konfigurasi json dan biasanya mengarahkan perpustakaan ini

RacePWN dapat diintegrasikan ke utilitas lain (misalnya, di Burp Suite), atau Anda dapat membuat antarmuka web untuk mengelola penerbangan (Anda masih belum bisa mendapatkannya). Selamat menikmati!

Namun pada kenyataannya masih ada ruang untuk tumbuh dan Anda dapat mengingat HTTP / 2 dan prospek serangannya. Tetapi saat ini HTTP / 2, sebagian besar sumber daya hanya memiliki permintaan proxy depan untuk HTTP / 1.1 tua yang baik.

Mungkin Anda tahu beberapa seluk beluk lainnya?

Asli

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


All Articles