시큐어코딩

개발보안 취약 사례 및 대응 방안 - 1

메오백 2024. 11. 24.

kt ds에서 진행하는 개발자를 위한 보안실무 교육을 이틀간 듣고 간단하게 정리해보고자 한다. 

클라이언트 기반 인증 우회 

url 직접 접근으로 인증 flow 우회 

공격자가 인증에 성공할 시 접근하는 url이 /member/success.php 안다면, 해당 url로 직접접근해서 인증을 우회하는 방식이다. 

인증 값 조작을 통한 인증 우회 

인증 모듈 결과를 클라이언트 영역에서 조작하는 공격 방식

예를 들어 임의의 sms 인증값을 입력하고 BurpSuite같은 웹 프록시 도구로 JS 코드를 조작(isAuth : falseisAuth : true로 조작하거나, 실패 응답코드를 성공 응답코드로 조작하는 등)하여 로그인에 성공한다.

응답 값에 인증번호 노출

sms 인증 번호가 js상에 노출되는 경우 휴대전화 없이 sms 인증에 성공한다. 

JS 인증 모듈 조작 

공격자가 계정 id, pw를 탈취한 상황에서 로그인 시 sms 인증을 요청할 때 인증 모듈이 js상에 있다면 공격자가 js를 조작해 임의의 인증코드를 입력해도 로그인에 성공한다. 

기능 에러로 인한 클라이언트기반 인증 우회 

브라우저상에서 탭을 2개 열어서 다른 인증정보 입력 시 타인 계좌를 결제수단으로 등록 가능한 경우 

조치방안

  • 로그인 sms 인증 모듈에서 가장 많은 클라이언트 인증 우회가 발견되므로 주의
  • 모든 인증 모듈은 server side에 구현, 인증 응답 값을 클라이언트로 전송하지 않을 것 
  • 로그인 계정 식별을 위한 코드는(sms 인증코드 등) 세션(server side의 HttpSession)에 저장
  • 단계별 인증 시 최종 단계에서 단계별 권한 모두 확인
    • 소액결제 시 중간단계인 본인인증 성공 여부를 마지막 단계에서 한번 더 확인  
@PostMapping("/sendSms")
public ResponseEntity<?> sendSmsAuthentication(@RequestParam String phoneNumber, HttpSession session) {
    String uniqueCode = generateUniqueCode(); // 랜덤 식별 코드 생성
    session.setAttribute("smsCode", uniqueCode); // 서버 세션에 저장

    sendSms(phoneNumber, uniqueCode); // 사용자 휴대폰으로 전송
    return ResponseEntity.ok("SMS sent successfully");
}

@PostMapping("/verifySms")
public ResponseEntity<?> verifySmsAuthentication(@RequestParam String code, HttpSession session) {
    String savedCode = (String) session.getAttribute("smsCode");

    if (savedCode != null && savedCode.equals(code)) {
        return ResponseEntity.ok("Authentication successful");
    }
    return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid authentication code");
}

스프링에서 server side 인증을 하는 예시를 확인해보자. sms 인증코드 값은 server side의 HttpSession 에 저장한다. JS에 노출되지 않으며 client side의 프록시 도구로 확인할 수 없다. 

클라이언트가 가지고 있는 값은 쿠키에 저장된 sessionId 뿐이다. 서버는 클라이언트의 Http 요청 쿠키에 포함된 sessionId로 세션을 식별해 smsCode 값을 비교해 인증을 완료한다. 

 

더보기
더보기

세션 

 

server side에서 세션이 처음으로 생성될 때 sessionId가 만들어진다. 

스프링을 예로 들면 request.getSession() 을 호출하거나 HttpSession을 컨트롤러의 파라미터로 전달받을 때 만들어진다.

Set-Cookie: SESSIONID=abc123def456ghi789; Path=/; HttpOnly; Secure; SameSite=Strict

 세션이 생성되면 HTTP 응답에 Set-Cookie 헤더값을 포함한다.

  • SESSIONID : 서버에서 생성한 고유의 세션 식별자로 서버에서 클라이언트의 세션을 식별하기 위해 사용한다. 
  • Path : 쿠키가 유효한 URL 경로를 지정한다.  
  • HttpOnly : client side(JS 등)에서 쿠키에 접근하지 못하게 한다. HttpOnly가 없으면 JS에서 document.cookie 로 접근할 수 있다. 공격을 방지하기 위해 민감한 정보를 저장할 때는 반드시 포함하는 것이 좋다. 
  • Secure : HTTPS 연결에서만 쿠키가 전송된다. 
  • Samesite=Strict : 쿠키가 동일 사이트 내 요청에만 전송되는 것으로 CSRF 공격 방지에 유용하다. 

 server side에서 위와 같이 응답하면 client side에서는 브라우저에 의해 sessionId가 자동으로 관리된다.  

GET /example HTTP/1.1
Host: example.com
Cookie: JSESSIONID=ABC123XYZ456

client side의 이후 요청에는 쿠키에 자동으로 sessionId 값을 포함된다. 

스프링 환경에서는 sessionId 확인이 자동으로 이루어진다. 

서버에서는 sessionId를 통해 클라이언트의 세션을 조회한다. 만약 세션이 유효하지 않다면(만료 또는 서버에서 의도적으로 세션 종료) 새 세션을 생성한다. 

 

브라우저 세션 

서버에도 세션이 있지만 브라우저에도 세션이 있다. 브라우저 세션은 브라우저의 탭에서 데이터를 저장하고 사용하는데 쓰인다. 각 브라우저 탭이 별도의 세션 저장소를 갖는다. 브라우저 탭을 닫으면 브라우저 세션 데이터가 삭제된다. 

