암호화되지 않은 중요정보
정의
- 많은 응용 프로그램은 메모리나 디스크 상에서 중요한 정보(개인정보, 인증정보, 금융정보 등)를 처리하는데, 이러한 정보가 제대로 보호되지 않을 경우, 보안 문제가 발생하거나 데이터의 무결성이 깨질 수 있다.
- 사용자 또는 시스템의 중요 정보가 포함된 데이터를 평문으로 송·수신 또는 저장 시 인가되지 않은 사용자에게 민감한 정보가 노출될 수 있다.
안전한 코딩기법
- 중요정보(개인정보, 금융정보, 패스워드)를 저장하거나 통신채널로 전송할 때는 반드시 암호화 과정을 거쳐야 하며, 중요정보를 읽거나 쓸 경우에 권한인증 등을 통해 적합한 사용자만 중요정보에 접근하도록 해야 한다.
- 가능하다면 SSL 또는 HTTPS 등과 같은 보안 채널을 사용해야 한다.
코드예제
중요정보 평문저장
다음은 안전하지 않은 코드예제로, 사용자로부터 전달받은 패스워드 암호화를 누락한 코드입니다.
#암호화되지 않은 중요정보(안전X)
def update_pass_bad(dbconn, password, user_id):
c = dbconn.cursor()
c.execute('UPDATE USERS SET PASSWORD=%s WHERE USER_ID=%s', password, user_id)
dbconn.commit()
다음은 안전한 코드예제로, 해시 알고리즘을 이용하여 단방향 암호화 이후에 패스워드를 저장하는 코드입니다.
#암호화되지 않은 중요정보(안전O)
def update_pass_good(dbconn, password, user_id, salt):
hash_obj = SHA256.new()
hash_obj.update(bytes(password + salt, 'utf-8'))
hash_pwd = hash_obj.hexdlgest()
c = dbconn.cursor()
c.execute('UPDATE USERS SET PASSWORD=%s WHERE USER_ID=%s', (hash_pwd, user_id))
dbconn.commit()
중요정보 평문전송
다음은 안전하지 않은 코드예제로, 인자값으로 전달받은 패스워드를 검증 없이 네트워크를 통해 전송하는 코드입니다. 이런 경우 패킷 스니핑을 통하여 패스워드가 노출될 수 있습니다.
#암호화되지 않은 중요정보(안전X)
HOST = '127.0.0.1'
PORT = 65434
def send_password_bad(password):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
s.sendall(password.endcode('utf-8'))
data = s.recv(1024)
다음은 안전한 코드예제로, 네트워크를 통해 전달되는 패스워드가 노출되지 않도록 암호화하여 전송하는 코드입니다.
#암호화되지 않은 중요정보(안전O)
HOST = '127.0.0.1'
PORT = 65434
def send_password_good(password):
block_key = os.environ.get('BLOCK_KEY')
aes = AEScipher(block_key)
enc_passowrd = aes.encrypt(password)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
s.sendall(enc_passowrd.endcode('utf-8'))
data = s.recv(1024)
class AEScipher:
BS = AES.block_size
def __init__(self, s_key):
self.s_key = hashlib.sha256(s_key.endcode('utf-8')).digest()
def pad(self, m):
return m + bytes([self.BS - len(m) % self.BS] * (self.BS - len(m) % self.BS))
def encrypt(self, plain):
plain = self.pad(plain.encode())
iv = Random.new().read(AES.block_size)
cipher = AES.new(self.s_key, AES.MODE_CBC, iv)
return base64.b64encode(iv + cipher.encrypt(plain)).decode('utf-8')
보안기능/암호화되지 않은 중요정보
[참고문헌] Python 시큐어코딩 가이드(2022) / KISA(한국인터넷진흥원)