'll Hacker

4주차 강의. 모의해킹 대비 OWASP top 10으로 뽀개기 심화스터디 본문

Hacking/EVI$ION(교내 해킹동아리)

4주차 강의. 모의해킹 대비 OWASP top 10으로 뽀개기 심화스터디

씨이오가 되자 2025. 5. 24. 23:25
Contents
728x90

 A04 : Insecure Design

설계 단계에서 필요한 보안 제어가 완전히 구현되지 않거나 비효율적으로 구현된 경우를 말한다. 설계 결함으로 인해 이후 개발 단계에서 여러 취약점이 발생할 가능성이 생긴다. 이러한 설계 결함은 소프트웨어 시스템이 적절한 보안 방어 장치를 갖추지 못하도록 만들 수 있으며, 그 결과 시스템이 특정 공격에 취약해질 수 있다.

 

안전하지 않은 설계 vs 안전하지 않은 구현?

설계 결함은 소프트웨어 시스템의 보안 요구사항이 처음부터 잘못 정의되었거나 아예 반영되지 않았을 때 발생한다. 비즈니스 리스크 평가가 제대로 이루어지지 않아서 발생한다. 이거는 수정할 수가 없다

구현 결함은 설계 자체는 올바르게 되었지만 실제 코드를 작성하는 과정에서 오류가 발생하는 것을 의미한다. 잘못된 코드 작성으로 인해 보안 취약점이 발생할 수 있다. 하지만, 설계결함과 달리 수정할 수 있는 부분이다.

 

따라서 설계 결함이 일어나지 않게 주의해야한다.

 

그렇다면 이거를 어떻게 해결하는가? - 보안이 고려된 애플리케이션 개발을 위한 요구사항 수집 및 자원 관리를 해야된다.

애플리케이션이 어떤 역할을 해야하는지 업무팀과 협의하여 비즈니스 요구사항을 수집해야한다. 또한, 보안 요구사항도 포함해야한다. 기밀성, 무결성, 가용성, 진위성 등이 중요하다.

  • 기밀성(confidentiality) : 민감한 데이터는 무단 접근이 안되도록 보호해야한다.
  • 무결성 (Integrity) : 데이터가 변조되지 않도록 보장해야한다.
  • 가용성 (Availability) : 시스템이 항상 접근 가능하도록 유지해야한다.
  • 진위성 (Authenticity) : 사용자와 데이터가 진짜임을 검증할 수 있어야 한다.

또한, 애플리케이션의 비즈니스 로직이 어떻게 작동해야하는지 명확히 정의해야한다. 멀티테넌시 환경이라면 서로 다른 고객의 데이터가 섞이지 않도록 분리해야한다.

 

멀티테넌시 환경?⏬

더보기
더보기

하나의 소프트웨어 시스템(애플리케이션 또는 서비스)을 여러 사용자(조직 또는 고객)가 동시에 공유해서 사용하는 구조이다.

또한 기술적 요구사항을 정리해야한다.  기능적 요구사항으로는 사용자는 로그인할 수 있어야한다, 2단계 인증을 제공한다.를 예로 들 수 있고, 비기능적 보안 요구사항은 비밀번호는 최소 12자 이상, TLS 1.2 이상 사용, 로그인 실패 5회 시 계정 잠금 등이 있다.

 

애플리케이션 전체 수명 주기(설계, 개발, 테스트, 운영) 동안 필요한 예산을 계획하고 협의해야한다. 보안활동(침투 테스트, 코드 리뷰, 모의해킹)도 예산에 반드시 포함해야한다.

 

공격 시나리오

#1. 인증 질문 기반의 계정 복구 (Credential Recovery via Q&A)

 

비밀번호 찾기 과정에서 질문과 답변(예: 당신의 첫 애완동물 이름은?) 을 사용하는 방식은 보안에 취약하다. 이 방식은 NIST 800-63b, OWASP ASVS, OWASP Top 10에서 사용금지되어 있다. QnA 방식은 제거하고 이메일 인증이나, OTP 인증, FIDO2 같은 다중인증으로 대체한다.

 

#2. 영화관 단체 예약 악용

 