브라우저 세션은 JS상에서 접근할 수 있어서 민감한 정보 저장에는 부적절하다.  

// 데이터 저장
sessionStorage.setItem('key', 'value');

// 데이터 읽기
const value = sessionStorage.getItem('key');

// 데이터 삭제
sessionStorage.removeItem('key');

// 모든 데이터 삭제
sessionStorage.clear();

 

두 용어를 혼동하지 않도록 하자. 

자동화 공격

무작위 대입 공격

무작위 대입 공격은 임계치 횟수가 설정되지 않은 인증 모듈에 무작위 문자 또는 값을 반복 대입해 인증 정보를 탈취하는 공격이다. 시간이 오래 걸리더라도 반드시 인증 정보를 탈취하는 공격 방식이다. 

예를 들어 이용권 번호를 1111111111111111 부터 9999999999999999 까지 전부 대입해보는 방식이다. 

Credential Stuffing 

사용자 로그인 정보, 개인 정보를 탈취한 후 다양한 서비스에 대입하는 공격 기법이다. 

예를 들어 티스토리 계정 정보를 탈취한 후 네이버, 구글, github 등 다양한 계정에 대입하는 것이다.

조치방안

CAPTCHA 적용 

  •  CAPTCHA 모듈 or Google reCAPTCHA v3 이상의 안전한 CAPTCHA 모듈 적용
  •  동일 CAPTCHA 코드는 재 사용이 불가능하도록 구현
  •  CAPTCHA 입력 오류 시에는 새로운 CAPTCHA 코드 갱신되도록 구현
  •  서버에서 CAPTCHA 코드 검증

AP 임계치 설정

  • 로그인, SMS, 이메일 인증에 대해 임계치 설정 

응답코드/문자열 통일 

  • 응답 코드/문자열을 통해 회원 존재 유/무를 파악할 수 없도록 로그인 성공/실패 응답코드/문자열을 통일

id가 일치하지 않습니다pw가 일치하지 않습니다 와 같은 응답 문자열 대신 id 혹은 pw가 일치하지 않습니다. 등으로 변경

비밀번호 RSA 암호화 

SSL은 중간자공격으로부터 안전하지 않기 때문에 비밀번호 등 중요 정보는 암호화 필수 적용

https://blog9909.tistory.com/70

 

https 취약점

https를 사용하면 안전하다고 생각해서 비밀번호 등을 암호화 하지 않는 경우가 있다. 하지만 https를 사용하더라도 중간자 공격에 의해 비밀번호가 탈취될 수 있다. https의 동작 대칭 키와 비대

blog9909.tistory.com

왜 http를 사용해도 암호화해야 하는지는 위 글을 참고하자.

파라미터 변조 

접근이 불가능한 파라미터 값을 조작해 접근해 타인 권한을 얻거나 정보를 열람하는 것이다.

예를 들어 /member/id=1 만 접근할 수 있어야 하는데 타인의 id인 /mebmer/id=10 으로 접근해 해당 회원의 개인정보를 열람하는 것이다. 

피해사례 

  • sms 인증 시 공격자 휴대전화로 파라미터 변경해 sms 인증 우회 
  • 결제 시 상품 금액 파라미터값 조작해 10원에 상품 구매 

조치방안

  • 파라미터 최소화, 기능 상 필요한 파라미터만 전달
  • 부득이하게 파라미터 사용 시에는 양방향 암호화 
  • 단계별 인증 시 최종 단계에서 파라미터 재검증 
    • 결제 모듈 실행 전 서버로 결제 정보 전송 (금액, 상품코드, 할인, 쿠폰 등)
    • 결제 처리된 금액과 서버에 저장된 결제 정보 동일한지 확인해 결제 처리
  • 서버 세션에 로그인 권한 식별할 수 있는 확인용 정보 저장 

url 강제 접속 

url에 접근 권한이 없는 사용자가 직접 url을 입력해 접근하는 것이다. 

피해사례

  • 일반 사용자가 카드 정보 확인 url 직접 입력해 관리자만 확인할 수 있는 카드 정보 확인 

조치방안 

  • 접근 권한이 제어되어야 하는 모든 페이지에 접근 제어 필수 적용 
  • 권한 관리 공통 모듈 적용 
  • 세션에 접근 권한 저장

디렉터리 인덱싱 

개발 과정의 편의를 위해 웹 디렉터리를 웹 브라우저에 노출시키는 것으로 소스코드, 웹 서버 내 개인정보 등이 노출될 수 있다. 

조치방안

웹 서버(apache 등) 설정으로 인덱싱 제안

 

불필요한 Method 허용 

GET, POST 외 불필요한 HTTP Method는 공격자에게 악용될 수 있다. 

PUT, DELETE의 경우 웹 디렉터리에 파일을 생성하거나 삭제할 수 있다. 

  • TRACE 
    • TRACE 로 요청한 헤더 정보가 응답 값에 노출된다.
    • Cross Site Tracing 공격에 취약하다
  • OPTIONS
    • 서버에서 지원하는 HTTP Method를 확인해서 2차 공격에 악용 
  • PUT, DELETE
    • 웹 디렉터리 파일을 생성/삭제할 수 있다. 
    • 악성 파일 생성, 정상적인 페이지 제거에 사용 

조치 방안 

웹 서버 설정 파일에서 사용하지 않는 Method 제한 (GET, POST 외에 제한하는 것이 좋다)

 

다음 포스팅에서는 이어서 SQL injection에 대해 알아보겠다. 

 

출처

개발자를 위한 보안 실무 (KT DS University)

'시큐어코딩' 카테고리의 다른 글

개발보안 취약 사례 및 대응방안 - 2  (1) 2024.12.04
https 취약점  (0) 2024.12.01

댓글