일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Stream
- Jenkins
- rabbitmq
- sqlserver
- 제이쿼리그리드
- 자동배포
- 자동빌드
- apache.poi
- JQuery
- poi
- 그리드
- 엑셀 업로드
- ORM
- 보안
- DevOps
- 스트림
- 자바8
- mssql
- mom
- stream api
- JPA
- java
- QueryDSL
- Javascript
- 대용량 업로드
- spring
- MessageQueue
- jqGrid
- ci/cd
- docker
- Today
- Total
개발 메모장
[보안] 시큐어 코딩이란? 본문
#. 기술의 발전에 따라 시스템을 보호하는 방식이 다양해졌고, 보호해야 하는 민감 정보들에 대한 취급 및 처리하는 경우도 많아졌을 것입니다.
#. 하지만 이에 따라 악용과 공격에 대한 기술도 발전했을 것입니다.
#. 더군다나 이전에 만들어진 시스템의 경우 발전된 기술로 공격 또는 악용할 것이며, 이들을 대응하려면 시스템에 지속적인 보안 처리를 해줘야 하나 실상은 그렇지 못한 경우가 많을 것입니다.
#. 행안부에 의해 제정된 법규와 그 기준을 간단하게나마 살펴보도록 하겠습니다.
- 시큐어 코딩이란??
- 해킹, 사이버 공격의 원인이 될 수 있는 보안상 취약점들을 찾아 제거해 사용자와 개발자 모두 안전한 소프트웨어를 개발할 수 있게 하는 소프트웨어 개발 기법 또는 지침, 원칙이라 할 수 있습니다.
- 유지보수 시에도 추가적인 적용을 하긴 하지만 주로 개발 단계에서 시큐어 코딩과 관련된 로직을 구현하기에 개발자의 능력이 중요하며 어떤 방식으로 처리할지 등이 시큐어 코딩 구성의 주요 대상이 됩니다.
- 개발자도 사람인지라 휴먼 에러를 발생하는 경우가 많기에 모든 취약점에 대해 고려하여 로직을 구현하기엔 한계가 있기 때문에 행정안전부에서 시큐어 코딩에 대한 가이드 라인을 제시하였습니다.
- 아래는 행정안전부 정책자료 중 Java로 개발 시 참고할 시큐어 코딩에 대한 가이드라인의 내용 중 일부입니다.

1. 입력 데이터 검증 및 표현
- 총 26개의 공격에 대한 시큐어 코딩 가이드가 있습니다.
- 시스템에서 입력한 값에 대한 검증이 적절하지 않은 경우 발생할 수 있는 보안 취약점을 예방하기 위해 점검하는 항목들입니다.
- 주로 SQL Injection, XSS 공격이 여기에 해당되며 이를 막기 위한 코딩방법입니다.
- XSS 공격 Example
- 프론트에서 입력한 값을 백에서 받아 사용자가 입력한 값으로 다시 리턴해줘야 할 때 특수문자 필터링을 제대로 하지 않는다면 XSS 공격에 취약한 상태가 됩니다.
- 툴을 이용해 확인한 결과 URL Encoding이 되어 정상적인 url 형태로 변경되었고 조회를 누르기만 해도 입력한 사이트로 이동하게 되어 문제가 발생하게 됩니다.


