From f20f95f67e1de02f77be203fe071a61f9dcfbbd1 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Mon, 25 Aug 2025 15:13:23 +0200 Subject: [PATCH] integration test --- cmd/integration-test/javascript.go | 52 +++++++++++++++++++ .../protocols/javascript/vnc-pass-brute.yaml | 38 ++++++++++++++ pkg/js/libs/vnc/vnc.go | 7 ++- 3 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 integration_tests/protocols/javascript/vnc-pass-brute.yaml diff --git a/cmd/integration-test/javascript.go b/cmd/integration-test/javascript.go index e45f122c3..064162dc8 100644 --- a/cmd/integration-test/javascript.go +++ b/cmd/integration-test/javascript.go @@ -15,11 +15,13 @@ var jsTestcases = []TestCaseInfo{ {Path: "protocols/javascript/ssh-server-fingerprint.yaml", TestCase: &javascriptSSHServerFingerprint{}, DisableOn: func() bool { return osutils.IsWindows() || osutils.IsOSX() }}, {Path: "protocols/javascript/net-multi-step.yaml", TestCase: &networkMultiStep{}}, {Path: "protocols/javascript/net-https.yaml", TestCase: &javascriptNetHttps{}}, + {Path: "protocols/javascript/vnc-pass-brute.yaml", TestCase: &javascriptVncPassBrute{}}, } var ( redisResource *dockertest.Resource sshResource *dockertest.Resource + vncResource *dockertest.Resource pool *dockertest.Pool defaultRetry = 3 ) @@ -98,6 +100,38 @@ func (j *javascriptSSHServerFingerprint) Execute(filePath string) error { return multierr.Combine(errs...) } +type javascriptVncPassBrute struct{} + +func (j *javascriptVncPassBrute) Execute(filePath string) error { + if vncResource == nil || pool == nil { + // skip test as vnc is not running + return nil + } + tempPort := vncResource.GetPort("5900/tcp") + finalURL := "localhost:" + tempPort + defer purge(vncResource) + errs := []error{} + for i := 0; i < defaultRetry; i++ { + results := []string{} + var err error + _ = pool.Retry(func() error { + //let ssh server start + time.Sleep(3 * time.Second) + results, err = testutils.RunNucleiTemplateAndGetResults(filePath, finalURL, debug) + return nil + }) + if err != nil { + return err + } + if err := expectResultsCount(results, 1); err == nil { + return nil + } else { + errs = append(errs, err) + } + } + return multierr.Combine(errs...) +} + // purge any given resource if it is not nil func purge(resource *dockertest.Resource) { if resource != nil && pool != nil { @@ -163,4 +197,22 @@ func init() { if err := sshResource.Expire(30); err != nil { log.Printf("Could not expire resource: %s", err) } + + // setup a temporary vnc server + vncResource, err = pool.RunWithOptions(&dockertest.RunOptions{ + Repository: "dorowu/ubuntu-desktop-lxde-vnc", + Tag: "latest", + Env: []string{ + "VNC_PASSWORD=mysecret", + }, + Platform: "linux/amd64", + }) + if err != nil { + log.Printf("Could not start resource: %s", err) + return + } + // by default expire after 30 sec + if err := vncResource.Expire(30); err != nil { + log.Printf("Could not expire resource: %s", err) + } } diff --git a/integration_tests/protocols/javascript/vnc-pass-brute.yaml b/integration_tests/protocols/javascript/vnc-pass-brute.yaml new file mode 100644 index 000000000..68cb9df62 --- /dev/null +++ b/integration_tests/protocols/javascript/vnc-pass-brute.yaml @@ -0,0 +1,38 @@ +id: vnc-password-test + +info: + name: VNC Password Authentication Test + author: pdteam + severity: high + description: | + Tests VNC authentication with correct and incorrect passwords. + metadata: + shodan-query: product:"vnc" + tags: js,network,vnc,authentication + +javascript: + - pre-condition: | + isPortOpen(Host,Port) + + code: | + let vnc = require('nuclei/vnc'); + let client = new vnc.VNCClient(); + client.Connect(Host, Port, Password); + + args: + Host: "{{Host}}" + Port: "5900" + Password: "{{passwords}}" + payloads: + passwords: + - "" + - root + - password + - admin + - mysecret + stop-at-first-match: true + + matchers: + - type: dsl + dsl: + - "success == true" diff --git a/pkg/js/libs/vnc/vnc.go b/pkg/js/libs/vnc/vnc.go index c1aaf8103..16103c30d 100644 --- a/pkg/js/libs/vnc/vnc.go +++ b/pkg/js/libs/vnc/vnc.go @@ -83,7 +83,7 @@ func connect(executionId string, host string, port int, password string) (bool, vncConfig := vnclib.NewClientConfig(password) // Attempt to connect and authenticate - _, err = vnclib.Connect(context.TODO(), conn, vncConfig) + c, err := vnclib.Connect(context.TODO(), conn, vncConfig) if err != nil { // Check for specific authentication errors if isAuthError(err) { @@ -91,6 +91,9 @@ func connect(executionId string, host string, port int, password string) (bool, } return false, err // Connection or other error } + if c != nil { + _ = c.Close() + } return true, nil } @@ -103,7 +106,7 @@ func isAuthError(err error) bool { // Check for common VNC authentication error messages errStr := err.Error() - return stringsutil.ContainsAny(errStr, "authentication", "auth", "password", "invalid", "failed") + return stringsutil.ContainsAnyI(errStr, "authentication", "auth", "password", "invalid", "failed") } // IsVNC checks if a host is running a VNC server.