-
Notifications
You must be signed in to change notification settings - Fork 302
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add MongoDB scanner. #156
Add MongoDB scanner. #156
Conversation
|
||
// getCommandMsg returns a mongodb message containing the specified BSON-encoded command. | ||
// metdata and commandArgs expected to be BSON byte arrays. | ||
func getCommandMsg(database string, commandName string, metadata []byte, commandArgs []byte) ([]byte) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can make you life a lot easier by using a bytes.Buffer with a preallocated buffer here.
modules/mongodb/scanner.go
Outdated
metaData, err := bson.Marshal(bson.M{ "buildInfo": 1 }) | ||
if err != nil { | ||
// programmer error | ||
panic("Invalid BSON") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure this shouldn't return an error?
modules/mongodb/scanner.go
Outdated
panic("Invalid BSON") | ||
} | ||
commandArgs, err := bson.Marshal(bson.M{}) | ||
if err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above. A good pattern is log error at source, and return up.
modules/mongodb/scanner.go
Outdated
|
||
// getBuildInfoMsg returns a mongodb message containing a command to retrieve MongoDB build info. | ||
func getBuildInfoMsg() ([]byte) { | ||
metaData, err := bson.Marshal(bson.M{ "buildInfo": 1 }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is static data, do once at process start time in the init() function and save for later use.
modules/mongodb/scanner.go
Outdated
return zgrab2.TryGetScanStatus(err), nil, err | ||
} | ||
if len(binfo) < MSGHEADER_LEN + 4 { | ||
err = fmt.Errorf("Server truncated message - no metadata doc (%d bytes: %s)", len(binfo), hex.EncodeToString(binfo)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
%x will do the hex encoding for you
) | ||
|
||
const ( | ||
OP_REPLY = 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
go prefers camel case for all things, including constants. Not a huge deal, but go vet will yell at you if you run it.
modules/mongodb/types.go
Outdated
if err != nil { | ||
return nil, err | ||
} | ||
msglen := int(binary.LittleEndian.Uint32(msglen_buf)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this ever need to be an int
?
modules/mongodb/types.go
Outdated
|
||
// ReadMsg reads a full MongoDB message from the connection. | ||
func (conn *Connection) ReadMsg() ([]byte, error) { | ||
msglen_buf := make([]byte, 4) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want this to be fast, use an array, and pass it is a slice view.
var msglen_buf [4]byte
io.ReadFull(conn.conn, msglen_buf[:])
This will save you a heap allocation.
* Generate static messages in Scanner Init() * s/panic/log.Fatal/ * Remove unnecessary casting * Use stack var and pass slice to avoid unnecessary alloc
modules/mongodb/scanner.go
Outdated
section_payload, err := bson.Marshal(bson.M{ "buildinfo": 1, "$db": "admin" }) | ||
if err != nil { | ||
// programmer error | ||
log.Fatal("Invalid BSON") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice if the specific error got logged too -- e.g. log.Fatalf("Invalid BSON: %v", err)
or ...%s", err.String())
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call
modules/mongodb/scanner.go
Outdated
Cxx string `bson:"cxx,omitempty"` | ||
CxxFlags string `bson:"cxxflags,omitempty"` | ||
LinkFlags string `bson:"linkflags,omitempty"` | ||
TargetAarch string `bson:"target_arch,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo? Also, this may be from the spec itself, but do they really treat "distarch" and "target_arch" differently?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lol this is a typo and I actually wrote the integration test to accommodate it. will fix
modules/mongodb/scanner.go
Outdated
scan.conn.Write(query) | ||
msg, err := scan.conn.ReadMsg() | ||
if err != nil { | ||
return zgrab2.TryGetScanStatus(err), nil, err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the data returned from the first packet / the fact that getMaxWireVersion()
didn't throw sufficient to say that this is a MongoDB server?
If so, returning the error is still correct, but instead of nil, it should return a partial response object.
If OTOH random data could get this far, then returning a nil result is the right choice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, if getMaxWireVersion() succeeds, then the server is speaking valid mongodb protocol. Should return partial response.
modules/mongodb/types.go
Outdated
return err | ||
} | ||
if n != len(data) { | ||
return &zgrab2.ScanError{Status: zgrab2.SCAN_CONNECTION_CLOSED, Err: nil} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a built-in error for short writes -- I think it's io.ErrShortWrite
?
In the long run, this probably should be built into the common socket wrapper code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ack
modules/mongodb/scanner.go
Outdated
} | ||
|
||
// Result holds the data returned by the scan | ||
type Result struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We typically use snake_case for our JSON output -- so you would need additional json
tags, e.g. json:"git_version"
or json:"build_environment,omitempty"
(the omitempty
used to prevent JSON fields with their default go values from being written; usually we use omitempty
unless there is a specific reason not to -- like for int
/bool
values where 0
/false
are meaningful)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ack
* Add error message to invalid BSON log msg * Use snake case for json output * Update affect integration tests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me
* Separate out isMaster and buildInfo commands * Return results of both in separate sub-structs * Include isMaster results regardless of whether buildInfo succeeds
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good
Added mongodb support.
How to Test
Pass IP of mongodb host to zgrab.
Notes & Caveats
Still needs tests
Issue Tracking
#16