본문 바로가기
Back-end/Python

[Pyftpdlib] FTP 서버 만들기 (3) - 사용자 패스워드 암호화

by 허도치 2020. 2. 18.

2020/02/12 - [Back-end/Python] - [Pyftpdlib] FTP 서버 만들기 (1) - 설치 및 실행

2020/02/12 - [Back-end/Python] - [Pyftpdlib] FTP 서버 만들기 (2) - 사용자 인증 설정

 

 

 

0. 서론

 지난 포스트에서 지정된 폴더와 권한을 가진 유저를 생성하여 FTP서버에 접속하는 방법에 대해서 알아보았다. 유저 인증 방식을 통해 FTP서버의 보안을 강화하는 효과를 얻을 수 있었다. 하지만, 사용자의 패스워드가 암호화 되지않은 일반 텍스트이기 때문에 해킹에 취약할 수 밖에 없다. 그래서, 이번 포스트에서는 사용자의 패스워드를 암호화하고 이를 이용하여 로그인하는 방법에 대해서 알아보도록 하겠다.

 

 

 

1. 패스워드 암호화
1-1. 스크립트 작성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#md5_hash.py
import sys
import argparse
from hashlib import md5
 
parser = argparse.ArgumentParser(description='패스워드 암호화')
parser.add_argument('--pwd', required=True, help="패스워드를 입력해주세요.")
args = parser.parse_args()
 
password = args.pwd
if sys.version_info >= (30):
    password = password.encode('utf-8')
 
md5_hash = md5(password).hexdigest()
 
print'password: {}'.format( password ) )
print'hashed: {}'.format( md5_hash ) )
cs

- 3 ln: arguments를 파싱해서 사용하기 좋게 만들어주는 모듈.
- 4 ln: 파이썬 기본 라이브리러인 hashlib에서 MD5 알고리즘 모듈만 사용.
  * MD5(Message-Digest algorithm 5): 128비트 길이의 암호화 해시 함수.
- 6~8 ln: 사용자의 패스워드를 입력받는 Arguments Parser 생성.
- 11~12 ln: 파이썬이 3버전 이상인 경우, 'utf-8'로 인코딩. (Bytes 타입으로 변경)
  * md5 모듈이 파이썬 2버전에서는 String을 사용하는데, 3버전부터 Bytes를 사용.
- 14 ln: 입력받은 패스워드를 128비트 길이의 암호화 해시로 변경.

 

1-2. 실행

$ python md5_hash.py --pwd admin1234

 

1-3. 실행 결과

- 'admin1234'는 MD5 암고리즘을 통해 'c93ccd78b2076528346216b3b2f701e6'으로 변경.
- 'user1234'는 MD5 암고리즘을 통해 'b5b73fae0d87d8b4e2573105f8fbe7bc'으로 변경.
- 이 패스워드를 FTP서버에 적용해보자.

 

 

 

2. FTP 서버 사용자 패스워드 검증
2-1. 스크립트 작성
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
#ftp_server_auth.py
import os
import sys
from hashlib import md5
 
from pyftpdlib.authorizers import DummyAuthorizer, AuthenticationFailed
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer
 
FTP_HOST = '0.0.0.0'
FTP_PORT = 9021
 
FTP_ADMIN_DIR = os.path.join(os.getcwd(), 'storage')
FTP_USERS_DIR = os.path.join(os.getcwd(), 'storage/users')
 
class DummyMD5Authorizer(DummyAuthorizer):
    def validate_authentication(self, username, password, handler):
        if sys.version_info >= (30):
            password = password.encode('utf-8')
        hash = md5(password).hexdigest()
        try:
            if self.user_table[username]['pwd'!= hash:
                raise KeyError
        except KeyError:
            raise AuthenticationFailed
 
def main():
    authorizer = DummyMD5Authorizer()
    
    authorizer.add_user('admin''c93ccd78b2076528346216b3b2f701e6', FTP_ADMIN_DIR, perm='elradfmwMT')
    authorizer.add_user('user''b5b73fae0d87d8b4e2573105f8fbe7bc', FTP_USERS_DIR, perm='elr')
   
    handler = FTPHandler
    handler.banner = "Dochi's FTP Server."
    handler.authorizer = authorizer
    handler.passive_ports = range(6000065535)
    
    address = (FTP_HOST, FTP_PORT)
    server = FTPServer(address, handler)
    
    server.max_cons = 256
    server.max_cons_per_ip = 5
 
    server.serve_forever()
 
if __name__ == '__main__':
    main()
cs

- 16 ln: DummyAuthorizer Class를 상속 받은 DummyMD5Authorizer Class 생성.
- 17 ln: validate_authentication 함수를 오버라이드(재정의).
  * 사용자가 로그인을 시도할 때, 입력한 패스워드와 사용자의 패스워드를 비교하는 함수.
- 18~25 ln: 사용자 패스워드를 검증하는 로직.
- 28 ln: DummyMD5Authorizer 객체 생성
-
30~31 ln: 암호화된 사용자 패스워드 입력.

 

2-2. FTP서버 실행

$ python ftp_server_auty.py

 

2-3. FTP서버 실행 결과

 

2-4. FTP서버 접속 결과

- 사용자명 'admin', 패스워드 'admin1234'를 입력하여 접속 성공.

 

 

 

마치며

- 사용자의 패스워드를 암호화함으로써 한층 더 보안이 강화된 느낌이다.
- 지금은 MD5 해싱 알고리즘을 사용했는데, base64나 대칭키 기반의 AES256을 적용해보는 것도 좋을것 같다.

댓글