- 교육, 의료, 쇼핑, 언론, 금융 등 국내 사이트 30여 곳 해킹 피해 확인 - 사용자 개인정보와 내부 DB가 대거 유출되었으며, 피해 규모는 총 11만건 이상의 민감정보로 추정
내용
- 오아시스 시큐리티, 최소 30개 이상의 국내 사이트에서 정보 유출 및 시스템 권한 탈취가 발생 > 공격자가 국내 약 100여 개 웹사이트를 대상으로 침투 시도를 진행했으며, 최소 30개 이상의 사이트에서 피해 발생 > 공격 대상은 온라인 쇼핑몰, 채용 포털, 교육 기관, 의료 서비스, 보험 비교 플랫폼, 언론사 등 매우 광범위 > 피해 사이트 중 일부는 국비 지원 교육기관, 어린이집 연합회 등 일상생활과 밀접한 정보들이 다수 포함 > 범용 해킹 도구뿐 아니라 각 웹사이트 특성을 분석해 제작한 맞춤형 악성코드가 활용 > 고도로 정밀하게 준비된 국내 표적 공격으로, 웹사이트 구조와 보안 취약점을 정밀하게 파악하고 있던 것으로 추정
> 피해 규모 ⒜ 국비지원 교육 정보 사이트 : 약 4만 7천여 건의 개인정보 ⒝ 명품 쇼핑 플랫폼 : 약 3만 8천여 건의 개인정보 ⒞ 구인구직 플랫폼 및 학원 : 수천~수만 건의 정보 유출 ※ 현재까지 확인된 개인정보는 11만건 이상으로, 2차 범죄로 악용될 가능성이 높음 ※ 공격 발생 직후 즉각 유관기관에 관련 사실 전달 및 후속 조치를 요
기타
- 중소 규모의 웹사이트 또한 고도화된 표적 공격의 대상이 되고 있음을 강조 > 중소 사이트 운영자들도 주기적 보안점검과 암호화 적용, DB 접근제어 등을 반드시 이행할 것을 권고 > 유출된 개인정보가 사기, 피싱, 스팸 발송 등에 활용될 수 있어 2차 피해 가능성에 대한 모니터링도 중요
1 class APIRequestQueue(WazuhRequestQueue):
2 """
3 Represents a queue of API requests. This thread will be always in background, it will remain blocked until a
4 request is pushed into its request_queue. Then, it will answer the request and get blocked again.
5 """
6
7 def __init__(self, server):
8 super().__init__(server)
9 self.logger = logging.getLogger('wazuh').getChild('dapi')
10 self.logger.addFilter(wazuh.core.cluster.utils.ClusterFilter(tag='Cluster', subtag='D API'))
11
12 async def run(self):
13 while True:
14 names, request = (await self.request_queue.get()).split(' ', 1)
15 names = names.split('*', 1)
16 # name -> node name the request must be sent to. None if called from a worker node.
17 # id -> id of the request.
18 # request -> JSON containing request's necessary information
19 name_2 = '' if len(names) == 1 else names[1] + ' '
20
21 # Get reference to MasterHandler or WorkerHandler
22 try:
23 node = self.server.client if names[0] == 'master' else self.server.clients[names[0]]
24 except KeyError as e:
25 self.logger.error(
26 f"Error in DAPI request. The destination node is not connected or does not exist: {e}.")
27 continue
28
29 try:
30 request = json.loads(request, object_hook=c_common.as_wazuh_object)
31 self.logger.info("Receiving request: {} from {}".format(
32 request['f'].__name__, names[0] if not name_2 else '{} ({})'.format(names[0], names[1])))
33 result = await DistributedAPI(**request,
34 logger=self.logger,
35 node=node).distribute_function()
36 task_id = await node.send_string(json.dumps(result, cls=c_common.WazuhJSONEncoder).encode())
37 except Exception as e:
38 self.logger.error(f"Error in distributed API: {e}", exc_info=True)
39 task_id = b'Error in distributed API: ' + str(e).encode()
40
41 if task_id.startswith(b'Error'):
42 self.logger.error(task_id.decode(), exc_info=False)
43 result = await node.send_request(b'dapi_err', name_2.encode() + task_id)
44 else:
45 result = await node.send_request(b'dapi_res', name_2.encode() + task_id)
46 if not isinstance(result, WazuhException):
47 if result.startswith(b'Error'):
48 self.logger.error(result.decode(), exc_info=False)
49 else:
50 self.logger.error(result.message, exc_info=False)
- as_wazuh_object()는 JSON 내부에 "__unhandled_exc__" 값이 있을 경우 "__class__" 및 "__args__" 값을 사용해 eval()로 호출 (Line28 ~ 30) [5]
> 그러나 사용자 입력에 대한 적절한 검증 없이 eval()를 호출하여 임의 코드 실행이 가능
- 25.06.02부터 글로벌 국경 간 프라이버시 규칙(CBPR, Cross Border Privacy Rules) 시행 - CBPR은 회원국 간 전자상거래를 활성화하고 안전한 개인정보 이전을 촉진하기 위해 마련된 제도
내용
- 글로벌 국경 간 프라이버시 규칙(Global CBPR, Global Cross Border Privacy Rules) > 회원국 간 전자상거래를 활성화하고 국경 간 안전한 개인정보 이전을 촉진하기 위한 제도 > 개인정보 관리체계 등에 대한 심사를 거쳐 일정한 개인정보 보호 수준을 갖춘 기업은 인증을 받을 수 있음 ※ 인증을 받은 기업은 해외 사업 시 대외 신뢰도 향상 등의 효과를 얻을 수 있음 ※ 일본, 싱가포르 등 Global CBPR을 국외이전 수단으로 채택한 국가로부터 원활하게 개인정보를 이전받을 수 있
> 지난 2011년 아시아-태평양 지역 9개 국가가 참여하는 APEC CBPR로 시작 > 이후 영향력을 전 세계로 넓히기 위해 대한민국, 미국, 일본 등의 주도로 2022년 글로벌 협의체 출범 > 3년 간의 논의를 거친 결과 글로벌 인증(Global CBPR)을 개시 > 현재 4개 국가(영국, 두바이, 모리셔스, 버뮤다)가 추가로 참여하고 있으며, 다수의 국가가 참여 의사 표명 ※ 아시아-태평양 지역 9개국 : 대한민국, 미국, 일본, 캐나다, 멕시코, 호주, 싱가포르, 필리핀, 대만 ※ 나라별 제도 운용 방식은 다를 수 있음
- 우리나라의 경우 개인정보보호위원회가 전체적인 정책을 총괄하고, KISA는 실제 인증 심사를 진
- SentinelOne, 전 세계 70여 개 조직이 중국 연계 해킹 조직의 표적이 됐다고 발표 - 사이버보안 기업도 주요 타깃으로, 업계 전반 위협 심각
내용
- SentinelLabs (SentinelOne 산하 위협분석 조직) > 전 세계 70여 개 조직이 중국 연계 해킹 조직의 표적이 됐다고 발표 > 24.06 ~ 25.03까지 두 차례에 걸쳐 공격이 발생
① 퍼플헤이즈(PurpleHaze) 캠페인 > APT15와 UNC5174로 추정되는 해킹 조직이 주도 > 24.10 SentinelOne의 인터넷에 노출된 서버를 대상으로 443 포트를 스캔하며 정찰 > entinelxdr[.]us, secmailbox[.]us와 같은 위장 도메인을 등록해 센티넬원 인프라로 위장 > Ivanti 장비의 제로데이 취약점을 통해 GOREshell 백도어를 심는 방식이 활용
② 섀도우패드(ShadowPad) 캠페인 > 중국 국적의 APT41이 주도 > 24.06 ~ 25.03까지 진행 > 센티넬원의 하드웨어 유통을 맡고 있는 IT 서비스·물류 기업을 타깃으로 삼아 공급망 침투 시도 > PowerShell 스크립트를 통해 ShadowPad 악성코드를 배포 (샌드박스 탐지 우회를 위해 60초 지연 실행과 30분 후 자동 재부팅 명령이 포함) > 오픈소스 원격 액세스 도구 Nimbo-C2를 활용해 화면 캡처, PowerShell 명령 실행, 파일 작업, UAC 우회 등 다양한 기능을 수행할 수 있도록 구성 > 민감한 사용자 문서를 찾고, 이를 7-Zip 암호 압축 파일로 만든 뒤 외부로 유출하는 PowerShell 기반 데이터 탈취 스크립트도 함께 활용
- 공격자가 보안기업 Check Point 게이트웨이 장비의 취약점을 통해 최초 접근에 성공했을 가능성이 높다고 분석 > Fortinet Fortigate, Microsoft IIS, SonicWall, CrushFTP 등 다양한 시스템에서도 ShadowPad C2 서버로의 통신이 확인 (해당 장비 또한 악용됐을 가능성 존재)
- 시사점 > 보안 기업 또한 공격 대상으로 삼고 있음 > 공급망을 통한 우회 침투와 보안 기업 탐지 기술 분석을 통한 회피 전략 마련 등 다층적 목표를 가진 위협 행위
기타
- 중국의 정교한 사이버 첩보 전략이 지속되고 있다는 증거 > 오랜 시간에 걸친 사전 정찰, 엣지 장비 침투, 맞춤형 악성코드 배포 등은 전형적인 국가 지원형 공격의 특징
- 단순 방어보다 공급망 리스크 사전 통제, 다층적 탐지 및 대응 체계를 갖추는 것이 필수 > IOC 공유와 실시간 위협 정보 교환, 정기적 시나리오 기반 대응 훈련 필요 > 국가 차원에서는 보안 수준 미비 벤더에 대한 감사와 국제적 제재 등 정책적 조치도 함께 마련되어야 함
- PHP 8.1의 Reflection API 변화로 보호된 내부 API 메서드를 호출하여 원격 코드 실행이 가능한 인증 우회 취약점 (CVSS: 10.0)
- PHP ≤ 8.0 및 PHP ≥ 8.1 비교 [2]
> Reflection API의 동작 변화를 반영하지 않은 경우, 기존 접근 제어 우회 및 보호 메서드에 접근이 가능해짐
구분
설명
PHP ≤ 8.0
- Reflection API(ReflectionMethod::invoke()등)를 사용해 다른 클래스나 메서드에 접근할 경우 > 기본적으로 protected 또는 private 멤버에 접근 불가 > setAccessible(true)를 명시적으로 사용해야 protected 또는 private 멤버에 접근 가능
PHP ≥ 8.1
- Reflection API(ReflectionMethod::invoke()등)를 사용해 다른 클래스나 메서드에 접근할 경우 > setAccessible(true)를 명시적으로 사용하지 않아도 protected 또는 private 멤버에 접근 가능하도록 변경 > 코드 흐름 개선 및 개발 편의성 등으로 변경된 것으로 판단됨
[사진 2] PHP 버전 별 protected 메소드 접근 결과 비교 [3]
2. CVE-2025-48828
[사진 3] CVE-2025-48828 [4]
- 조작된 탬플릿 조건문을 통해 vBulletin 템플릿 엔진의 필터링을 우회하여 임의의 PHP 코드를 실행할 수 있는 원격 코드 실행 취약점 (CVSS: 9.0)
- vBulletin의 템플릿 조건문(<vb:if>)을 악용해 임의의 PHP 코드를 실행
> vBulletin의 템플릿 엔진은 <vb:if> 태그와 같은 조건문을 처리할 때, 내부적으로 eval() 함수를 사용하여 PHP 코드로 변환하고 실행
> vBulletin은 정규 표현식을 사용해 템플릿 파서에 안전하지 않은 함수의 실행을 막기위한 보안 검사를 실행
> PHP의 가변 함수 호출을 이용해 보안 검사를 우회하여 원격 코드 실행이 가능
- PHP 가변 함수 호출 > 변수를 사용해서 함수를 호출하는 것 [사진 3] PHP 가변 함수 호출
- 공격자가 시스템 수준 권한을 가진 상태에서 서버의 Machine Key를 탈취해 원격 코드 실행을 가능하게 하는 역직렬화 취약점
> ConnectWise는 ScreenConnect의 클라우드 버전에서 국가 배후 해커가 취약점을 악용해 공격 받은 사실을 공개 [4]
- 해당 취약점은 ASP.NET의 ViewState 처리 과정에서 역직렬화(Deserialization)가 안전하지 않게 구현된 데서 비롯됨
- ViewState > ASP.NET Web Forms에서 페이지의 상태(state)를 클라이언트에 저장하기 위한 메커니즘 > ASP.NET Web Forms에서 페이지 상태 유지를 위해 사용되는 직렬화된 데이터 > 사용자가 어떤 값을 입력하거나, 페이지에서 변경한 상태를 Postback 시에도 유지하기 위해 사용 > Base64로 인코딩되어 <input type="hidden"> 필드에 포함되어 전송
> web.config 파일에 ViewState의 무결성과 보안을 위해 다음 두 가지 키가 저장 [5]
Machine Key
설명
Validation Key
ViewState 데이터의 변조 여부를 확인하는 데 사용되는 키 값
Decryption Key
ViewState 데이터를 암/복호화하는데 사용되는 키 값
[사진 2] Machine Key
- 공격자가 조작된 요청으로 탈취한 Machine Key 또는 공개된(≒노출된) Machine Key를 사용해 악성 ViewState를 생성 및 전송 [6]
- MS 클라우드 서비스인 OneDrive에 연동 앱들이 사용자 폴더 전체를 볼 수 있는 보안 허점 발견 - OneDrive에 저장된 파일을 챗GPT에 올릴 때, 업로드된 파일뿐 아니라 다른 모든 파일을 보거나 수정할 수 있음
내용
- Oasis Security 연구팀, OneDrive File Picker 기능에서 보안 허점 발견 > OneDriveFile Picker : 윈드라이브에서 업로드할 파일을 선택할 때 쓰는 기능 > OneDriveFile Picker를 통해 파일을 업로드할 때, 사용자의 전체 OneDrive 콘텐츠에 접근할 수 있음
- OneDrive에 대한 세분화된 OAuth 범위가 없기 때문에 발생하는 문제 > OneDriveFile Picker 구현에서 단일 파일만 업로드하는 경우에도 전체 드라이브에 대한 읽기 권한 요청 > 업로드 완료 전 사용자에게 동의를 요청하는 메시지가 표시되나 메시지의 모호성 존재
- 또, OneDriveFile Picker 관련 인증에 주로 쓰이는 마이크로소프트 인증 라이브러리(MSAL)에서도 문제 발견 > 인증 토큰 정보를 브라우저의 세션 저장 공간에 평문으로 저장 > 토큰을 자주 재발급해 사용자 데이터에 접근할 수 있는 기간을 늘인다는 문제도 존재
- MS 계정 페이지에서 외부 앱 접근 권한을 확인하고 불필요한 앱의 공유 중단 필요
기타
- Oasis는 취약점 발견 직후 MS와 해당 기능을 사용하는 기업에 통보 > MS 문제 개선 약속