
CVE-2022-30600에 대한 개념 증명
이 저장소에는 CVE-2022-30600을 악용하는 개념 증명을 위한 2가지 구현이 포함되어 있습니다.
CVE-2022-30600은 공격자가 Moodle 웹앱 내에서 계정 잠금 임계값을 우회할 수 있게 해주는 보안 취약점입니다.
NVD 데이터베이스(https://nvd.nist.gov/vuln/detail/CVE-2022-30600)에 설명된 대로, 아래 버전은 이 익스플로잇에 취약한 것으로 알려져 있습니다.
3.9 - 3.9.13
3.10 - 3.10.10
3.11 - 3.11.6
이 취약점을 패치하는 데 사용된 커밋에 설명된 대로, 문제는 데이터베이스에서 login_failed_count 값을 액세스하고 증가시키는 데 사용되는 로직에 있습니다.
2개 이상의 동시 로그인 요청이 발생하면 Moodle 웹앱이 애플리케이션 내에서 로그인 값을 올바르게 확인하고 업데이트하지 못할 수 있습니다. 그 결과 2회 이상의 로그인 실패가 단 1회의 로그인 실패로만 집계됩니다.
이를 더 잘 이해하기 위해, 아래 다이어그램은 클라이언트, 웹앱, 데이터베이스 관점에서 실패한 로그인 요청의 개략적인 분석입니다.
sequenceDiagram
participant C as Client
participant W as Webapp
participant D as Database
C->>W: Login Request
W->>D: Requests failed_login_attempt
D->>W: failed_login_attempt = 0
W->>W: local failed_login_attempt = 0
W->>W: local failed_login_attempt = 1
W->>D: failed_login_attempt = 1
W->>C: Login Failed
그 결과 데이터베이스의 failed_login_attempt 값은 정확하며, 이후의 로그인 시도는 값을 올바르게 업데이트합니다.
공격자가 여러 개의 동시 로그인 요청을 보내면 다음과 같은 문제가 발생합니다.
sequenceDiagram
participant C as Client
participant W as Webapp
participant D as Database
C->>W: Login Request (session 1)
C->>W: Login Request (session 2)
W->>D: Requests failed_login_attempt (session 1)
W->>D: Requests failed_login_attempt (session 2)
D->>W: failed_login_attempt = 0 (session 1)
D->>W: failed_login_attempt = 0 (session 2)
W->>W: local failed_login_attempt = 0 (session 1)
W->>W: local failed_login_attempt = 0 (session 2)
W->>W: local failed_login_attempt = 1 (session 1)
W->>W: local failed_login_attempt = 1 (session 2)
W->>D: failed_login_attempt = 1 (session 1)
W->>D: failed_login_attempt = 1 (session 2)
W->>C: Login Failed (session 1)
W->>C: Login Failed (session 2)
이 상호작용의 결과는 2번의 실패한 로그인 요청이 발생했음에도 불구하고 failed_login_attempt 데이터베이스 값이 1만 증가한다는 것입니다. 이는 수백 개의 요청으로 확장될 수 있으며, 제한은 클라이언트가 만들 수 있는 동시 요청 수와 웹 서버가 동시에 처리할 수 있는 요청 수에 의해 결정됩니다.
또한, 공격자가 여러 클라이언트(예: 봇넷)에 접근할 수 있고 이러한 요청이 이루어지는 시간을 동기화할 수 있다면, 하나의 클라이언트를 사용할 때의 한계를 극복하고 공격을 완화하기 더 어렵게 만들 수 있습니다.
poc.py는 이 공격의 Python3 구현입니다. 동시 요청을 수행하기 위해 스레드를 사용합니다. 이 개념 증명이 작동하지만, Python3에 존재하는 GIL(Global Interpreter Lock)은 이러한 상황에서 여러 스레드를 사용하는 이점을 저해합니다. 단일 클라이언트에서 공격을 수행할 때 더 잘 작동하는 C++ 구현을 강력히 권장합니다.
poc.py [-h] -u USERNAME -url TARGET -w WORDLIST -t THREADS [-a ATTEMPTS] [-d DELAY]
옵션:
-h, --help
도움말 메시지를 표시합니다
-u USERNAME, --username USERNAME
공격 대상 계정의 사용자 이름입니다
-url TARGET, --target TARGET
공격 대상 Moodle 웹앱의 기본 URL입니다
-w WORDLIST, --wordlist WORDLIST
사용할 워드리스트 파일의 경로입니다
-t THREADS, --threads THREADS
각 시도에 대해 생성되는 스레드 수입니다
-a ATTEMPTS, --attempts ATTEMPTS
수행하려는 시도 횟수입니다. 기본값은 1입니다.
-d DELAY, --delay DELAY
각 시도 사이의 지연 시간(초)입니다. 기본값은 2입니다.
python3 poc.py -u admin -url https://moodle/ -w /usr/share/wordlists/rockyou.txt -t 15 -a 8
대상: https://moodle/
계정 사용자 이름: admin
워드리스트: /usr/share/wordlists/rockyou.txt
스레드: 각 시도에서 15개의 로그인 요청이 이루어집니다.
시도: 공격이 총 8회 반복됩니다.
이 예시에서는 총 120(8 * 15)개의 로그인 요청이 이루어집니다. 각 시도 사이에는 2초의 지연 시간이 있습니다.
poc.cpp는 공격의 C++ 구현이며, 공격을 수행하기 위해 curl 라이브러리를 사용합니다. 따라서 애플리케이션을 컴파일하려면 몇 가지 컴파일러 플래그가 필요합니다. 전반적으로 이 구현은 Python3 버전보다 성능이 우수합니다. 스레드가 클라이언트 장치의 모든 코어를 사용할 수 있어 더 짧은 시간에 더 많은 동시 연결을 허용하기 때문입니다. 따라서 익스플로잇이 더 일관되게 작동할 수 있습니다.
g++ poc.cpp -o poc -lcurl
사용법:
poc [OPTION...]
-a, --attempts
공격이 수행되는 횟수입니다.
-t, --threads
각 시도에서 사용할 스레드 수입니다.
-n, --username
공격 대상 계정의 사용자 이름입니다.
-u, --URL
Moodle 웹앱의 기본 URL입니다.
-d, --delay
시도 간 지연 시간입니다. 기본값은 5입니다.
-v, --version
버전을 표시합니다.
-h, --help
도움말 메시지를 표시합니다.
-w, --wordlist arg
비밀번호 워드리스트입니다.
./poc -w /usr/share/wordlists/rockyou.txt -u https://moodle/ -n admin -a 3 -t 5 -d 2
워드리스트: /usr/share/wordlists/rockyou.txt
URL: https://moodle/
계정 사용자 이름: admin
시도: 3회의 시도가 이루어집니다.
스레드: 각 시도에서 5개의 스레드가 사용됩니다.
지연: 각 시도 사이에 2초의 지연 시간이 있습니다.
이 스크립트를 개발, 테스트 및 디버깅하기 위해 가상 머신을 생성했습니다. 이 가상 머신은 다음 소프트웨어 및 버전을 사용했습니다.
Moodle 3.9.0 PHP 7.2.34 MySQL 8.0.30 Ubuntu 5.15.0-41-generic Apache 2.4.52
저는 제 소스 코드가 불법 활동에 사용되는 것을 묵인하지 않습니다.