Skip to content

Commit 2d3168b

Browse files
authored
Merge pull request #6735 from projectdiscovery/dwisiswant0/fix/js/mysql-panic-due-to-missing-executionId-in-ctx
fix(js): mysql panic due to missing `executionId` in ctx
2 parents 880898f + 05ff121 commit 2d3168b

File tree

19 files changed

+119
-34
lines changed

19 files changed

+119
-34
lines changed

cmd/integration-test/javascript.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ var jsTestcases = []TestCaseInfo{
1818
{Path: "protocols/javascript/oracle-auth-test.yaml", TestCase: &javascriptOracleAuthTest{}, DisableOn: func() bool { return osutils.IsWindows() || osutils.IsOSX() }},
1919
{Path: "protocols/javascript/vnc-pass-brute.yaml", TestCase: &javascriptVncPassBrute{}},
2020
{Path: "protocols/javascript/postgres-pass-brute.yaml", TestCase: &javascriptPostgresPassBrute{}, DisableOn: func() bool { return osutils.IsWindows() || osutils.IsOSX() }},
21+
{Path: "protocols/javascript/mysql-connect.yaml", TestCase: &javascriptMySQLConnect{}, DisableOn: func() bool { return osutils.IsWindows() || osutils.IsOSX() }},
2122
{Path: "protocols/javascript/multi-ports.yaml", TestCase: &javascriptMultiPortsSSH{}},
2223
{Path: "protocols/javascript/no-port-args.yaml", TestCase: &javascriptNoPortArgs{}},
2324
}
@@ -28,6 +29,7 @@ var (
2829
oracleResource *dockertest.Resource
2930
vncResource *dockertest.Resource
3031
postgresResource *dockertest.Resource
32+
mysqlResource *dockertest.Resource
3133
pool *dockertest.Pool
3234
defaultRetry = 3
3335
)
@@ -203,6 +205,38 @@ func (j *javascriptPostgresPassBrute) Execute(filePath string) error {
203205
return multierr.Combine(errs...)
204206
}
205207

208+
type javascriptMySQLConnect struct{}
209+
210+
func (j *javascriptMySQLConnect) Execute(filePath string) error {
211+
if mysqlResource == nil || pool == nil {
212+
// skip test as mysql is not running
213+
return nil
214+
}
215+
tempPort := mysqlResource.GetPort("3306/tcp")
216+
finalURL := "localhost:" + tempPort
217+
defer purge(mysqlResource)
218+
errs := []error{}
219+
for i := 0; i < defaultRetry; i++ {
220+
results := []string{}
221+
var err error
222+
_ = pool.Retry(func() error {
223+
//let mysql server start
224+
time.Sleep(5 * time.Second)
225+
results, err = testutils.RunNucleiTemplateAndGetResults(filePath, finalURL, debug)
226+
return nil
227+
})
228+
if err != nil {
229+
return err
230+
}
231+
if err := expectResultsCount(results, 1); err == nil {
232+
return nil
233+
} else {
234+
errs = append(errs, err)
235+
}
236+
}
237+
return multierr.Combine(errs...)
238+
}
239+
206240
type javascriptMultiPortsSSH struct{}
207241

