Code Review : Arbitrary Download File

Code Review. Apa itu?

Artikel ini merupakan sebuah studi kasus nyata, yang ada di beberapa tempat. Salah satunya adalah merupakan project Security Testing yang pernah saya lalui. Case persis mungkin tidak sama. Namun saya buatkan script code yang menyerupai, agar lebih mudah dipahami.

Code Review merupakan sebuah metoda untuk mengaudit file. Baik dari sisi tinjauan performa, maupun tinjauan keamanan. Dalam dunia Cyber Security, Code Review sering dianggap dimasukkan dalam kategori White Box Security Audit. Seorang Blackbox-er yang menemukan source code lengkap, misal seperti di artikel sebelumnya, dia selanjutnya akan melakukan Code Review juga. Mencari celah. Apakah dia tetap dinamakan Blackbox tester? Ya. Secara tugas dia tetap Blackbox Tester.

Sebenarnya, banyak mesin Code Review yang sudah tersedia di internet secara gratis. Kita bisa saja menggunakan Sonarqube , ataupun Snyk.io, atau mesin lainnya. Tetapi kadang review secara manual tetap diperlukan.

 

Arbitrary Download File

Arbitrary Download File, mungkin dapat saya masukkan dalam kategori vulnerability bug besar : Directory Traversal. Ini mirip-mirip sama LFI si. Tapi jika LFI bisa langsung dibuat RCE, untuk Arbitrary Download File ini tidak selalu. Adalah sebuah kerentanan aplikasi/code yang memiliki script streaming download yang memungkinkan untuk dapat mendownload file-file yang tidak seharusnya boleh didownload. Bug ini masih cukup banyak terjadi.

Perhatikan script di bawah ini :

<?php

$file="resources/".$_GET['file']."";
$tmp_ext = explode('.',$file);
$ext = end($tmp_ext);
$arr_ext = array("jpeg","jpg","pdf","rar","zip","png");
if(!in_array($ext,$arr_ext)) header("Location: http://".$_SERVER['SERVER_NAME']."/index.php?pg=brokenlink");
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Type: application/force-download");
header( "Content-Disposition: attachment; filename=".basename($file));
header( "Content-Description: File Transfer");
@readfile($file);
?>

Apakah ada kesalahan di script tersebut?

 

Code Review Arbitrary Download File

Code Review Arbitrary Download File

Kira-kira, script tersebut biasanya digunakan dengan model halaman seperti di atas ini. Sebuah halaman web, yang memiliki item download, yang jika kita dekati dengan mouse, maka pada progress bar (pojok kiri bawah), akan memunculkan informasi URL nya. Di case ini, URL tersebut adalah :

http://localhost/mainan/download_error/download.php?file=a.jpg

Mari kita telaah satu persatu.

 

Empat Baris Pertama :

$file="resources/".$_GET['file'].""; $tmp_ext = explode('.',$file); $ext = end($tmp_ext); $arr_ext = array("jpeg","jpg","pdf","rar","zip","png");

Empat baris pertama adalah menentukan lokasi file yang akan didownload, berdasarkan nama file yang didapat dari variable $_GET[‘file’]. Selanjutnya, script tersebut membentuk sebuah array yang isinya adalah berisi tentang daftar ekstensi file yang ditentukan.

 

Baris Kelima

if(!in_array($ext,$arr_ext)) header("Location: http://".$_SERVER['SERVER_NAME']."/index.php?pg=brokenlink");

Bagian ini, adalah membandingkan antara nama file dan daftar array. Jika tidak terdapat nama ekstensi yang disebut di dalam nama file yang dipanggil di $_GET, maka segera akan dibuang dengan cara diredirect ke file index.php?pg=brokenlink. Ini memang dimaksudkan juga untuk mengamankan dari ancaman directory traversal attack.

Baris Selanjutnya.

Setelah dirasa sudah diamankan dulu di baris kelima, maka script dilanjutkan dengan hal berikut :

header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Type: application/force-download");
header( "Content-Disposition: attachment; filename=".basename($file));
header( "Content-Description: File Transfer");
@readfile($file);

Jadi, script terakhir ini bertujuan, bahwa setelah diamankan akan dilanjutkan dengan aktivitas download, dengan mengirim data download ke browser milik user. Aman?

 

Tinjauan keamanan