영화관 예매 시스템에서는 15명 이상 단체 예약 시 보증금이 필요하다. 하지만, 시스템 논리를 역이용하여 보증금없이 수백 좌석(600석) 예약을 시도하는 공격자가 있을 수 있다.

단 몇번의 요청으로 전국 극장 600석을 동시에 점유함으로써 고객이 영화 예매를 못하게 하고, 영화관 측 수익 손실을 유발하게 만들 수 있다. 따라서 예약 수량 제한 로직을 명확히 구현하고, 갑자기 몇백, 몇천석 요청 시 알림을 보내는 탐지 시스템을 구현한다던가, 예약 취소율 높은 사용자를 차단하는 로직을 구현한다.

 

#3. 봇(스크립트)을 이용한 제품 사재기

 

전자상거래 사이트에서 고성능 그래픽카드와 같은 제품이 입고되자마자 봇이 빠르게 구매하여 실사용자가 구매하지 못하는 문제가 발생할 수 있다. 리셀러가 사재기하여 경매 사이트에서 고가로 판매하는 경우가 있었고, 고객들은 구매를 실패하여 실망감으로 브랜드 이미지를 악화시키고, 기업 입장에서도 신뢰도 하락하고 언론에 부정적 기사가 노출할 수도 있다. 봇 탐지 및 방어 로직 필요하다. 비정상적인 속도를 감지해서 차단시키고, CAPTCHA, Bot Behavior 분석, 구매열 대기열 시스템을 만든다. 계정당 수량 제한, 휴먼 인증을 하여 해결한다.

 

* CAPTCHA는 사람과 봇을 구분하기 위한 자동 테스트이다. 


주목할만한 CWE는 CWE-209, CWE-256, CWE-501, CWE-522 이 있다. 

CWE-209 : Generation of Error Message Containing Sensitive Information

민감한 정보가 포함된 오류 메시지 생성한다. 애플리케이션이 오류 발생 시 시스템 정보, 경로, 쿼리, 스택 트레이스, DB 오류 등 민감한 정보를 포함한 오류 메시지를 클라이언트에 보여주는 경우가 있다. 

try:
    cursor.execute("SELECT * FROM users WHERE id = %s" % user_input)
except Exception as e:
    print(e)

 

e가 DB 연결 오류라면 DB 이름, 테이블 구조, 경로가 노출될 수 있다.

공격자가 내부구조, DB 정보, 기술 스택 등을 알아내어 추가적인 공격에 활용할 수 있다. 그래서 사용자에게는 일반적인 오류 메시지만 제공하여 "알 수 없는 오류가 발생했습니다. 고객센터에 문의하세요" 상세한 오류는 서버 로그에만 기록하게 구현한다.


CWE-256: Unprotected Storage of Credentials

자격 증명을 안전하지 않게 저장한다. 비밀번호, API 키, 토큰 등의 자격 증명을 평문으로 저장하거나 암호화하지 않고 노출된 방식으로 저장하는 경우이다.

Properties prop = new Properties();
prop.load(new FileInputStream("config.properties"));
String password = prop.getProperty("password");
DriverManager.getConnection(url, usr, password);

 

위 코드는 정상적으로 작동한다. config.properties라는 설정 파일에서 password 값을 읽어서, 이를 이용해 데이터베이스에 연결한다. config.properties 파일에 비밀번호가 평문으로 저장되어 있다. 이 파일에 접근할 수 있는 악의적인 내부 직원이 있다면, 파일을 열어서 비밀번호를 그대로 확인할 수 있고, 해당 비밀번호를 이용해 시스템에 무단 접근할 수 있다.

따라서 민가만 정보는 평문으로 저장하지 말고, 안전한 방식으로 관리해야한다. 예를 들어서 환경변수로 분리한다던가, 암호화된 자격 증명 저장소를 사용한다던가, 암호화된 파일과 복호화 키를 별도로 관리해야한다.

 


CWE-501 : Trust Boundary Violation

신뢰 경계를 무시한 데이터 전달 또는 처리이다. 외부에서 들어오는 데이터(=비신뢰 영역)를 내부 신뢰 영역에 적절한 검증없이 넘기거나 처리하는 경우 발생한다.

 

사용자가 보낸 HTTP 요청에서 username 파라미터를 받아서, 세션에 저장하는 코드이다.

