1. 개요
- 목적 : unix password cracker 만들기 (SHA512 해시 패스워드 기준)
- 난이도 : 하
- 사용 라이브러리 : crypt
2. 준비
- python3
3. 코드 작성
1.
python 기본 라이브러리의 해시 기능을 테스트 해보자.
salt와 해시시키고자 하는 plain text를 삽입하면 다음과 같은 결과를 얻는다.
import crypt
string1 = 'HX' #salt
string2 = 'egg' #plain text
print(crypt.crypt(string2, string1)) #Hash digested
###### print ######
└─$ python3 crypt_test.py
HX9LLTdc/jiDE
2.
dictionary 파일로 부터 brute-force를 위한 word를 하나씩 가져와 crypt를 이용해 salt 및 해시데이터를 만들고 대조해보는 testPass 함수를 작성해보자.
중요한 점은 리눅스 /etc/shadow 파일 포맷에서 : 이후에 $구분자에 의해 hash 알고리즘과 salt가 결정된다는 점이다.
아래 예시에서 $6$은 해시 알고리즘으로 SHA512를 이용한다는 의미로 salt 데이터는 해당 알고리즘 부를 포함한
$6$5l70Gupv 가 된다.
root:$6$5l70Gupv$xBTxhCSexudn5jJ9hampIfTK0KIR3nqK1K1Rxye.OA5obtKArO7jgftjJtVSdp31MPxItEPmOuWhbgBvp0wqn.:16737:0:99999:7:::
이를 기준으로 작성하면 다음과 같다.
def testPass(cryptPass):
with open('dictionary.txt', 'r') as dictFile:
salt = '$6$'+cryptPass.split('$')[2] # salt should be $6$~~~~ format
#print(salt)
for word in dictFile.readlines():
word = word.strip('\n') # delete new line char in word
cryptWord = crypt.crypt(word, salt)
if (cryptWord == cryptPass):
print( "[+] Found Password : "+word+"\n")
return
print( "[-] Password Not found \n")
return
3.
crack을 수행할 패스워드(해시파일)을 불러와서 testPass함수를 적용할 main 함수를 작성한다.
main 함수는 /etc/shadow 상의 패스워드 포맷에 맞춰 ':'를 기준으로 파싱해서 데이터를 가져오게 만든다.
완성된 코드는 다음과 같다.
import crypt
def testPass(cryptPass):
with open('dictionary.txt', 'r') as dictFile:
salt = '$6$'+cryptPass.split('$')[2] # salt should be $6$~~~~ format
#print(salt)
for word in dictFile.readlines():
word = word.strip('\n') # delete new line char in word
cryptWord = crypt.crypt(word, salt)
if (cryptWord == cryptPass):
print( "[+] Found Password : "+word+"\n")
return
print( "[-] Password Not found \n")
return
def main():
with open('password.txt', 'r') as passFile:
for line in passFile.readlines():
if ":" in line :
user = line.split(':')[0]
cryptPass = line.split(':')[1]
print("[*] Cracking Password For : "+user)
testPass(cryptPass)
if __name__ == "__main__": # only run this part if not imported
main()
4. 테스트
1. 임의로 dictionary.txt 파일을 생성
2. 임의로 계정을 생성(useradd)
3. 생성된 계정에 패스워드를 부여(passwd)
test계정에는 dictionary.txt에 존재하는 비밀번호를 부여하였으며, test2계정에는 존재하지 않는 비밀번호를 부여
4. /etc/shadow를 통해 SHA512로 해시된 암호 값을 확인
앞에어 언급했던 것처럼 여기서 test, test2라는 username 뒤에 $6$라는 것은 패스워드가 SHA512로 해싱되었다는 것을 의미한다. etc/shadow파일 포맷 대한 자세한 사항은 다음 링크를 참고
5. 마지막 두 계정 데이터를 password.txt 파일에 넣자.
└─$ sudo cat /etc/shadow | tail -2 > password.txt
└─$ cat password.txt
test:$6$sUnNAyLAawyBU1i4$Eg0CZ3RYW9JKO6niYFCMVcoLghizV4Rj8c8/.4IeiWUPNOZtNQthc4GZwp28geNHwiEKHjgoXK9d6O1kA6r1T1:19106:0:99999:7:::
test2:$6$nVqqrMIYNehKmyS0$DLu.f3x26XTHkOgssIw8sqQFct3DtqfyuzwoWZKud8Yueinmk195K1VBjwz8ZOt9W2rBnhqOWAPN2lJDCbG3k/:19106:0:99999:7:::
6. 이후 해당 코드를 돌려보면, 다음과 같이 test계정의 암호 '1234'는 크래킹 하였고 dictionary.txt에 존재하지 않는 비밀 번호를 부여한 test2 계정의 암호는 크래킹하지 못한 것을 확인할 수 있다.
[참고] A Cookbook for Hackers, Forensic Analyst, Penetration Testers and Security Engineers, O'Conner
'Software Engineering > Python' 카테고리의 다른 글
파이썬을 이용한 파일 압축/압축 풀기 프로그램 만들기 (0) | 2022.04.24 |
---|---|
파이썬 데이터조작 cheet sheet (0) | 2022.04.20 |
댓글