Dari tinjauan keamanan, script di atas memang sementara ini aman, jika dan hanya jika dibuka menggunakan browser organik, seperti Mozilla, Chrome, dan lain sejenisnya, yang efektif dengan redirect user. Namun apa jadinya jika dibuka dengan menggunakan curl, wget, atau lainnya? Perintah header location, hanya akan dia baca, tapi tidak diikuti. Setelah itu dia akan bablas ke baris bawahnya dan melanjutkan perintah di baris bawahnya.

Mari kita coba dengan jurus curl saya.

curl http://localhost/mainan/download_error/download.php?file=../../../../../../../etc/passwd

Code Review Arbitrary Download File

Gimana? Bablas ya? Ndak ada redirect-redirectan lagi… Oke, kita lanjutkan mencari info OS, dan juga lokasi Apache. Yang selanjutnya dapat dilanjutkan dengan mencari informasi lebih lanjut, untuk melanjutkan skenario serangan berikutnya.

Code Review, Arbitrary Download File

 

Mitigasi

Nah ini… Bagian mitigasi ini bisa dilakukan dengan beberapa cara. Dari sisi server, kita dapat menggunakan rewrite + Regex. Sedangkan di sisi programming, seharusnya dilakukan filtering dengan benar. Untuk filtering di sisi programming, lain kali ya, saya belajar programming dulu. Namun untuk hardening di sisi server, kita dapat menambahkan rule Rewrite. Stepnya adalah mencari lokasi konfigurasi virtualhost, dan memastikan bahwa Module Rewrite telah menyala. Setelah itu ditambahkan rule ini :

RewriteEngine On
RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=http:// [OR]
RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=(\.\.//?)+ [OR]
RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=/([a-z0-9_.]//?)+ [NC,OR]
RewriteCond %{QUERY_STRING} \=PHP[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} [NC,OR]
RewriteCond %{QUERY_STRING} (\.\./|\.\.) [OR]
RewriteCond %{QUERY_STRING} ftp\: [NC,OR]
RewriteCond %{QUERY_STRING} http\: [NC,OR]
RewriteCond %{QUERY_STRING} https\: [NC,OR]
RewriteCond %{QUERY_STRING} \=\|w\| [NC,OR]
RewriteCond %{QUERY_STRING} ^(.*)/self/(.*)$ [NC,OR]
RewriteCond %{QUERY_STRING} ^(.*)cPath=http://(.*)$ [NC,OR]
RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} (<|%3C)([^s]*s)+cript.*(>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} (\<|%3C).*iframe.*(\>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} (<|%3C)([^i]*i)+frame.*(>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} base64_encode.*\(.*\) [NC,OR]
RewriteCond %{QUERY_STRING} base64_(en|de)code[^(]*\([^)]*\) [NC,OR]
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} ^.*(\[|\]|\(|\)|<|>).* [NC,OR]
RewriteCond %{QUERY_STRING} (NULL|OUTFILE|LOAD_FILE) [OR]
RewriteCond %{QUERY_STRING} (\./|\../|\.../)+(motd|etc|bin) [NC,OR]
RewriteCond %{QUERY_STRING} (localhost|loopback|127\.0\.0\.1) [NC,OR]
RewriteCond %{QUERY_STRING} (<|>|'|%0A|%0D|%27|%3C|%3E|%00) [NC,OR]
RewriteCond %{QUERY_STRING} concat[^\(]*\( [NC,OR]
RewriteCond %{QUERY_STRING} union([^s]*s)+elect [NC,OR]
RewriteCond %{QUERY_STRING} union([^a]*a)+ll([^s]*s)+elect [NC,OR]
RewriteCond %{QUERY_STRING} (;|<|>|'|"|\)|%0A|%0D|%22|%27|%3C|%3E|%00).*(/\*|union|select|insert|drop|delete|update|cast|create|char|convert|alter|declare|order|script|set|md5|benchmark|encode) [NC,OR]
RewriteCond %{QUERY_STRING} (sp_executesql) [NC]
RewriteRule ^(.*)$ - [F,L]

 

Ingat, script ini ada kemungkinan akan membuat beberapa parameter Query String / Request URI yang mengandung karakter tertentu menjadi tidak jalan, Forbidden 403. Silakan ditelaah sendiri.

 

Q: Om, bisa nggak regex itu ditaruh di .htaccess?

A: Bisa doong. Tapi nggak disarankan, karena .htaccess ada di folder user. Apalagi kondisi bisa ditulisi, akhirnya nanti bisa juga diganti hacker.

 

Let’s Discuss…. Happy Pentest, Happy Testing.

Leave a Reply

Your email address will not be published. Required fields are marked *