yon11b

[SK 쉴더스 루키즈] Insecure Design(tampering 실습) 본문

보안/SK 쉴더스 루키즈

[SK 쉴더스 루키즈] Insecure Design(tampering 실습)

yon11b 2026. 5. 7. 23:52
반응형

Insecure Design

설계 단계에서 안전하지 않게 디자인 해서 발생하는 모든 취약점을 의미한다.

(안전하지 않은 구현과 반대)

 

안전하지 않은 설계의 대표적인 사례들

1. 위협 모델링의 부재

2. 결함이 있는 비즈니스 로직

3. 속도 제한의 부재

4. 신뢰할 수 없는 클라이언트 제어

 

안전하게 설계하는 방법

1. 보안 개발 생명주기(Secure SDLC) 도입

DevSecOps로 보안까지 자동화하기

https://www.dynatrace.com/news/blog/devsecops-automation-improves-application-security/

요구사항 → 설계 → 개발(코딩) → 빌드 → 테스트 → 배포 → 운영
                    ↓           ↓        ↓
                  SAST         SCA     DAST
                  SCA                  IAST

 

 

애플리케이션 보안 테스팅 도구(테스트 과정에서 쓰일 도구들)

약자 풀네임 한글 시점 방식
SAST Static Application Security Testing 정적 분석 개발 단계 (코딩 중) 소스코드를 실행하지 않고 분석
DAST Dynamic Application Security Testing 동적 분석 테스트/운영 단계 실행 중인 앱에 실제 공격 시뮬레이션 (블랙박스)
IAST Interactive Application Security Testing 대화형 분석 테스트 단계 앱 내부에 에이전트 삽입 → 실행 중 코드 흐름 추적 (SAST+DAST 혼합)
SCA Software Composition Analysis 소프트웨어 구성 분석 전 단계 오픈소스/서드파티 라이브러리의 알려진 취약점(CVE) 검사

 

 

2. 위협 모델링 생활화(STRIDE, DREAD)

STRIDE

위협 찾기

1. Spoofing(신원도용)

안전하지 않은 설계

- 서버 간 통신 시,상호 인증 절차를 설계에 포함하지 않은 경우

- MFA 미적용

 

2. Tampering(데이터 변조)

공격자가 시스템을 통과하는 데이터나 저장된 데이터를 악의적으로 변경

안전하지 않은 설계

- 중요 데이터(예: 거래 금액, 사용자 권한) 전송 시, 데이터의 무결성을 검증하는 로직(예: 해시, 전자서명)을 
설계하지 않은 경우

 

3. Repudiation(부인방지)

안전하지 않은 설계

- 사용자의 행위에 대한 로그를 기록하도록 설계하지 않은 경우

 

4. Information Disclosure(정보 노출)

허가되지 않은 사용자가 민감한 정보에 접근

안전하지 않은 설계

- 에러 발생 시 로그를 사용자에게 그대로 노출

- URL파라미터를 통해 민감한 정보가 노출

- DB에 평문 저장

 

5. Denial of Service(서비스 거부)

안전하지 않은 설계

- 파일 업로드 크기, API요청 횟수 등을 지정해 놓지 않은 경우

 

6. Elevation of Privilege(권한 상승)

안전하지 않은 설계

- 권한 분리 x

- 최소 권한 원칙 설계 x 경우

 

DREAD

찾아낸 위협의 위험도 평가하기

 

1. Damage(손상 가능성)

위협이 성공했을 때 발생하는 피해의 심각성

- 데이터 손실, 변조, 유출 규모

- 기업 이미지 손상

- 금전적 손실

- 법적 위반 가능성

등등..

 

2. Reproducibility(재현 가능성)

같은 공격을 얼마나 쉽게, 얼마나 일관되게 똑같이 재현할 수 있는지 정도

- 절차가 복잡한가?

- 매번 동일한 결과가 나오는가?

- 공격에 필요한 조건이 자주 발생하는가?

예시

- 클릭 몇 번으로 가능 => 높은 점수

- 특정 환경에서만 발생 => 낮은 점수


3. Exploitability(악용 가능성)

공격자가 성공적으로 공격하기 위해 필요한 노력, 기술, 자원의 정도

- 전문 지식이 필요한가?

- 공격 도구가 쉽게 사용 가능한가?

예시

- 오래된 라이브러리를 이용하는 공격 => 높은 점수

- 제로데이 => 낮은 점수


4. Affectability(영향 받는 사용자 수)

- 전체 사용자가 영향을 받는가?

- 내부, 외부 시스템 다 영향을 받는가?

- 전체 서비스가 중단되는가? 일부만 중단되는가?


5. Discoverability(발견 가능성)

- 취약점이 공개적으로 알려져 있는가?

- 시스템 설계가 공개되어 있는가?

- 자동화된 스캔 도구로 쉽게 찾을 수 있는가?

 

예시

- HTTP 헤더에 민감 정보가 포함되어 쉽게 발견되는 경우 => 높은 점수

- 매우 깊이 숨겨진 코드 로직에 있는 취약점 => 낮은 점수

 

DREAD 점수 활용

- 가장 높은 점수를 받은 위협부터 순서대로 보안 개선 작업을 진행 가능

- 특정 위협에 대한 주관적인 느낌이 아닌, 객관적인 척도를 제공하여 팀 내에서 위협 우선순위에 대한 합의를 도출하는 데 큰 도움이 됨

 

NodeGoat Insecure Design 실습: Tampering

 

Learning Resources 를 클릭하면 칸아카데미 사이트로 리다이렉트 된다.

 

 

Learning Resources 코드

    // Handle redirect for learning resources link
    app.get("/learn", isLoggedIn, (req, res) => {
        // Insecure way to handle redirects by taking redirect url from query string
        return res.redirect(req.query.url);
    });

 

뭐가 문제일까?

그냥 모든 페이지를 다 리다이렉트함 → 이상한 사이트를 입력하면 거기로 보내져서 취약함.

 

중간에 검증 로직을 추가해준다.

화이트리스트 기반으로 허용된 것만 redirect 해주고 나머지는 다 기본 페이지로 리다이렉트 해준다.

    app.get("/learn", isLoggedIn, (req, res) => {
        const resourceId = req.query.url; // "1", "2", "3" 등의 값을 받음
        let redirectUrl;

        switch (resourceId) {
            case "1":
                // 1번 리소스 페이지
                redirectUrl = "https://www.khanacademy.org/economics-finance-domain/core-finance/investment-vehicles-tutorial/ira-401ks/v/traditional-iras";
                break;
            case "2":
                // 2번 허용된 리소스 페이지
                redirectUrl = "https://naver.com";
                break;
            case "3":
                // 3번 허용된 파트너사 문서 페이지 (외부지만 허용된 URL)
                redirectUrl = "https://google.com";
                break;
            default:
                // "1", "2", "3" 이외의 값이거나 id 파라미터가 없는 경우
                // 안전한 디폴트 페이지로 보냅니다.
                redirectUrl = "https://www.khanacademy.org/economics-finance-domain/core-finance/investment-vehicles-tutorial/ira-401ks/v/traditional-iras";
                break;
        }

        return res.redirect(redirectUrl);
    });

 

728x90