Skip to content

Commit

Permalink
implements xmpp, coap and opcua
Browse files Browse the repository at this point in the history
  • Loading branch information
RicYaben committed Oct 17, 2024
1 parent 735e746 commit 4b736d3
Show file tree
Hide file tree
Showing 72 changed files with 739 additions and 3 deletions.
Empty file modified docker-runner/base-apt-update.sh
100755 → 100644
Empty file.
Empty file modified docker-runner/docker-run.sh
100755 → 100644
Empty file.
Empty file modified docker-runner/entrypoint.sh
100755 → 100644
Empty file.
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,15 @@ require golang.org/x/exp v0.0.0-20240707233637-46b078467d37
require (
github.com/gorilla/websocket v1.5.3 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pkg/errors v0.9.1 // indirect
golang.org/x/sync v0.7.0 // indirect
)

require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/eclipse/paho.mqtt.golang v1.4.3
github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/gopcua/opcua v0.5.3
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-github/v50 v50.2.0/go.mod h1:VBY8FB6yPIjrtKhozXv4FQupxKLS6H4m6xFZlT43q8Q=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/gopcua/opcua v0.5.3 h1:K5QQhjK9KQxQW8doHL/Cd8oljUeXWnJJsNgP7mOGIhw=
github.com/gopcua/opcua v0.5.3/go.mod h1:nrVl4/Rs3SDQRhNQ50EbAiI5JSpDrTG6Frx3s4HLnw4=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hdm/jarm-go v0.0.7 h1:Eq0geenHrBSYuKrdVhrBdMMzOmA+CAMLzN2WrF3eL6A=
Expand All @@ -47,6 +49,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
Expand Down
Empty file modified integration_tests/.template/cleanup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/.template/container/entrypoint.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/.template/setup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/.template/test.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/cleanup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/ftp/cleanup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/ftp/container/entrypoint.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/ftp/setup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/ftp/test.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/http/cleanup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/http/setup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/http/test.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/ipp/cleanup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/ipp/container-cups-tls/Dockerfile
100755 → 100644
Empty file.
Empty file modified integration_tests/ipp/container-cups-tls/entrypoint.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/ipp/container-cups/Dockerfile
100755 → 100644
Empty file.
Empty file modified integration_tests/ipp/container-cups/entrypoint.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/ipp/setup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/ipp/test.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/mongodb/cleanup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/mongodb/setup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/mongodb/test.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/mssql/cleanup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/mssql/setup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/mssql/test.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/mysql/cleanup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/mysql/setup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/mysql/test.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/new.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/ntp/cleanup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/ntp/setup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/ntp/test.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/pop3/cleanup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/pop3/container/entrypoint.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/pop3/setup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/pop3/test.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/postgres/cleanup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/postgres/container/build.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/postgres/container/setup_nossl.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/postgres/container/setup_ssl.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/postgres/setup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/postgres/test.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/redis/cleanup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/redis/setup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/redis/test.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/setup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/smtp/cleanup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/smtp/container/entrypoint.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/smtp/setup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/smtp/test.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/ssh/cleanup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/ssh/setup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/ssh/test.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/telnet/cleanup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/telnet/container/entrypoint.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/telnet/setup.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/telnet/test.sh
100755 → 100644
Empty file.
Empty file modified integration_tests/test.sh
100755 → 100644
Empty file.
3 changes: 1 addition & 2 deletions modules/coap/scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,7 @@ func (scanner *Scanner) newCoAPscan(t *zgrab2.ScanTarget) *scan {

func (scanner *Scanner) Scan(t zgrab2.ScanTarget) (zgrab2.ScanStatus, interface{}, error) {
scan := scanner.newCoAPscan(&t)
err := scan.Grab()
if err != nil {
if err := scan.Grab(); err != nil {
return err.Unpack(&scan.results)
}
return zgrab2.SCAN_SUCCESS, &scan.results, nil
Expand Down
7 changes: 7 additions & 0 deletions modules/opcua.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package modules

import "github.com/zmap/zgrab2/modules/opcua"

func init() {
opcua.RegisterModule()
}
234 changes: 234 additions & 0 deletions modules/opcua/browse.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
package opcua

import (
"context"

"github.com/gopcua/opcua"
"github.com/gopcua/opcua/id"
"github.com/gopcua/opcua/ua"
"github.com/pkg/errors"
"github.com/zmap/zgrab2"
)

type NodeDef struct {
NodeID *ua.NodeID `json:"nodeID"`
NodeClass ua.NodeClass `json:"nodeClass"`
BrowseName string `json:"browseName"`
Description string `json:"description"`
AccessLevel ua.AccessLevelType `json:"accessLevel"`
Path string `json:"path"`
DataType string `json:"dataType"`
Writable bool `json:"writable"`
}

func (n *NodeDef) SetNodeClass(v *ua.DataValue) error {
switch err := v.Status; err {
case ua.StatusOK:
n.NodeClass = ua.NodeClass(v.Value.Int())
return nil
default:
return err
}
}

func (n *NodeDef) SetBrowseName(v *ua.DataValue) error {
switch err := v.Status; err {
case ua.StatusOK:
n.BrowseName = v.Value.String()
return nil
default:
return err
}
}

func (n *NodeDef) SetDescription(v *ua.DataValue) error {
switch err := v.Status; err {
case ua.StatusOK:
if v.Value != nil {
n.Description = v.Value.String()
}
return nil
case ua.StatusBadAttributeIDInvalid:
return nil
default:
return err
}
}

func (n *NodeDef) SetAccessLevel(v *ua.DataValue) error {
switch err := v.Status; err {
case ua.StatusOK:
n.AccessLevel = ua.AccessLevelType(v.Value.Int())
n.Writable = n.AccessLevel&ua.AccessLevelTypeCurrentWrite == ua.AccessLevelTypeCurrentWrite
return nil
case ua.StatusBadAttributeIDInvalid:
return nil
default:
return err
}
}

func (n *NodeDef) SetDataType(dt *ua.DataValue) error {
switch err := dt.Status; err {
case ua.StatusOK:
switch v := dt.Value.NodeID().IntID(); v {
case id.DateTime:
n.DataType = "time.Time"
case id.Boolean:
n.DataType = "bool"
case id.SByte:
n.DataType = "int8"
case id.Int16:
n.DataType = "int16"
case id.Int32:
n.DataType = "int32"
case id.Byte:
n.DataType = "byte"
case id.UInt16:
n.DataType = "uint16"
case id.UInt32:
n.DataType = "uint32"
case id.UtcTime:
n.DataType = "time.Time"
case id.String:
n.DataType = "string"
case id.Float:
n.DataType = "float32"
case id.Double:
n.DataType = "float64"
default:
n.DataType = dt.Value.NodeID().String()
}
return nil
case ua.StatusBadAttributeIDInvalid:
return nil
default:
return err
}
}

type EndpointResult struct {
Error *zgrab2.ScanError `json:"error,omitempty"`
EndpointDescription *ua.EndpointDescription
Authenticated []string `json:"authentication"`
Endpoint map[string]interface{} `json:"endpoint"`
Nodes []*NodeDef `json:"nodes"`
Namespaces []string `json:"namespaces"`
}

func newEndpoint(ep *ua.EndpointDescription) *EndpointResult {
return &EndpointResult{
EndpointDescription: ep,
Authenticated: []string{},
}
}

type Results struct {
Endpoints []*EndpointResult `json:"endpoints,omitempty"`
}

type browser struct {
level uint
maxLevel uint
ctx context.Context
}

func newBrowser(level uint, ctx context.Context) *browser {
b := &browser{
ctx: ctx,
maxLevel: 10,
}
b.setLevel(level)

return b
}

func (b *browser) setLevel(level uint) {
if level > b.maxLevel {
panic(errors.Errorf("failed to set browser level. The maximum level is %d, but attempted to set %d", b.maxLevel, level))
}
b.level = level
}

func (b *browser) Node(n *opcua.Node) (*NodeDef, error) {
var def = &NodeDef{
NodeID: n.ID,
}

// NOTE: We do not need to know anything else about the node
// If you are modifying this, please be aware of possible
// ethical issues. Reading values from nodes will not offer
// more insights.
attrs, err := n.Attributes(
b.ctx,
ua.AttributeIDNodeClass,
ua.AttributeIDBrowseName,
ua.AttributeIDDescription,
ua.AttributeIDAccessLevel,
ua.AttributeIDDataType,
)
if err != nil {
return def, err
}

for i, f := range []func(v *ua.DataValue) error{
def.SetNodeClass,
def.SetBrowseName,
def.SetDescription,
def.SetAccessLevel,
def.SetDataType,
} {
if err := f(attrs[i]); err != nil {
return def, err
}
}

return def, nil
}

func (b *browser) getChildren(refType uint32, n *opcua.Node, path string, level int) ([]*NodeDef, error) {
refs, err := n.ReferencedNodes(b.ctx, refType, ua.BrowseDirectionForward, ua.NodeClassAll, true)
if err != nil {
return nil, errors.Errorf("References: %d: %s", refType, err)
}

var nodes []*NodeDef
for _, rn := range refs {
children, err := b.browse(rn, path, level+1)
if err != nil {
return nil, errors.Errorf("browse children: %s", err)
}
nodes = append(nodes, children...)
}
return nodes, nil
}

func (b *browser) browse(n *opcua.Node, path string, level int) ([]*NodeDef, error) {
if level > int(b.level) {
return nil, nil
}

def, err := b.Node(n)
if err != nil {
return nil, err
}
def.Path = join(path, def.BrowseName)

var nodes []*NodeDef
nodes = append(nodes, def)
for _, refType := range []uint32{id.HasComponent, id.Organizes, id.HasProperty} {
nChilds, err := b.getChildren(refType, n, def.Path, level)
if err != nil {
return nil, err
}
nodes = append(nodes, nChilds...)
}
return nodes, nil
}

func join(a, b string) string {
if a == "" {
return b
}
return a + "." + b
}
66 changes: 66 additions & 0 deletions modules/opcua/opcua_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package opcua

import (
"testing"

"github.com/zmap/zgrab2"
)

type opcuaTester struct {
address string
port uint
uri string
certHost string
endpoint string
level uint
}

func (cfg *opcuaTester) getScanner() (*Scanner, error) {
var module Module
flags := module.NewFlags().(*Flags)
flags.Uri = cfg.uri
flags.CertHost = cfg.certHost
flags.Endpoint = cfg.endpoint
flags.BrowseDepth = cfg.level

scanner := module.NewScanner()
if err := scanner.Init(flags); err != nil {
return nil, err
}
return scanner.(*Scanner), nil
}

func (cfg *opcuaTester) runTest(t *testing.T, testName string) {
target := zgrab2.ScanTarget{
Port: &cfg.port,
Domain: cfg.address,
}

scanner, err := cfg.getScanner()
if err != nil {
t.Fatalf("[%s] Unexpected error: %v", testName, err)
}

st, res, err := scanner.Scan(target)
if err != nil {
t.Fatalf("[%s] error while scanning: %v, %v", testName, err, st)
}
t.Logf("%+v", res)
}

var tests = map[string]*opcuaTester{
"demo": {
address: "opcua.demo-this.com",
port: 51210,
uri: "urn:opcua:scanner",
certHost: "localhost",
endpoint: "UA/SampleServer",
level: 2,
},
}

func TestOPCUA(t *testing.T) {
for tname, cfg := range tests {
cfg.runTest(t, tname)
}
}
Loading

0 comments on commit 4b736d3

Please sign in to comment.