보안 공부/소스코드 보안약점 진단

소스코드 보안약점 진단 - 중요정보 평문저장

H.J.World 2022. 1. 6. 10:10
728x90
반응형

소스코드 보안약점 진단 // 소프트웨어 보안약점 진단 // SW 보안약점 진단과 같이 다양한 이름으로 불리는 진단 과업 중 하나이다.

SW개발보안은 해킹 등 사이버공격의 원인인 보안약점을 SW개발단계에서 사전에 제거하고 SW 개발 생명주기의 각 단계별로 수행하는 일련의 보안활동을 통하여 안전한 SW를 개발·운영하기 위한 목적으로 적용하는 개발체계이다.

해당 내용은 KISA에서 발간하는 취약점 진단 가이드 항목을 기준으로 작성한다.

 

제2절 보안기능

보안기능(인증, 접근제어, 기밀성, 암호화, 권한관리 등)을 부적절하게 구현시 발생할 수 있는 보안 약점으로 적절한 인증 없는 중요기능 허용, 부적절한 인가 등이 포함된다.


5. 중요정보 평문저장

가. 개요

많은 응용프로그램은 메모리나 디스크에서 중요한 데이터(개인정보, 인증정보, 금융정보)를 처리한다. 이러한 중요 데이터가 제대로 보호되지 않을 경우, 보안이나 데이터의 무결성을 잃을 수 있다. 특히 프로그램이 개인정보, 인증정보 등의 사용자 중요정보 및 시스템 중요정보를 처리하는 과정에서 이를 평문으로 저장할 경우 공격자에게 민감한 정보가 노출될 수 있다.

나. 보안대책

개인정보(주민등록번호, 여권번호 등), 금융정보(카드번호, 계좌번호 등), 패스워드 등 중요정보를 저 장할 때는 반드시 암호화하여 저장해야 하며, 중요정보를 읽거나 쓸 경우에 권한인증 등을 통해 적합 한 사용자가 중요정보에 접근하도록 해야 한다.

다. 코드예제

아래 예제는 인증을 통과한 사용자의 패스워드 정보가 평문으로 DB에 저장된다.

- 안전하지 않은 코드의 예 JAVA -

1: String id = request.getParameter("id");
// 외부값에 의해 패스워드 정보를 얻고 있다.
2: String pwd = request.getParameter("pwd");
3: ......
4: String sql = " insert into customer(id, pwd, name, ssn, zipcode, addr)“
+ " values (?, ?, ?, ?, ?, ?)";
5: PreparedStatement stmt = con.prepareStatement(sql);
6: stmt.setString(1, id);
7: stmt.setString(2, pwd);
......
// 입력받은 패스워드가 평문으로 DB에 저장되어 안전하지 않다.
8: stmt.executeUpdate();

 

- 안전한 코드의 예 JAVA -

다음 예제는 패스워드 등 중요 데이터를 해쉬값으로 변환하여 저장하고 있다.

1: String id = request.getParameter("id");
// 외부값에 의해 패스워드 정보를 얻고 있다.
2: String pwd = request.getParameter("pwd");
// 패스워드를 솔트값을 포함하여 SHA-256 해시로 변경하여 안전하게 저장한다.
3: MessageDigest md = MessageDigest.getInstance("SHA-256");
4: md.reset();
5: md.update(salt);
6: byte[] hashInBytes = md.digest(pwd.getBytes());
7: StringBuilder sb = new StringBuilder();
8: for (byte b : hashInBytes) {
9: sb.append(String.format("%02x", b));
10: }
11: pwd = sb.toString();
12: ......
13: String sql = " insert into customer(id, pwd, name, ssn, zipcode, addr)"
+ " values (?, ?, ?, ?, ?, ?)";
14: PreparedStatement stmt = con.prepareStatement(sql);
15: stmt.setString(1, id);
16: stmt.setString(2, pwd);
17: ......
18: stmt.executeUpdate();

 

라. 진단방법

중요정보란 일반적으로 설계과정에서 결정되기 때문에, 중요정보의 평문저장을 일반적으로 검사할 수 있는 기법은 존재하지 않는다. 따라서 이러한 정보를 저장하고 사용하는 경우 반드시는 암호화 및 복호화 과정을 거쳐야 한다. 다만, 로그인이나 암호의 사용과 같은 특정한 경우 해당 메소드의 인자 값 추적을 통해 평문 유무를 판단할 수 있다.

중요정보라고 판단된 데이터 경우에는 불필요한 참조가 존재하지 않도록 제거해야하며, 임의의 변수 에 임시 저장할 경우에도 암호화 유무를 확인해야하며 사용이 완료된 임시변수의 값은 반드시 초기화 해주어야 한다. 또한, 쿠키에 값을 저장하는 경우에는 중요정보를 저장하지 않거나 또는 저장을 하더라도 암호화를 통해서 저장해야 한다.

다음 예제는 소켓 연결이 수립되고 난 후, 전달 받은 암호 값을 password_buffer에 저장하고 이를 다시 파일에 직접 기록하는 코드이다. 이 때, 전달받은 값을 암호화하지 않고 저장하기 때문에 해당 파일에 접근할 수 있는 사용자라면, 암호 값을 획득할 수 있다.

1: if (connect(sock, (struct sockaddr *)&server, sizeof server) < 0)
2: error(“Connecting”);
3: …
4: while ((n=read(sock,buffer,BUFSIZE-1))!=-1) {
5: … // buffer값을 password_buffer에 추가
6: write(passFileD,password_buffer,n);
7: …

중요정보를 암호화 작업 없이 password_buffer에 그대로 유지하고 있으며, 해당 내용을 파일에 저장하기 때문에 위 예제 코드는 보안약점이 존재한다고 진단할 수 있으며, 임시 변수인 buffer를 사용완 료하고 난 후 값의 초기화 여부 또한 확인해야 한다.

- 정탐코드의 예 -

다음 예제는 데이터베이스에 접근하기 위한 정보를 설정파일로 작성한 경우이다. 다른 소스 파일에 서 해당 파일을 포함(Include)하여 사용하지만, 설정파일에 데이터베이스를 접근하는 ID와 패스워드 가 평문으로 저장되어 있기 때문에 이러한 정보가 외부로 노출될 수 있는 위험성이 있다.

1: …
2: <connectionStrings>
3: <add name=”ud_DEV” connectionString=”connectDB=uDB; uid=db2admin; pwd=-
password; dbalias=uDB;” providerName=”System.Data.Odbc” />
4: </connectionStrings>
5: …
728x90
반응형