[ntp:questions] Re: "Listen on" semantics

Danny Mayer mayer at ntp.isc.org
Sun Sep 24 03:19:42 UTC 2006

Luc Pardon wrote:
> Harlan Stenn wrote:
>>>>> In article <45110BAE.8040106 at skopos.be>, xntp at skopos.be (Luc
>>>>> Pardon) writes:
>> Lots of good stuff.
>> Luc>     Case in point #1: back in 2001, there was a bug in - yes -
>> (x)ntpd
>> Luc> that allowed remote root access. See, for example:
>> Luc>
>> http://archive.cert.uni-stuttgart.de/archive/bugtraq/2001/04/msg00064.html
>> First, please compare this history to other root-running processes and
>> tell
>> me how (x)ntpd compares.  Especially given the length of time (x)ntpd has
>> been in the field.
>     We wouldn't be having this discussion if I was of the opinion that
> (x)ntpd had a lousy track record. I wouldn't bother.
>     I mentioned this only to show that there can be buffer overflow bugs
> in otherwise correct code.
Right now you can only get buffer overflow bugs by sending an NTP packet
but the code already checks for that, so you don't have any way of doing it.

>  > Luc>     Case in point #2: only last week, my logs were being flooded
>> Luc> because somebody sent icmp port unreachable packets to udp/123.
>> Fair point, and Real Soon Now we're going to have better configuration
>> control over logfiles.  
>     The problem is that you can't distinguish between real and fake
> packets. If you suppress the fake "connection refused", you may be
> wiping real problems under the carpet as well.

Do you know what "connection refused" really means? It means that
nothing is listening on that port of that server. It does not mean that
the server is refusing to accept it.

>> And I thought syslog() was pretty good about "Last
>> message repeated N times".
>     Point taken, I did forget that. It issues a "repeated" every second,
> so our attacker would not be ready by Sunday. Unless he can find another
> way - preferably with (x)ntpd - to generate a syslog entry and alternate
> that with the port unreachable packets. A "grep syslog *.c | grep
> LOG_ERR" yields some promising candidates.

We silently drop any packets at the network level and I believe at the
restrict level. They don't get logged except if you are debugging. We
can change our code for the logging so that we can just count identical
messages and put it out when the message changes along with the count.
It would cut down dramatically on logging an attack.

>    Out of curiosity, I had a quick look at the ntp-dev-4.2.3p39 code.
>   <black hat on>
>  At first sight, it seems possible to craft a packet that will end up in
> process_private() in ntp_request.c and trigger the sanity check in there.
>    In ntp_proto.c(388), it says:
>         hismode = (int)PKT_MODE(pkt->li_vn_mode);
>         hisstratum = PKT_TO_STRATUM(pkt->stratum);
>         if (hismode == MODE_PRIVATE) {
>                 if (restrict_mask & RES_NOQUERY) {
>                         sys_restricted++;
>                         return;                 /* no query private */
>                 }
>                 process_private(rbufp, ((restrict_mask &
>                     RES_NOMODIFY) == 0));
>                 return;
>         }
>   So I'd set the li_vn_mode to PRIVATE (whatever that means <g>) and I'd
> fake the source address to to steer it past the restrict rules
> in most setups. If and when I make it into process_private(), I have a
> choice of 4 fields in the packet that I can load with invalid values, or
> I could make it too long or too short.

MODE_PRIVATE is are mode 7 packets and the only thing that uses it is
ntpdc. Notice that if restrictions don't allow it it just drops the
request without logging. Yes, is likely to be allowed but what
happens to the response? It goes back to the local machine. If the
source port is also 123 then it returns to the server and this time the
packet will get dropped since it will no longer be a valid packet (see
the mapping, I think in ntp_proto.c).

 In ntp_request.c(433) my
> malicious eyes see the following code that makes me drool:
>         /*
>          * Do some sanity checks on the packet.  Return a format
>          * error if it fails.
>          */
>         ec = 0;
>         if (   (++ec, ISRESPONSE(inpkt->rm_vn_mode))
>             || (++ec, ISMORE(inpkt->rm_vn_mode))
>             || (++ec, INFO_VERSION(inpkt->rm_vn_mode) > NTP_VERSION)
>             || (++ec, INFO_VERSION(inpkt->rm_vn_mode) < NTP_OLDVERSION)
>             || (++ec, INFO_SEQ(inpkt->auth_seq) != 0)
>             || (++ec, INFO_ERR(inpkt->err_nitems) != 0)
>             || (++ec, INFO_MBZ(inpkt->mbz_itemsize) != 0)
>             || (++ec, rbufp->recv_length < REQ_LEN_HDR)
>                 ) {
>                 msyslog(LOG_ERR, "process_private: INFO_ERR_FMT: test %d
> failed, pkt from %s", ec, stoa(srcadr));
>                 req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
>                 return;
>         }
>   Too bad the restrict rules are in front of it, otherwise I could use
> my own IP (or that of one of my zombies) and I'd get an ack if I
> succeeded, then start faking source IP's.
>   <black hat off>
>   Again: this is just the result of a quick look at unfamiliar code.
> More likely than not, I'm missing something obvious so that this won't
> fly. But it sure looks promising and if it should work, I have my siege
> engine complete. By alternating one of these with an icmp packet, I can
> flood the log just fine.

We can apply counting mechanisms here.

>    Again, this would not be an issue at all if (x)ntpd didn't take candy
> from strangers.

Whether it does or does not is up to the operator.


More information about the questions mailing list