- 따라서 반드시 프론트에서도 정규식을 이용해 스크립트에 사용되는 특수문자들을 필터링해야 합니다.
- 백에서도 마찬가지로 메서드를 생성하여 필터링 처리해야 합니다.
public static String XSSfiltered(String origin) {
return origin.replaceAll("<", "<")
.replaceAll(">", ">")
.replaceAll("\\[&]", " &")
.replaceAll("\"", """)
.replaceAll("'", "'")
.replaceAll(" ", " ")
.replaceAll("\\(", "(")
.replaceAll("\\)", ")")
.replaceAll("\\[#]", "#");
}
- SQL Injection Example
- PreparedStatement를 사용하지 않고 처리하거나 myBatis 등에서 파라미터에 $를 사용하여 동적 쿼리로 작동 시 문제가 됩니다.
- 따라서 반드시 전처리 후 #를 이용해 안전하게 처리하는 것이 권장하는 방법입니다.
- 위험한 코드의 예에서 test의 값이 a' or 1=1 이 들어가면 전체 데이터가 조회됩니다.
(Select * From testTable Where test_col = 'a' or 1=1 이 되므로 전체 조회 가능)
// 위험한 코드의 예
String test = request.getParameter("test");
...
String sql = "Select * From testTable Where test_col = '" + test + "'";
Connection con = db.getConnection();
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(sql);
// 안전한 코드의 예
String test = request.getParameter("test");
...
String sql = "Select * From testTable Where test_col = ?";
Connection Con = db.getConnection();
PreparedStatement pstmt = con.preparedStatement(sql);
pstmt.setString(1, test);
ResultSet rs = pstmt.executeQuery();
2. 보안 기능
- 총 24개의 공격에 대한 시큐어 코딩 가이드가 있습니다.
- 시스템 개발 단계에서 인증, 인가, 비암호화(평문 저장 및 전송), 기밀성, 접근 제어 등에 대한 구현을 통해 취약점을 예방하기 위한 항목들입니다.
- 암호와 같은 중요 정보에 대해 암호화 처리를 하지 않고 하드 코딩하여 노출될 수 있는 위험성과 인증 및 인가, 권한에 따른 문제 요인 등을 다룹니다.
※ 비인가 접근을 막고 저장된 정보는 암호화를 통해 취약점이 존재하지 않도록 코딩 및 관리해야 합니다.
(암호의 경우 복호화가 불가한 SHA를 사용하는 것이 좋음)
3. 시간 및 상태
- 총 7개의 공격에 대한 시큐어 코딩 가이드가 있습니다.
- 프로그램 동작 과정 중 멀티 스레드 또는 멀티 프로세스 등의 환경에서 시스템의 자원, 세션 정보 등에 대한 정보와 관련된 취약점에 대한 내용입니다.
- 데드락, 자원 공유에 대한 경쟁조건, 세션 고착 등에 대한 문제점이 발생하게 됩니다.
※ 제어문을 사용하지 않는 재귀함수
- 무한 루프를 막기 위해 모든 재귀 호출에 조건문 또는 반복문 블록 내에서만 처리하게끔 구성해야 합니다.
- 재귀 호출이 조건문 또는 반복문 밖에서 일어나는 경우 대부분 무한 루프를 일으켜 시스템을 마비시킬 수 있습니다.
※ 레이스 컨디션 발생에 주의
- 하나의 자원을 다수의 프로세스가 사용하는 경우에 자원 공유가 적절히 되지 않아 발생하는 오류가 원인이 됩니다.
- 두 개의 프로세스가 하나의 자원을 사용하는데 그중 하나의 프로세스에서 사용할 파일의 상태가 변경된다면 레이스 컨디션이 발생할 수 있습니다.
※ 레이스 컨디션(Race Condition)
- 두 개 이상의 프로세스가 공용 자원을 병행적으로(concurrently) 읽거나 쓸 때, 공용 데이터에 대한 접근이 어떤 순서에 따라 이루어졌는지에 따라 그 실행 결과가 달라지는 상황을 말합니다.
4. 에러 처리
- 총 4개의 공격에 대한 시큐어 코딩 가이드가 있습니다.
- 에러 발생 시 이를 처리하는 방식이 부적절하거나 누락된 경우 발생할 수 있는 내용과 관련된 취약점에 대한 내용입니다.
- 개발 시 개발자 편의를 위하여 에러 로그를 콘솔에 띄우는 경우가 있는데 이 것 또한 공격자의 공격을 돕는 행위가 될 수 있습니다.
- 오류에 대한 정보는 최소한의 정보만 담아야 하며, 구체적인 예외처리를 통해 사전에 방어하는 것이 좋습니다.
- 오류 상황에 대한 대응 부재
// 위험한 코드의 예
public String createUser(WebSession s) {
try{
String username = s.getParser().getParameter(username);
return username;
} catch(NullPointerException e) {
// TODO Auto-generated catch block
}
}
// 안전한 코드의 예
public String createUser(WebSession s) {
try{
String username = s.getParser().getParameter(username);
return username;
} catch(NullPointerException e) {
s.setMessage(e.getMessage());
return username;
}
}
5. 코드 오류
- 총 7개의 공격에 대한 시큐어 코딩 가이드가 있습니다.
- 개발자의 실수 및 지식 부족으로 인해 발생하는 오류 및 관리가 어려워질 수 있는 경우를 예방하기 위한 점검 항목에 대한 내용입니다.
- 시스템의 코드가 복잡하면 관리 및 유지보수, 가독성이 떨어지고, 이식성 또한 낮아지기며 안전성을 위협하는 여러 취약점들을 찾기 어려워질 가능성이 높습니다.
- 형변환 오류나 잘못된 자원 반환 또는 미반환 등이 해당됩니다.
※ 널 포인터 역참조(Null Pointer Dereference)
- 공격자가 의도적으로 널 값을 넣는 경우 발생하는 오류로 추후 공격 계획을 세우는데 도움이 될 수 있습니다.
// 위험한 코드의 예
public void test(HttpServletRequest request) {
String id = request.getParameter("id");
System.out.println(id);
}
// 안전한 코드의 예
public void test(HttpServletRequest request) {
String id = request.getParameter("id");
if(id != null) {
System.out.println(id);
} else {
System.out.println("id is null");
}
}
6. 캡슐화
- 총 8개의 공격에 대한 시큐어 코딩 가이드가 있습니다.
- 객체 및 필드의 은닉을 통해 인가된 데이터와 그렇지 않은 데이터를 구분해 허용되지 않은 사용자에게 데이터가 누출되는 것을 방지해야 합니다.
※ 삭제하지 않은 디버깅 코드
- 개발이 완료되면 개발 시 확인하기 위한 여러 정보 중 민감한 정보를 담고 있는 것이 있을 수 있기에 이 정보가 노출되지 않도록 해야 합니다.
※ 잘못된 세션으로 인한 데이터 노출
- 멀티 스레드 환경에서 전역 변수가 서로 다른 세션에서 데이터를 공유하지 않게 해야 합니다.
- 동시 접속 시 타이밍 이슈로 인해 1번 사용자가 2번 사용자의 정보를 보게 될 수 있습니다.
// 위험한 코드의 예
public class Test {
prate String name;
protected void testM(HttpServletRequest request) {
name = request.getParameter("name");
System.out.println("name ===> " + name);
}
}
// 안전한 코드의 예
public class Test {
protected void testM(HttpServletRequest request) {
String name = request.getParameter("name");
if(name == null || "".equals(name)) {
System.out.println("null 입니다.");
}
System.out.println("name ===> " + name);
}
}
7. API 오용
- 총 7개의 공격에 대한 시큐어 코딩 가이드가 있습니다.
- 취약점이 알려진 API의 사용은 보안상 심각한 위협요인이 될 수 있습니다.
※ DNS lookup에 의존한 보안 결정
- 공격자가 도메인명 엔트리를 속일 수 있기에 도메인명으로 보안결정을 하면 안 됩니다.
- IP주소를 이용해 인증처리 하는 것이 안전합니다.
※ equals()와 hashCode() 하나만 정의하는 경우
- a.equals(b) == true 인 경우 a.hashCode() == b.hashCoed() 여야 하며, 명확한 비교를 위해선 둘 다 구현하는 것이 좋습니다.
#. 평소 알면서도 지나갔던 것에 대한 내용도 있어 조금 더 신경 써야겠다는 생각이 듭니다.
#. 100% 안전한 코드는 없겠지만 100%에 가까운 코드를 만들기 위해 노력해야 할 것 같습니다.
#. 무심코 넘긴 코드가 어떤 칼날이 되어 되돌아올지 모르기에 항상 주의 깊게 살펴야 할 것 같습니다.
===========================================================
틀린 내용이 있거나 이견 있으시면 언제든 가감 없이 말씀 부탁드립니다!
참고 : 행정안전부 > 정보화 표준.지침 자료실 > 소프트웨어 개발보안(시큐어 코딩) 관련 가이드
===========================================================
'보안' 카테고리의 다른 글
[CDN] cdn.jsdelivr.net SSL 만료(부트스트랩 오류) (0) | 2024.05.03 |
---|---|
[보안] Jasypt를 이용한 민감정보 암호화 (0) | 2024.03.12 |
[보안] Replay Attack 정의 및 대응 (0) | 2024.01.16 |
[보안] 파일 업로드 시 취약점 사전 대응 방법(Java, Windows) (1) | 2023.11.30 |
[보안-Windows] 방화벽 포트 열기 (1) | 2023.11.27 |