Documentation
¶
Overview ¶
Package ntp provides a zgrab2 module that probes for the NTP service. NOTE: unlike most modules, this scans on UDP.
The default scan does a standard get time request.
Passing the monlist flag will check for the DDoS-amplifying MONLIST command.
The results of the scan are the version number and the time returned by the server, and if verbose results are enabled, the entire parsed response packet(s).
For more details on NTP, see https://tools.ietf.org/html/rfc5905.
Index ¶
- Constants
- Variables
- func RegisterModule()
- type AssociationMode
- type Flags
- type ImplNumber
- type InfoError
- type LeapIndicator
- type Module
- type NTPHeader
- type NTPLong
- type NTPShort
- type PrivatePacketHeader
- type ReferenceID
- type RequestCode
- type Results
- type Scanner
- func (scanner *Scanner) GetName() string
- func (scanner *Scanner) GetTime(sock net.Conn) (*NTPHeader, error)
- func (scanner *Scanner) GetTrigger() string
- func (scanner *Scanner) Init(flags zgrab2.ScanFlags) error
- func (scanner *Scanner) InitPerSender(senderID int) error
- func (scanner *Scanner) MonList(sock net.Conn, result *Results) (zgrab2.ScanStatus, error)
- func (s *Scanner) Protocol() string
- func (scanner *Scanner) Scan(t zgrab2.ScanTarget) (zgrab2.ScanStatus, interface{}, error)
- func (scanner *Scanner) SendAndReceive(impl ImplNumber, req RequestCode, body []byte, sock net.Conn) (*PrivatePacketHeader, []byte, error)
Constants ¶
const ( // NoWarning is a LeapIndicator that indicates that there is no problem NoWarning LeapIndicator = 0 // ExtraSecond is a LeapIndicator that indicates that the last minute has 61 seconds ExtraSecond = 1 // MissingSecond is a LeapIndicator that indicates that the last minute has 59 seconds MissingSecond = 2 // Unknown is a LeapIndicator that indicates an unknown alarm condition Unknown = 3 )
const ( // Reserved is a reserved AssociationMode Reserved AssociationMode = 0 // SymmetricActive is an AssociationMode indicating that the service is in the active symmetric mode SymmetricActive = 1 // SymmetricPassive is an AssociationMode indicating that the service is in the passive symmetric mode SymmetricPassive = 2 // Client is an AssociationMode indicating that the caller is a client Client = 3 // Server is an AssociationMode indicating that the packet is to be interpreted as a server Server = 4 // Broadcast is an AssociationMode indicating that the this is a broadcast packet Broadcast = 5 // Control is an AssociationMode reserved for NTP control messages Control = 6 // Private is an AssociationMode reserved for private use Private = 7 )
const ( // ImplUniv corresponds to the IMPL_UNIV constant ImplUniv ImplNumber = 0 // ImplXNTPDOld corresponds to the IMPL_XNTPD_OLD constant ImplXNTPDOld = 2 // ImplXNTPD corresponds to the IMPL_XNTPD constant ImplXNTPD = 3 )
Constants from ntp/include/ntp_request.h
const ( // ReqPeerList corresponds to the REQ_PEER_LIST constant ReqPeerList RequestCode = 0 // ReqPeerListSum corresponds to the REQ_PEER_LIST_SUM constant ReqPeerListSum = 1 // ReqPeerInfo corresponds to the REQ_PEER_INFO constant ReqPeerInfo = 2 // ReqPeerStats corresponds to the REQ_PEER_STATS constant ReqPeerStats = 3 // ReqSysInfo corresponds to the REQ_SYS_INFO constant ReqSysInfo = 4 // ReqSysStats corresponds to the REQ_SYS_STATS constant ReqSysStats = 5 // ReqIOStats corresponds to the REQ_IO_STATS constant ReqIOStats = 6 // ReqMemStats corresponds to the REQ_MEM_STATS constant ReqMemStats = 7 // ReqLoopInfo corresponds to the REQ_LOOP_INFO constant ReqLoopInfo = 8 // ReqTimerStats corresponds to the REQ_TIMER_STATS constant ReqTimerStats = 9 // ReqConfig corresponds to the REQ_CONFIG constant ReqConfig = 10 // ReqUnconfig corresponds to the REQ_UNCONFIG constant ReqUnconfig = 11 // ReqSetSysFlag corresponds to the REQ_SET_SYS_FLAG constant ReqSetSysFlag = 12 // ReqClrSysFlag corresponds to the REQ_CLR_SYS_FLAG constant ReqClrSysFlag = 13 // ReqMonitor corresponds to the REQ_MONITOR constant ReqMonitor = 14 // ReqNoMonitor corresponds to the REQ_NOMONITOR constant ReqNoMonitor = 15 // ReqGetRestrict corresponds to the REQ_GET_RESTRICT constant ReqGetRestrict = 16 // ReqResAddFlags corresponds to the REQ_RES_ADD_FLAGS constant ReqResAddFlags = 17 // ReqResSubFlags corresponds to the REQ_RES_SUB_FLAGS constant ReqResSubFlags = 18 // ReqUnrestrict corresponds to the REQ_UNRESTRICT constant ReqUnrestrict = 19 // ReqMonGetList corresponds to the REQ_MON_GETLIST constant ReqMonGetList = 20 // ReqResetStats corresponds to the REQ_RESET_STATS constant ReqResetStats = 21 // ReqResetPeer corresponds to the REQ_RESET_PEER constant ReqResetPeer = 22 // ReqRereadKeys corresponds to the REQ_REREAD_KEYS constant ReqRereadKeys = 23 // ReqDoDirtyHack corresponds to the REQ_DO_DIRTY_HACK constant ReqDoDirtyHack = 24 // ReqDontDirtyHack corresponds to the REQ_DONT_DIRTY_HACK constant ReqDontDirtyHack = 25 // ReqTrustKey corresponds to the REQ_TRUST_KEY constant ReqTrustKey = 26 // ReqUntrustKey corresponds to the REQ_UNTRUST_KEY constant ReqUntrustKey = 27 // ReqAuthInfo corresponds to the REQ_AUTH_INFO constant ReqAuthInfo = 28 // ReqTraps corresponds to the REQ_TRAPS constant ReqTraps = 29 // ReqAddTrap corresponds to the REQ_ADD_TRAP constant ReqAddTrap = 30 // ReqClrTrap corresponds to the REQ_CLR_TRAP constant ReqClrTrap = 31 // ReqRequestKey corresponds to the REQ_REQUEST_KEY constant ReqRequestKey = 32 // ReqControlKey corresponds to the REQ_CONTROL_KEY constant ReqControlKey = 33 // ReqGetCtlStats corresponds to the REQ_GET_CTLSTATS constant ReqGetCtlStats = 34 // ReqGetLeapInfo corresponds to the REQ_GET_LEAPINFO constant ReqGetLeapInfo = 35 // ReqGetClockInfo corresponds to the REQ_GET_CLOCKINFO constant ReqGetClockInfo = 36 // ReqSetClkFudge corresponds to the REQ_SET_CLKFUDGE constant ReqSetClkFudge = 37 // ReqGetKernel corresponds to the REQ_GET_KERNEL constant ReqGetKernel = 38 // ReqGetClkBugInfo corresponds to the REQ_GET_CLKBUGINFO constant ReqGetClkBugInfo = 39 // ReqSetPrecision corresponds to the REQ_SET_PRECISION constant ReqSetPrecision = 41 // ReqMonGetList1 corresponds to the REQ_MON_GETLIST_1 constant ReqMonGetList1 = 42 // ReqHostnameAssocID corresponds to the REQ_HOSTNAME_ASSOCID constant ReqHostnameAssocID = 43 // ReqIfStats corresponds to the REQ_IF_STATS constant ReqIfStats = 44 // ReqIfReload corresponds to the REQ_IF_RELOAD constant ReqIfReload = 45 )
const ( // InfoErrorOkay corresponds to the INFO_OKAY constant InfoErrorOkay InfoError = 0 // InfoErrorImpl corresponds to the INFO_ERR_IMPL constant InfoErrorImpl = 1 // InfoErrorReq corresponds to the INFO_ERR_REQ constant InfoErrorReq = 2 // InfoErrorFmt corresponds to the INFO_ERR_FMT constant InfoErrorFmt = 3 // InfoErrorNoData corresponds to the INFO_ERR_NODATA constant InfoErrorNoData = 4 // InfoErrorUnknown5 has no corresponding constant (it is the unused value 5) InfoErrorUnknown5 = 5 // InfoErrorUnknown6 has no corresponding constant (it is the unused value 6) InfoErrorUnknown6 = 6 // InfoErrorAuth corresponds to the INFO_ERR_AUTH constant InfoErrorAuth = 7 )
Variables ¶
var ( // ErrInvalidLeapIndicator is returned if an invalid LeapIndicator is found ErrInvalidLeapIndicator = errors.New("leap indicator not valid") // ErrInvalidVersion is returned if an invalid version number is found ErrInvalidVersion = errors.New("version number not valid") // ErrInvalidMode is returned if an invalid mode identifier is found ErrInvalidMode = errors.New("mode not valid") // ErrInvalidStratum is returned if an invalid stratum identifier is found ErrInvalidStratum = errors.New("stratum invalid") // ErrInvalidReferenceID is returned if an invalid reference ID is found (i.e. it contains non-ASCII characters) ErrInvalidReferenceID = errors.New("reference ID contained non-ASCII characters") // ErrBufferTooSmall is returned if a buffer is not large enough to contain the input ErrBufferTooSmall = errors.New("buffer too small") // ErrInvalidHeader is returned if the header cannot be interpreted as a valid NTP header ErrInvalidHeader = errors.New("invalid header data") // ErrInvalidResponse is returned if the response cannot be interpreted as a valid NTP response ErrInvalidResponse = errors.New("invalid response") // ErrInvalidRequestCode is returned if an invalid RequestCode is found ErrInvalidRequestCode = errors.New("request code invalid") )
Functions ¶
Types ¶
type AssociationMode ¶
type AssociationMode uint8
AssociationMode is a three-bit value, whose values are defined in figure 9 of https://tools.ietf.org/html/rfc5905
type Flags ¶
type Flags struct { zgrab2.BaseFlags zgrab2.UDPFlags Verbose bool `long:"verbose" description:"More verbose logging, include debug fields in the scan results"` Version uint8 `long:"version" description:"The version number to pass to the Server." default:"3"` LeapIndicator uint8 `long:"leap-indicator" description:"The LI value to pass to the Server. Default 3 (Unknown)"` SkipGetTime bool `long:"skip-get-time" description:"If set, don't request the Server time"` MonList bool `long:"monlist" description:"Perform a ReqMonGetList request"` RequestCode string `long:"request-code" description:"Specify a request code for MonList other than ReqMonGetList" default:"REQ_MON_GETLIST"` }
Flags holds the command-line flags for the scanner.
type ImplNumber ¶
type ImplNumber uint8
ImplNumber is an 8-bit value used in Private packets
func (ImplNumber) MarshalJSON ¶
func (num ImplNumber) MarshalJSON() ([]byte, error)
MarshalJSON gives the #define name, or "UNKNOWN (0x##)"
type InfoError ¶
type InfoError uint8
InfoError is a 3-bit integer, values taken from ntp_request.h
func (InfoError) Error ¶
Error implements the error interface (returns the #define name, or "UNKNOWN (0x##)")
func (InfoError) MarshalJSON ¶
MarshalJSON gives the #define name, or "UNKNOWN (0x##)"
type LeapIndicator ¶
type LeapIndicator uint8
LeapIndicator is a two-bit field, whose values are defined in figure 9 of https://tools.ietf.org/html/rfc5905
type Module ¶
type Module struct { }
Module is the zgrab2 module implementation
func (*Module) NewFlags ¶
func (module *Module) NewFlags() interface{}
NewFlags returns a flags instant to be populated with the command line args
func (*Module) NewScanner ¶
NewScanner returns a new NTP scanner instance
type NTPHeader ¶
type NTPHeader struct { // LeapIndicator is the the top two bits of the first byte LeapIndicator LeapIndicator `json:"leap_indicator"` // Version is bits 5..3 of the first byte Version uint8 `json:"version"` // The mode is the lowest three bits of the first byte Mode AssociationMode `json:"mode"` // Stratum is defined in figure 11: values > 16 are Reserved Stratum uint8 `json:"stratum"` // Poll: 8-bit signed integer representing the maximum interval between // successive messages, in log2 seconds. Poll int8 `json:"poll"` // Precision: 8-bit signed integer representing the precision of the system clock, in log2 seconds. Precision int8 `json:"precision"` // Root Delay: Total round-trip delay to the reference clock RootDelay NTPShort `json:"root_delay"` // Root Dispersion: Total dispersion to the reference clock RootDispersion NTPShort `json:"root_dispersion"` // Reference ID (refid): 32-bit code identifying the particular Server or reference clock. ReferenceID ReferenceID `json:"reference_id,omitempty"` // Reference Timestamp: Time when the system clock was last set or corrected ReferenceTimestamp NTPLong `json:"reference_timestamp,omitempty"` // Origin Timestamp (org): Time at the Client when the request departed for the Server OriginTimestamp NTPLong `json:"origin_timestamp,omitempty"` // Receive Timestamp (rec): Time at the Server when the request arrived from the Client ReceiveTimestamp NTPLong `json:"receive_timestamp,omitempty"` // Transmit Timestamp (xmt): Time at the Server when the response left for the Client TransmitTimestamp NTPLong `json:"transmit_timestamp,omitempty"` }
NTPHeader is defined in figure 8 of RFC5905
func (*NTPHeader) ValidateSyntax ¶
ValidateSyntax checks that the header's values are within range and make semantic sense
type NTPLong ¶
NTPLong is a 64-bit fixed-length number defined in figure 3 of RFC5905
func (*NTPLong) Encode ¶
Encode encodes the NTPShort according to RFC5905 -- upper 32 bits the seconds, lower 32 bits the fractional seconds (big endian)
type NTPShort ¶
NTPShort a 32-bit struct defined in figure 3 of RFC5905.
func (*NTPShort) Decode ¶
Decode populates the values of this NTPShort with the first 4 bytes of buf
func (*NTPShort) Encode ¶
Encode encodes the NTPShort according to RFC5905 -- upper 16 bits the seconds, lower 16 bits the fractional seconds (big endian)
func (*NTPShort) GetDuration ¶
GetDuration gets the time.Duration corresponding to when
func (*NTPShort) SetDuration ¶
SetDuration sets the Seconds and Fraction to match the given duration
type PrivatePacketHeader ¶
type PrivatePacketHeader struct { IsResponse bool `json:"is_response"` HasMore bool `json:"has_more"` Version uint8 `json:"version"` Mode AssociationMode `json:"mode"` IsAuthenticated bool `json:"is_authenticated"` SequenceNumber uint8 `json:"sequence_number"` ImplementationNumber ImplNumber `json:"implementation_number"` RequestCode RequestCode `json:"request_code"` Error InfoError `json:"error"` NumItems uint16 `json:"num_items"` MBZ uint8 `json:"mbz"` ItemSize uint16 `json:"item_size"` }
PrivatePacketHeader represents a header for a mode-7 packet, roughly corresponding to struct resp_pkt in ntp_request.h
func (*PrivatePacketHeader) Encode ¶
func (header *PrivatePacketHeader) Encode() ([]byte, error)
Encode encodes the packet header as a struct resp_pkt
type ReferenceID ¶
type ReferenceID [4]byte
ReferenceID is defined in RFC5905 as a 32-bit code whose interpretation depends on the stratum field
func (ReferenceID) MarshalJSON ¶
func (id ReferenceID) MarshalJSON() ([]byte, error)
MarshalJSON ensures that it is marshalled like a slice, not an array
type RequestCode ¶
type RequestCode uint8
RequestCode is an 8-bit value used in Private packets, from ntp/include/ntp_request.h
func (RequestCode) MarshalJSON ¶
func (code RequestCode) MarshalJSON() ([]byte, error)
MarshalJSON gives the #define name, or "UNKNOWN (0x##)"
type Results ¶
type Results struct { // Version is the version number returned in the get time response header. // Absent if --skip-get-time is set. Version *uint8 `json:"version,omitempty"` // Time is the time returned by the server (specifically, the // ReceiveTimestamp) in response to the get time call. Converted into a // standard golang time. // Absent if --skip-get-time is set. Time *time.Time `json:"time,omitempty"` // TimeResponse is the full header returned by the get time call. // Absent if --skip-get-time is set. Debug only. TimeResponse *NTPHeader `json:"time_response,omitempty" zgrab:"debug"` // MonListResponse is the raw data returned by the call to monlist. // Only present if --monlist is set. MonListResponse []byte `json:"monlist_response,omitempty"` // MonListHeader is the header returned by the call to monlist. // Only present if --monlist is set. Debug only. MonListHeader *PrivatePacketHeader `json:"monlist_header,omitempty" zgrab:"debug"` }
Results is the struct that is returned to the zgrab2 framework from Scan()
type Scanner ¶
type Scanner struct {
// contains filtered or unexported fields
}
Scanner holds the state for a single scan
func (*Scanner) GetTime ¶
GetTime sends a "Client" packet to the Server and reads / returns the response
func (*Scanner) GetTrigger ¶
GetTrigger returns the Trigger defined in the Flags.
func (*Scanner) InitPerSender ¶
InitPerSender initializes the scanner for a given sender
func (*Scanner) MonList ¶
MonList does a ReqMonGetList call to the Server and populates result with the output
func (*Scanner) Scan ¶
func (scanner *Scanner) Scan(t zgrab2.ScanTarget) (zgrab2.ScanStatus, interface{}, error)
Scan scans the configured server with the settings provided by the command line arguments as follows:
- If SkipGetTime is not set, send a GetTime packet to the server and read the response packet into the result.
- If MonList is set, send a MONLIST packet to the server and read the response packet into the result.
The presence of an NTP service at the target can be inferred by a non-nil result -- if the service does not return any data or if the response is not a valid NTP packet, then the result will be nil. The presence of a DDoS-amplifying target can be inferred by result.MonListReponse being present.
func (*Scanner) SendAndReceive ¶
func (scanner *Scanner) SendAndReceive(impl ImplNumber, req RequestCode, body []byte, sock net.Conn) (*PrivatePacketHeader, []byte, error)
SendAndReceive is a rough version of ntpdc.c's doquery(), except it only supports a single packet response