SW개발보안 관련 취약점
오픈소스(OSS) 취약점
현대 소프트웨어의 80% 이상은 오픈소스 코드로 구성되어 있다. 이로 인해 다음과 같은 보안 문제가 자주 발생한다. 최근에는 과학기술정보통신부, 국가정보원, 디지털플랫폼정부위원회가 협력하여 'SW 공급망 보안 가이드라인 1.0'을 배포한 바 있다.
참고: SW 공급망 보안 가이드라인
KISA 한국인터넷진흥원
안녕하세요. 과학기술정보통신부(한국인터넷진흥원), 국가정보원, 디지털플랫폼정부위원회가 합동으로 '소프트웨어(SW) 공급망 보안 가이드라인 1.0'을 마련하였으니 업무에 참고하시기 바랍니
www.kisa.or.kr
1. 방치된 오픈소스 사용
보안 패치가 적용되지 않은 채 오래된 오픈소스를 사용하는 경우, 이미 알려진 취약점이 그대로 노출될 수 있다. 따라서 오픈소스의 버전 관리와 취약점 확인이 중요하다.
2. 공급망 해킹
소프트웨어를 제공하는 공급업체가 해킹을 당하면서, 그들이 배포하는 제품이나 업데이트 파일에 악성코드가 삽입되고 이를 사용하는 협력사까지 감염되는 방식이다.
대표 사례: 솔라윈즈(SolarWinds) 해킹 사태
- 해커가 SolarWinds의 업데이트 서버를 침입하였다.
- 정상 소프트웨어 업데이트 파일에 트로이 목마를 삽입하였다.
- 미국 정부기관을 포함해 약 18,000개 조직이 감염되었다.
이러한 사건을 계기로 공급망 보안의 중요성이 강조되었으며, 이에 대응하기 위한 가이드라인이 마련되었다.
3. 웹 프레임워크 및 플러그인의 보안 취약점
개발의 편의성을 높이기 위해 사용하는 웹 프레임워크나 플러그인에서도 다양한 보안 취약점이 발견되고 있다.
예를 들어, 스프링 프레임워크(Spring Framework)에서는 최근 4년간 다음과 같은 보안 약점이 지속적으로 보고되고 있다.
- CSRF (Cross-Site Request Forgery)
- XSS (Cross-Site Scripting)
- 역직렬화(Deserialization) 취약점
역직렬화 취약점 예시 (Spring + Jackson)
ObjectMapper mapper = new ObjectMapper();
Object obj = mapper.readValue(jsonInput, Object.class); // jsonInput이 악성이라면 원격 코드 실행 가능성이 있다
4. IoT 보안 위협
사물인터넷(IoT) 기기의 보안이 미흡할 경우 해커의 원격 제어나 디도스(DDoS) 공격의 도구로 악용될 수 있다.
펌웨어의 정기적인 업데이트와 인증 절차 강화가 필요하다.
개발 생명주기 단계별 보안 적용 방안
보안은 개발 완료 후에 적용하는 것이 아니라, 기획부터 유지보수까지 모든 단계에서 고려되어야 한다.
1. 분석 단계
- 화면 정의서 등 초기 산출물을 바탕으로 잠재적인 보안 취약점을 미리 파악한다.
2. 설계 단계
- 인증, 권한 관리, 데이터 암호화 등 보안 요구사항을 명확히 설계에 반영한다.
3. 구현 단계
- 보안 코딩 가이드를 준수하여 코드를 작성한다.
- 단위 테스트를 통해 보안 취약점을 조기에 발견한다.
- Java의 checkpoint 기능 등을 활용하여 문제 코드를 사전에 제거한다.
안전하지 않은 코드 예시
try {
FileReader reader = new FileReader("config.txt");
} catch (IOException e) {
System.err.print(e.getMessage()); // 민감한 내부 경로나 예외 메시지가 노출될 수 있다
}
안전한 코드 예시
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FileLoader {
private static final Logger logger = LoggerFactory.getLogger(FileLoader.class);
public void loadFile() {
try {
FileReader reader = new FileReader("config.txt");
} catch (IOException e) {
logger.error("ERROR-01: 파일 열기 실패", e);
}
}
}
발견된 취약점 사례 및 시큐어 코딩
1. SQL Injection (SQL 인젝션)
SQL Injection은 사용자 입력값을 검증하지 않고 SQL 쿼리에 직접 삽입하는 경우, 공격자가 악의적인 SQL 구문을 삽입하여 데이터베이스를 조작하거나 민감 정보를 탈취하는 공격이다.
취약한 코드 예시 (Java JDBC)
String userId = request.getParameter("userId");
String query = "SELECT * FROM users WHERE user_id = '" + userId + "'";
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(query);
위 코드는 userId에 ' OR '1'='1 과 같은 값을 입력하면 모든 사용자 정보가 노출될 수 있다.
시큐어 코딩 예시 (PreparedStatement 사용)
String userId = request.getParameter("userId");
String query = "SELECT * FROM users WHERE user_id = ?";
PreparedStatement pstmt = connection.prepareStatement(query);
pstmt.setString(1, userId);
ResultSet rs = pstmt.executeQuery();
PreparedStatement를 사용하면 SQL 구문과 사용자 입력이 분리되어 SQL Injection을 방지할 수 있다.
2. XSS (Cross-Site Scripting)
XSS는 공격자가 웹페이지에 악의적인 스크립트를 삽입하여 사용자의 브라우저에서 실행시키는 공격이다. 쿠키 탈취, 세션 하이재킹 등의 피해로 이어질 수 있다.
취약한 코드 예시 (JSP)
<% String userInput = request.getParameter("comment"); %>
<p><%= userInput %></p>
comment에 <script>alert('XSS')</script> 입력 시, 페이지에서 자바스크립트가 실행된다.
시큐어 코딩 예시 (JSP + 출력값 이스케이프 처리)
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<% String userInput = request.getParameter("comment"); %>
<c:out value="${fn:escapeXml(userInput)}"/>
fn:escapeXml() 함수는 HTML 태그 및 특수문자를 이스케이프 처리하여, 스크립트 실행을 방지한다.