
Metasploit 풀 리퀘스트용
이는 Phoenix Talon 모듈을 요청하는 이슈 #8571를 해결할 수 있습니다.
대상 시스템에서, 커널이 accept() 시점에 mc_list의 추가 복사본을 유지하기 때문에 이중 해제(double-free)가 트리거됩니다.
커널 4.10.15 이하를 실행하는 시스템이 다음 루틴을 실행 중이면 위험합니다:
sockfd = socket(AF_INET, xx, IPPROTO_TCP);
setsockopt(sockfd, SOL_IP, MCAST_JOIN_GROUP, xxxx, xxxx);
bind(sockfd, xxxx, xxxx);
listen(sockfd, xxxx);
newsockfd = accept(sockfd, xxxx, xxxx);
close(newsockfd); // trigger release calls, handoff to RCU
sleep(5); // wait for rcu to free()
close(sockfd); // second free()
부모 소켓 sockfd가 생성됩니다. MCAST_JOIN_GROUP 옵션으로 멀티캐스트 그룹에 추가됩니다.
로컬 인터페이스에서 소켓을 멀티캐스트 그룹에 추가할 때 커널이 메모리를 할당합니다. 이 시점에서 mc_list는 부모 소켓에 존재합니다.
bind()로 소켓에 주소가 할당된 후, 연결을 위해 listen()과 accept()가 수행됩니다.
accept()는 새 소켓 newsockfd를 생성하며, 여기에 mc_list 포인터 값을 포함한 부모의 모든 필요한 필드가 복사됩니다. 이 시점에서 동일한 메모리 블록을 가리키는 여러 포인터가 존재하므로 이중 해제가 발생합니다.
연결이 설정되면 커널은 부모 소켓의 mc_list 객체를 상속하는 자식 소켓을 생성합니다. 이 상속 결함은 파일 net/ipv4/inet_connection_sock.c의 648번째 줄 inet_csk_clone_lock에 있습니다. 패치를 보면 이 의도하지 않은 상속에 대한 한 줄 수정을 확인할 수 있습니다.
다음으로, 자식 소켓을 닫습니다. 위에서 설명한 대로, 이는 mc_list 객체를 해제하지 않습니다. RCU(원격 복사 업데이트) 구조를 통해 메모리를 해제합니다. RCU 핸드오프가 kfree()를 호출할 충분한 시간을 확보하기 위해 몇 초 동안 sleep()합니다. 마지막으로 부모 소켓을 닫으면 두 번째 해제가 트리거됩니다.
간단한 DoS입니다. 위에서 설명한 필요한 서버 루틴을 실행 중인 알려진 대상 시스템에서 원격으로 이중 해제를 트리거합니다. 이로 인해 커널 패닉이 발생합니다.