add some tighter bounds checking in MSSQL scanner, and if there is an uncaught panic, log the body that caused it
This commit is contained in:
parent
e7e7be1f6f
commit
6618920234
@ -11,7 +11,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
logrus "github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/zmap/zgrab2"
|
"github.com/zmap/zgrab2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -401,6 +401,9 @@ func (options PreloginOptions) Encode() ([]byte, error) {
|
|||||||
for _, ik := range sortedKeys {
|
for _, ik := range sortedKeys {
|
||||||
k := PreloginOptionToken(ik)
|
k := PreloginOptionToken(ik)
|
||||||
v := options[k]
|
v := options[k]
|
||||||
|
if len(cursor) < 5 {
|
||||||
|
return nil, fmt.Errorf("encode: size mismatch (options.Size()=%d)", options.Size())
|
||||||
|
}
|
||||||
cursor[0] = byte(k)
|
cursor[0] = byte(k)
|
||||||
if offset > 0xffff {
|
if offset > 0xffff {
|
||||||
return nil, ErrTooLarge
|
return nil, ErrTooLarge
|
||||||
@ -411,6 +414,9 @@ func (options PreloginOptions) Encode() ([]byte, error) {
|
|||||||
offset += len(v)
|
offset += len(v)
|
||||||
cursor = cursor[5:]
|
cursor = cursor[5:]
|
||||||
}
|
}
|
||||||
|
if len(cursor) < 1 {
|
||||||
|
return nil, fmt.Errorf("encode: size mismatch (options.Size()=%d, len(sortedKeys)=%d)", options.Size(), len(sortedKeys))
|
||||||
|
}
|
||||||
// Write the terminator after the last PL_OPTION header
|
// Write the terminator after the last PL_OPTION header
|
||||||
// (and just before the first value)
|
// (and just before the first value)
|
||||||
cursor[0] = 0xff
|
cursor[0] = 0xff
|
||||||
@ -421,6 +427,9 @@ func (options PreloginOptions) Encode() ([]byte, error) {
|
|||||||
// returned in rest.
|
// returned in rest.
|
||||||
// If body can't be decoded as a PRELOGIN body, returns nil, nil, ErrInvalidData
|
// If body can't be decoded as a PRELOGIN body, returns nil, nil, ErrInvalidData
|
||||||
func decodePreloginOptions(body []byte) (result *PreloginOptions, rest []byte, err error) {
|
func decodePreloginOptions(body []byte) (result *PreloginOptions, rest []byte, err error) {
|
||||||
|
if len(body) < 1 {
|
||||||
|
return nil, nil, ErrInvalidData
|
||||||
|
}
|
||||||
cursor := body[:]
|
cursor := body[:]
|
||||||
options := make(PreloginOptions)
|
options := make(PreloginOptions)
|
||||||
max := 0
|
max := 0
|
||||||
@ -506,7 +515,13 @@ func (options PreloginOptions) MarshalJSON() ([]byte, error) {
|
|||||||
|
|
||||||
fedAuthRequired, hasFedAuthRequired := opts[PreloginFedAuthRequired]
|
fedAuthRequired, hasFedAuthRequired := opts[PreloginFedAuthRequired]
|
||||||
if hasFedAuthRequired {
|
if hasFedAuthRequired {
|
||||||
aux.FedAuthRequired = &fedAuthRequired[0]
|
temp := uint8(0)
|
||||||
|
if len(fedAuthRequired) > 0 {
|
||||||
|
temp = fedAuthRequired[0]
|
||||||
|
} else {
|
||||||
|
logrus.Debugf("fedAuthRequired was present but empty (options=%#v)", options)
|
||||||
|
}
|
||||||
|
aux.FedAuthRequired = &temp
|
||||||
}
|
}
|
||||||
|
|
||||||
nonce, hasNonce := opts[PreloginNonce]
|
nonce, hasNonce := opts[PreloginNonce]
|
||||||
@ -632,6 +647,7 @@ func (connection *Connection) readPreloginPacket() (*TDSPacket, *PreloginOptions
|
|||||||
if packet.Type != TDSPacketTypeTabularResult {
|
if packet.Type != TDSPacketTypeTabularResult {
|
||||||
return packet, nil, &zgrab2.ScanError{Status: zgrab2.SCAN_APPLICATION_ERROR, Err: err}
|
return packet, nil, &zgrab2.ScanError{Status: zgrab2.SCAN_APPLICATION_ERROR, Err: err}
|
||||||
}
|
}
|
||||||
|
defer zgrab2.LogPanic("Error decoding Prelogin packet %#v", packet.Body)
|
||||||
plOptions, rest, err := decodePreloginOptions(packet.Body)
|
plOptions, rest, err := decodePreloginOptions(packet.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return packet, nil, err
|
return packet, nil, err
|
||||||
|
17
utility.go
17
utility.go
@ -10,6 +10,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/zmap/zflags"
|
"github.com/zmap/zflags"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"runtime/debug"
|
||||||
)
|
)
|
||||||
|
|
||||||
var parser *flags.Parser
|
var parser *flags.Parser
|
||||||
@ -209,3 +211,18 @@ func IsTimeoutError(err error) bool {
|
|||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LogPanic is intended to be called from within defer -- if there was no panic, it returns without
|
||||||
|
// doing anything. Otherwise, it logs the stacktrace, the panic error, and the provided message
|
||||||
|
// before re-raising the original panic.
|
||||||
|
// Example:
|
||||||
|
// defer zgrab2.LogPanic("Error decoding body '%x'", body)
|
||||||
|
func LogPanic(format string, args...interface{}) {
|
||||||
|
err := recover()
|
||||||
|
if err == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
logrus.Errorf("Uncaught panic at %s: %v", string(debug.Stack()), err)
|
||||||
|
logrus.Errorf(format, args...)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user