Sahiden sıkıntınız var zannedersem. Eleman belirli bir web uygulaması zafiyetine ilişkin bilgilendirme metnini anlamadığını dile getirmiş, bu biçim alakasız cevapları sunmak için sorudan kelime seçmeniz gerekiyor yahu.
Soruya gelince, adından da anlaşılabileceği üzere Visual Composer isimli WordPress uzantısı yazılıma dair Ultimate Addons v3.16.10 opsiyonel eklentisinde yer alan XSS, CSRF ve RCE tipi zaafları konu ediniyor. Tek bir adet değil, çoklu zafiyetlere sebebiyet veren bu hataya ilişkin teknik detaylar, yazılımın kaynak kodu üstünden gösterilmiş. WordPress AJAX desteğinde wp_ajax_update_#ARG# geri çağırım uzantısında tanılı wp_ajax_update_css_options uygulamaya şu biçimde tanıtılmış:
Kod:
add_action( 'wp_ajax_update_css_options', array($this,'update_css_options'));
İlgili callback tanısının fonksiyonel biçimde update_css_options'u çağırdığı ortada.
Kod:
function update_settings(){
if(isset($_POST['ultimate_smooth_scroll'])){
$ultimate_smooth_scroll = $_POST['ultimate_smooth_scroll'];
} else {
$ultimate_smooth_scroll = 'disable';
}
$result1 = update_option('ultimate_smooth_scroll',$ultimate_smooth_scroll);
if(isset($_POST['ultimate_smooth_scroll_options'])){
$ultimate_smooth_scroll_options = $_POST['ultimate_smooth_scroll_options'];
} else {
$ultimate_smooth_scroll_options = '';
}
$result2 = update_option('ultimate_smooth_scroll_options',$ultimate_smooth_scroll_options);
if($result1 || $result2){
echo 'success';
} else {
echo 'failed';
}
Fonksiyon betiğinde, kullanıcı erişimine dair kısıtlayıcı hiçbir kontrol satırı bulunmadığından ötürü, web sayfasında herhangi bir yetkilendirmeye sahip herhangi bir hesap, bu fonksiyonu kafasına göre çağırabilir. Fonksiyon, ultimate_smooth_scroll_options isminde bir verinin üstüne yazmak maksadıyla kullanılıyor. Veriyi günceller iken hiçbir güvenlik tedbiri yok, olduğu gibi kullanıcı tarafından iletildiğince yazılıyor.
Kod:
update_option('ultimate_smooth_scroll_options',$ultimate_smooth_scroll_options)
Zafiyetin barınma durumu, ilgili verinin kullanıldığı yere göre değişkenlik gösterecektir. İşin aslı, veri direkt olarak wp_head geri bildirisine argüman sunmakta, WordPress bünyesinde barınan bir event trigger vazifesi üstlenip sayfa içeriğine direkt etkisi olan bir API mekanizması.
Kod:
add_action( 'wp_head', array( $this, 'ultimate_init_vars' ) );
function ultimate_init_vars() {
... blablabla
$ultimate_smooth_scroll_options = get_option('ultimate_smooth_scroll_options');
... blablabla
echo "<script type='text/javascript'>
jQuery(********).ready(function($) {
var ult_smooth_speed = ".$speed.";
var ult_smooth_step = ".$step.";
$('html').attr('data-ult_smooth_speed',ult_smooth_speed).attr('data-ult_smooth_step',ult_smooth_step);
});
</script>";
}
Bu da demek oluyor ki, ultimate_smooth_scroll_options verisine minik bir müdahale aracılığıyla kullanıcıya sunulan sayfa içeriğini tümden değiştirebilirsin, yazdığın her bir satır aynen sayfa içeriğine enjekte olacaktır. Kişi, yazısında bu kritik zaafı sömürmenin birtakım yollarını sunmuş.
1. Stored XSS: Web sayfasını ziyaret eden her bir mahlukatın tarayıcısının arka planında işleyecek bir betik oluşturabilirsin.
Kod:
$ curl -X POST 'http://127.0.0.1/wp-admin/admin-ajax.php' [AUTH_COOKIES] --data "action=update_ultimate_options&ultimate_smooth_scroll=enable&ultimate_smooth_scroll_options[speed]=11&ultimate_smooth_scroll_options[step]=11; eval(String.fromCharCode(1,2,3,4))"
İlgili kod parçacığı, beklenen verilere ek olarak eval(String.fromCharCode(1,2,3,4)) olası zararlı satırın da işlemesine sebebiyet verecektir. Olayın CSRF boyutu yetkin olmaması durumunda yetkili bir bireye göndereceğin tek adrese kişinin erişmesi durumunda dahi tüm bunları yapabilecek olmanda yatıyor. XSS iyi güzel, dilediğince herhangi bir sayfa ziyaretçisine JS betiği enjekte edebiliyorsun; hoş da sunucu taraflı RCE nerede? Şey, o diğer bir dosyada.
wp_ajax_#ARG# uzantılarımıza geri dönelim. Orada, wp_ajax_smile_ajax_add_zipped_font isimli bir geri bildirim tanılaması var idi. Kendileri, AJAX çağrısı durumunda add_zipped_font isimli bir fonksiyonu çağırmakta.
Kod:
public function add_zipped_font() {
//check if referer is ok
//if(function_exists('check_ajax_referer')) { check_ajax_referer('smile_nonce_save_backend'); }
//check if capability is ok
$cap = apply_filters( 'avf_file_upload_capability', 'update_plugins' );
if ( ! current_user_can( $cap ) ) {
die( __( "Using this feature is reserved for Super Admins. You unfortunately don't have the necessary permissions.", "ultimate_vc" ) );
}
//get the file path of the zip file
$attachment = $_POST['values'];
$path = realpath( get_attached_file( $attachment['id'] ) );
$unzipped = $this->zip_flatten( $path, array( '\.eot', '\.svg', '\.ttf', '\.woff', '\.json', '\.css' ) );
// if we were able to unzip the file and save it to our temp folder extract the svg file
if ( $unzipped ) {
$this->create_config();
}
//if we got no name for the font don't add it and delete the temp folder
if ( $this->font_name == 'unknown' ) {
$this->delete_folder( $this->paths['tempdir'] );
die( __( 'Was not able to retrieve the Font name from your Uploaded Folder', 'ultimate_vc' ) );
}
die( __( 'smile_font_added:', 'ultimate_vc' ) . $this->font_name );
}
Kullanıcı erişimini denetliyor, ardından dosya için dizini argüman olarak alıp zip_flatten isimli, veri olarak düzenli ifadeler barındıran bir fonksiyona şutluyor. Bu fonksiyon da dosya içeriğini, regexp eşleşmesi neticesinde çıkartıyor. İyi hoş da, hata nerede? zip_flatten fonksiyonunun betiğinde.
Kod:
foreach ( $filter as $regex ) {
preg_match( "!" . $regex . "!", $entry, $matches );
if ( ! empty( $matches ) ) {
$delete = false;
break;
}
}
Kod, ilgili *zararsız* dosya uzantılarının, yalnızca dosya isminde yer alıp almadığını denetliyor. Başta, sonda, ortada beride olması hiç mühim değil. Anlayacağınız arşiv içeriğinde yer alan damn.json.php dahi dizine çıkartılmakta.
Sonuç olarak niyeti olan eleman titizce hazırlanmış bir senaryo vasıtasıyla web sayfasında yer alan herhangi bir yetkiliye CSRF üzerinden istemsiz düzenlemeler yaptırabilir, bu düzenlemeler ışığında web sayfası ziyaretçilerinin tamamına betik enjekte edebilir,böylelikle her türlü kullanıcı verisine, çerezler misal, ulaşıp yönetici hesabı üzerinden RCE vasıtasıyla sunucu taraflı komut çalıştırabilir. Eleman bir de create_config->write_config fonksiyonunda açık tespit etmiş.
Olay budur efendim. Sevgiler.