208242
func (j *javascriptMultiPortsSSH) Execute(filePath string) error {
@@ -345,4 +379,22 @@ func init() {
345379
if err := postgresResource.Expire(30); err != nil {
346380
log.Printf("Could not expire postgres resource: %s", err)
347381
}
382+
383+
// setup a temporary mysql instance
384+
mysqlResource, err = pool.RunWithOptions(&dockertest.RunOptions{
385+
Repository: "mysql",
386+
Tag: "latest",
387+
Env: []string{
388+
"MYSQL_ROOT_PASSWORD=secret",
389+
},
390+
Platform: "linux/amd64",
391+
})
392+
if err != nil {
393+
log.Printf("Could not start mysql resource: %s", err)
394+
return
395+
}
396+
// by default expire after 30 sec
397+
if err := mysqlResource.Expire(30); err != nil {
398+
log.Printf("Could not expire mysql resource: %s", err)
399+
}
348400
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
id: mysql-connect
2+
3+
info:
4+
name: MySQL Connect Test
5+
author: pdteam
6+
severity: high
7+
8+
javascript:
9+
- pre-condition: |
10+
isPortOpen(Host, Port)
11+
code: |
12+
const mysql = require('nuclei/mysql');
13+
const client = new mysql.MySQLClient;
14+
success = client.Connect(Host, Port, User, Pass);
15+
args:
16+
Host: "{{Host}}"
17+
Port: "3306"
18+
User: "root"
19+
Pass: "secret"
20+
matchers:
21+
- type: dsl
22+
dsl:
23+
- "success == true"

pkg/js/libs/mssql/memo.mssql.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
)
1212

1313
func memoizedconnect(executionId string, host string, port int, username string, password string, dbName string) (bool, error) {
14-
hash := "connect" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) + ":" + fmt.Sprint(username) + ":" + fmt.Sprint(password) + ":" + fmt.Sprint(dbName)
14+
hash := "connect" + ":" + fmt.Sprint(executionId) + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) + ":" + fmt.Sprint(username) + ":" + fmt.Sprint(password) + ":" + fmt.Sprint(dbName)
1515

1616
v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) {
1717
return connect(executionId, host, port, username, password, dbName)
@@ -27,7 +27,7 @@ func memoizedconnect(executionId string, host string, port int, username string,
2727
}
2828

2929
func memoizedisMssql(executionId string, host string, port int) (bool, error) {
30-
hash := "isMssql" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port)
30+
hash := "isMssql" + ":" + fmt.Sprint(executionId) + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port)
3131

3232
v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) {
3333
return isMssql(executionId, host, port)

pkg/js/libs/mysql/memo.mysql.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
)
1010

1111
func memoizedisMySQL(executionId string, host string, port int) (bool, error) {
12-
hash := "isMySQL" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port)
12+
hash := "isMySQL" + ":" + fmt.Sprint(executionId) + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port)
1313

1414
v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) {
1515
return isMySQL(executionId, host, port)
@@ -25,7 +25,7 @@ func memoizedisMySQL(executionId string, host string, port int) (bool, error) {
2525
}
2626

2727
func memoizedfingerprintMySQL(executionId string, host string, port int) (MySQLInfo, error) {
28-
hash := "fingerprintMySQL" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port)
28+
hash := "fingerprintMySQL" + ":" + fmt.Sprint(executionId) + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port)
2929