usrname = request.getParameter("usrname");
if (session.getAttribute(ATTR_USR) == null) {
    session.setAttribute(ATTR_USR, usrname);
}
usrname = request.Item("usrname");
if (session.Item(ATTR_USR) == null) {
    session.Add(ATTR_USR, usrname);
}

 

사용자가 인증됐는지 확인하기 전에, 사용자가 보낸 값을 세션에 저장한다. 즉, 외부에서 온 사용자 입력값을 신뢰하고, 이를 바로 내부의 신뢰된 세션 객체에 저장하는 행위이다. 

 

따라서 이 CWE는 인증 우회, 권한 상승, 명령어 인젝션 등의 심각한 보안 문제로 이어질 수 있다.

 

항상 입력값 검증 및 필터링이 필요하며, 신뢰 경계 통과 시 명시적인 검증 로직 및 제어흐름을 구현해야한다. 사용자 세션, 역할, 권한은 서버 측에서 독립적으로 검증해야한다.


CWE-522 : Insufficiently Protected Credentials

전송 중인 자격 증명이 충분히 보호되지 않는다. 사용자 자격 증명(로그인 정보, 인증 토큰 등)을 암호화되지 않은 채널(http 등)로 전송하거나, 적절한 보호 조치없이 노출하는 경우이다. 

 

$user = $_GET['user'];
$pass = $_GET['pass'];
$checkpass = $_GET['checkpass'];
if ($pass == $checkpass) {
  SetUserPassword($user, $pass);
}

단순히 사용자 이름과 비밀번호를 GET 파라미터로 받아, 두 비밀번호가 일치하면 변경한다. 

요청을 보낸 사용자가 실제 해당 계정의 사용자인지 검증하지 않는다. 인증 절차없이 누구나 user=admin으로 요청하면 관리자 비밀번호를 변경할 수 있다. 

 

$user = $_GET['user'];
$pass = $_GET['pass'];
$checkpass = $_GET['checkpass'];
if ($pass == $checkpass) {
  SetUserPassword($user, $pass);
}

설정 파일(config.properties)에 비밀번호가 평문으로 저장되어있다. 내부 직원이 이 파일을 읽으면 DB 접속 정보가 유출된다.

 

String password = regKey.GetValue(passKey).toString();
NetworkCredential netCred = new NetworkCredential(username, password, domain);

레지스트리에 비밀번호를 보호없이 저장한다. 시스템에 접근가능한 내부자에게 비밀번호가 노출된다. 

 

strcmp(compress(password), compressed_password)
passwd.Equals(compress(password), compressed_password)

압축 알고리즘은 복호화가 가능한 방식이다. 해시가 아닌 압축을 사용하면 저장된 비밀번호 복원가능하다. 반드시 SHA-256, bcrypt, PBKDF2, Argorn2 같은 일방향 해시 알고리즘을 사용한다. 비밀번호 비교는 hash(input) == stored_hash 방식으로 해야한다.

 

webapp.ldap.username=secretUsername
webapp.ldap.password=secretPassword
<connectionStrings>
  <add name="..." connectionString="uid=db2admin; pwd=password;" />
</connectionStrings>

설정 파일에 사용자 이름과 비밀번호가 평문으로 포함된다. 서버 내부 권한이 있는 사람 누구나 읽을 수 있다. 암호화된 저장소 사용한다. .NET의 경우, web.config에서 Protected Configuration Provider로 암호화 가능하다.

 


사용자 입력 검증 기본 원칙

  1. 화이트리스트 : 허용할 값만 명시
  2. 길이 제한 : 입력값의 최대 길이를 제한
  3. 정규표현식 사용 : 입력 포맷을 검증한다
  4. 입력과 출력 분리 : HTML/SQL 등에서 이스케이프가 필수이다.
  5. 서버 측 검증 필수 : 프론트앤드에서 검증하더라도, 백엔드에서 반드시 다시 확인해야한다.

보안 입력 검증 라이브러리 

Java javax.validation (Hibernate Validator)
Python WTForms, Cerberus, Pydantic
JavaScript validator.js, Yup, zod
PHP filter_var() 내장함수
.NET DataAnnotations, FluentValidation
728x90