3030
v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) {
3131
return fingerprintMySQL(executionId, host, port)

pkg/js/libs/mysql/memo.mysql_private.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ import (
88
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
99
)
1010

11-
func memoizedconnectWithDSN(dsn string) (bool, error) {
12-
hash := "connectWithDSN" + ":" + fmt.Sprint(dsn)
11+
func memoizedconnectWithDSN(executionId string, dsn string) (bool, error) {
12+
hash := "connectWithDSN" + ":" + fmt.Sprint(executionId) + ":" + fmt.Sprint(dsn)
1313

1414
v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) {
15-
return connectWithDSN(dsn)
15+
return connectWithDSN(executionId, dsn)
1616
})
1717
if err != nil {
1818
return false, err

pkg/js/libs/mysql/mysql.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ func (c *MySQLClient) Connect(ctx context.Context, host string, port int, userna
108108
if err != nil {
109109
return false, err
110110
}
111-
return connectWithDSN(dsn)
111+
return connectWithDSN(executionId, dsn)
112112
}
113113

114114
type (
@@ -190,8 +190,9 @@ func fingerprintMySQL(executionId string, host string, port int) (MySQLInfo, err
190190
// const client = new mysql.MySQLClient;
191191
// const connected = client.ConnectWithDSN('username:password@tcp(acme.com:3306)/');
192192
// ```
193-
func (c *MySQLClient) ConnectWithDSN(dsn string) (bool, error) {
194-
return memoizedconnectWithDSN(dsn)
193+
func (c *MySQLClient) ConnectWithDSN(ctx context.Context, dsn string) (bool, error) {
194+
executionId := ctx.Value("executionId").(string)
195+
return memoizedconnectWithDSN(executionId, dsn)
195196
}
196197

197198
// ExecuteQueryWithOpts connects to Mysql database using given credentials

pkg/js/libs/mysql/mysql_private.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package mysql
22

33
import (
4+
"context"
45
"database/sql"
56
"fmt"
67
"net"
@@ -72,7 +73,7 @@ func BuildDSN(opts MySQLOptions) (string, error) {
7273
}
7374

7475
// @memo
75-
func connectWithDSN(dsn string) (bool, error) {
76+
func connectWithDSN(executionId string, dsn string) (bool, error) {
7677
db, err := sql.Open("mysql", dsn)
7778
if err != nil {
7879
return false, err
@@ -83,7 +84,8 @@ func connectWithDSN(dsn string) (bool, error) {
8384
db.SetMaxOpenConns(1)
8485
db.SetMaxIdleConns(0)
8586

86-
_, err = db.Exec("select 1")
87+
ctx := context.WithValue(context.Background(), "executionId", executionId) // nolint: staticcheck
88+
err = db.PingContext(ctx)
8789
if err != nil {
8890
return false, err
8991
}

pkg/js/libs/oracle/memo.oracle.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
)
1010

1111
func memoizedisOracle(executionId string, host string, port int) (IsOracleResponse, error) {
12-
hash := "isOracle" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port)
12+
hash := "isOracle" + ":" + fmt.Sprint(executionId) + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port)
1313

1414
v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) {
1515
return isOracle(executionId, host, port)

pkg/js/libs/pop3/memo.pop3.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
)
1010

1111
func memoizedisPoP3(executionId string, host string, port int) (IsPOP3Response, error) {
12-
hash := "isPoP3" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port)
12+
hash := "isPoP3" + ":" + fmt.Sprint(executionId) + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port)
1313

1414
v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) {
1515
return isPoP3(executionId, host, port)

pkg/js/libs/postgres/memo.postgres.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ import (
55
"errors"
66
"fmt"
77

8-
_ "github.com/projectdiscovery/nuclei/v3/pkg/js/utils/pgwrap"
9-
108
utils "github.com/projectdiscovery/nuclei/v3/pkg/js/utils"
119

10+
_ "github.com/projectdiscovery/nuclei/v3/pkg/js/utils/pgwrap"
11+
1212
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
1313
)
1414

1515
func memoizedisPostgres(executionId string, host string, port int) (bool, error) {
16-
hash := "isPostgres" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port)
16+
hash := "isPostgres" + ":" + fmt.Sprint(executionId) + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port)
1717

1818
v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) {
1919
return isPostgres(executionId, host, port)
@@ -29,7 +29,7 @@ func memoizedisPostgres(executionId string, host string, port int) (bool, error)
2929
}
3030

3131
func memoizedexecuteQuery(executionId string, host string, port int, username string, password string, dbName string, query string) (*utils.SQLResult, error) {
32-
hash := "executeQuery" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) + ":" + fmt.Sprint(username) + ":" + fmt.Sprint(password) + ":" + fmt.Sprint(dbName) + ":" + fmt.Sprint(query)
32+
hash := "executeQuery" + ":" + fmt.Sprint(executionId) + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) + ":" + fmt.Sprint(username) + ":" + fmt.Sprint(password) + ":" + fmt.Sprint(dbName) + ":" + fmt.Sprint(query)
3333

3434
v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) {
3535
return executeQuery(executionId, host, port, username, password, dbName, query)
@@ -45,7 +45,7 @@ func memoizedexecuteQuery(executionId string, host string, port int, username st
4545
}
4646

4747
func memoizedconnect(executionId string, host string, port int, username string, password string, dbName string) (bool, error) {
48-
hash := "connect" + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) + ":" + fmt.Sprint(username) + ":" + fmt.Sprint(password) + ":" + fmt.Sprint(dbName)
48+
hash := "connect" + ":" + fmt.Sprint(executionId) + ":" + fmt.Sprint(host) + ":" + fmt.Sprint(port) + ":" + fmt.Sprint(username) + ":" + fmt.Sprint(password) + ":" + fmt.Sprint(dbName)
4949

5050
v, err, _ := protocolstate.Memoizer.Do(hash, func() (interface{}, error) {
5151
return connect(executionId, host, port, username, password, dbName)

0 commit comments

Comments
 (0)