[INS-243] Fix jdbc detector detecting incomplete connection string and fixed invalid… (#4636)
Lint / golangci-lint (push) Waiting to run
Lint / semgrep (push) Waiting to run
Release / Release (push) Waiting to run
Scan for secrets / test (push) Waiting to run
Test / test (push) Waiting to run
Test / test-community (push) Waiting to run
Lint / golangci-lint (push) Waiting to run
Lint / semgrep (push) Waiting to run
Release / Release (push) Waiting to run
Scan for secrets / test (push) Waiting to run
Test / test (push) Waiting to run
Test / test-community (push) Waiting to run
* Fix jdbc detector detecting incomplete conn string and fixed invalid parsing of sql server string * [INS-165] Jdbc detector integration tests fix (#4637) * [INS-165] Fix Jdbc tests and updated the deprecated code
This commit is contained in:
@@ -50,7 +50,8 @@ var _ detectors.Detector = (*Scanner)(nil)
|
||||
var _ detectors.CustomFalsePositiveChecker = (*Scanner)(nil)
|
||||
|
||||
var (
|
||||
keyPat = regexp.MustCompile(`(?i)jdbc:[\w]{3,10}:[^\s"'<>,(){}[\]&]{10,512}`)
|
||||
// Matches typical JDBC connection strings amd ingores any special character at the end
|
||||
keyPat = regexp.MustCompile(`(?i)jdbc:[\w]{3,10}:[^\s"'<>,{}[\]]{10,511}[A-Za-z0-9]`)
|
||||
)
|
||||
|
||||
// Keywords are used for efficiently pre-filtering chunks.
|
||||
|
||||
@@ -29,8 +29,8 @@ func TestJdbcVerified(t *testing.T) {
|
||||
postgresUser := gofakeit.Username()
|
||||
postgresPass := gofakeit.Password(true, true, true, false, false, 10)
|
||||
postgresDB := gofakeit.Word()
|
||||
postgresContainer, err := postgres.RunContainer(ctx,
|
||||
testcontainers.WithImage("postgres:13-alpine"),
|
||||
postgresContainer, err := postgres.Run(ctx,
|
||||
"postgres:13-alpine",
|
||||
postgres.WithDatabase(postgresDB),
|
||||
postgres.WithUsername(postgresUser),
|
||||
postgres.WithPassword(postgresPass),
|
||||
@@ -56,8 +56,8 @@ func TestJdbcVerified(t *testing.T) {
|
||||
mysqlUser := gofakeit.Username()
|
||||
mysqlPass := gofakeit.Password(true, true, true, false, false, 10)
|
||||
mysqlDatabase := gofakeit.Word()
|
||||
mysqlC, err := mysql.RunContainer(ctx,
|
||||
mysql.WithDatabase(mysqlDatabase),
|
||||
mysqlC, err := mysql.Run(ctx,
|
||||
"mysql:8.0.36",
|
||||
mysql.WithUsername(mysqlUser),
|
||||
mysql.WithPassword(mysqlPass),
|
||||
)
|
||||
@@ -79,8 +79,8 @@ func TestJdbcVerified(t *testing.T) {
|
||||
sqlServerPass := gofakeit.Password(true, true, true, false, false, 10)
|
||||
sqlServerDatabase := "master"
|
||||
|
||||
mssqlContainer, err := mssql.RunContainer(ctx,
|
||||
testcontainers.WithImage("mcr.microsoft.com/azure-sql-edge"),
|
||||
mssqlContainer, err := mssql.Run(ctx,
|
||||
"mcr.microsoft.com/azure-sql-edge",
|
||||
mssql.WithAcceptEULA(),
|
||||
mssql.WithPassword(sqlServerPass),
|
||||
)
|
||||
@@ -125,6 +125,10 @@ func TestJdbcVerified(t *testing.T) {
|
||||
Verified: true,
|
||||
Redacted: fmt.Sprintf("jdbc:postgresql://%s:%s/%s?sslmode=disable&password=%s&user=%s",
|
||||
postgresHost, postgresPort.Port(), postgresDB, strings.Repeat("*", len(postgresPass)), postgresUser),
|
||||
AnalysisInfo: map[string]string{
|
||||
"connection_string": fmt.Sprintf("jdbc:postgresql://%s:%s/%s?sslmode=disable&password=%s&user=%s",
|
||||
postgresHost, postgresPort.Port(), postgresDB, postgresPass, postgresUser),
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
@@ -143,6 +147,10 @@ func TestJdbcVerified(t *testing.T) {
|
||||
Verified: true,
|
||||
Redacted: fmt.Sprintf(`jdbc:mysql://%s:%s@tcp(%s:%s)/%s`,
|
||||
mysqlUser, strings.Repeat("*", len(mysqlPass)), mysqlHost, mysqlPort.Port(), mysqlDatabase),
|
||||
AnalysisInfo: map[string]string{
|
||||
"connection_string": fmt.Sprintf(`jdbc:mysql://%s:%s@tcp(%s:%s)/%s`,
|
||||
mysqlUser, mysqlPass, mysqlHost, mysqlPort.Port(), mysqlDatabase),
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
@@ -161,6 +169,10 @@ func TestJdbcVerified(t *testing.T) {
|
||||
Verified: true,
|
||||
Redacted: fmt.Sprintf("jdbc:sqlserver://odbc:server=%s;port=%s;database=%s;password=%s",
|
||||
sqlServerHost, sqlServerPort.Port(), sqlServerDatabase, strings.Repeat("*", len(sqlServerPass))),
|
||||
AnalysisInfo: map[string]string{
|
||||
"connection_string": fmt.Sprintf("jdbc:sqlserver://odbc:server=%s;port=%s;database=%s;password=%s",
|
||||
sqlServerHost, sqlServerPort.Port(), sqlServerDatabase, sqlServerPass),
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
|
||||
@@ -40,6 +40,8 @@ func TestJdbc_Pattern(t *testing.T) {
|
||||
<jdbc-url>jdbc:mysql:localhost:3306/mydatabase</jdbc-url>
|
||||
<jdbc-url>jdbc:sqlserver://x.x.x.x:1433;databaseName=MY-DB;user=MY-USER;password=MY-PASSWORD;encrypt=false</jdbc-url>
|
||||
<jdbc-url>jdbc:sqlserver://localhost:1433;databaseName=AdventureWorks</jdbc-url>
|
||||
<jdbc-url>(jdbc:mysql://testuser:testpassword@tcp(localhost:1521)/testdb)</jdbc-url>
|
||||
<jdbc-url>jdbc:postgresql://localhost:1521/testdb?sslmode=disable&password=testpassword&user=testuser&</jdbc-url>
|
||||
<working-dir>$ProjectFileDir$</working-dir>
|
||||
</data-source>
|
||||
</component>
|
||||
@@ -50,6 +52,8 @@ func TestJdbc_Pattern(t *testing.T) {
|
||||
"jdbc:mysql:localhost:3306/mydatabase",
|
||||
"jdbc:sqlserver://x.x.x.x:1433;databaseName=MY-DB;user=MY-USER;password=MY-PASSWORD;encrypt=false",
|
||||
"jdbc:sqlserver://localhost:1433;databaseName=AdventureWorks",
|
||||
"jdbc:mysql://testuser:testpassword@tcp(localhost:1521)/testdb",
|
||||
"jdbc:postgresql://localhost:1521/testdb?sslmode=disable&password=testpassword&user=testuser",
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -64,8 +68,10 @@ func TestJdbc_Pattern(t *testing.T) {
|
||||
"jdbc:oracle:thin:@host:1521:db",
|
||||
"jdbc:mysql://host:3306/db,other_param",
|
||||
"jdbc:db2://host:50000/db?param=1"
|
||||
]
|
||||
}`,
|
||||
"jdbc:postgresql://localhost:1521/testdb?sslmode=disable&password=testpassword&user=testuser"
|
||||
"jdbc:mysql://testuser:testpassword@tcp(localhost:1521)/testdb"
|
||||
]
|
||||
}`,
|
||||
want: []string{
|
||||
"jdbc:postgresql://localhost:5432/mydb",
|
||||
"jdbc:mysql://user:pass@host:3306/db?param=1",
|
||||
@@ -73,6 +79,8 @@ func TestJdbc_Pattern(t *testing.T) {
|
||||
"jdbc:oracle:thin:@host:1521:db",
|
||||
"jdbc:mysql://host:3306/db",
|
||||
"jdbc:db2://host:50000/db?param=1",
|
||||
"jdbc:postgresql://localhost:1521/testdb?sslmode=disable&password=testpassword&user=testuser",
|
||||
"jdbc:mysql://testuser:testpassword@tcp(localhost:1521)/testdb",
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -23,7 +23,8 @@ func TestMySQL(t *testing.T) {
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
mysqlC, err := mysql.RunContainer(ctx,
|
||||
mysqlC, err := mysql.Run(ctx,
|
||||
"mysql:8.0.36",
|
||||
mysql.WithDatabase(mysqlDatabase),
|
||||
mysql.WithUsername(mysqlUser),
|
||||
mysql.WithPassword(mysqlPass),
|
||||
|
||||
@@ -6,7 +6,6 @@ package jdbc
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -34,8 +33,8 @@ func TestPostgres(t *testing.T) {
|
||||
t.Log("dbName: ", dbName)
|
||||
|
||||
ctx := context.Background()
|
||||
postgresContainer, err := postgres.RunContainer(ctx,
|
||||
testcontainers.WithImage("postgres:13-alpine"),
|
||||
postgresContainer, err := postgres.Run(ctx,
|
||||
"postgres:13-alpine",
|
||||
postgres.WithDatabase(dbName),
|
||||
postgres.WithUsername(user),
|
||||
postgres.WithPassword(pass),
|
||||
@@ -56,10 +55,6 @@ func TestPostgres(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("failed to start container: %s", err)
|
||||
}
|
||||
defer postgresContainer.Terminate(ctx)
|
||||
|
||||
tests := []struct {
|
||||
|
||||
@@ -73,6 +73,11 @@ func parseSqlServer(ctx logContext.Context, subname string) (JDBC, error) {
|
||||
continue
|
||||
}
|
||||
|
||||
// incase there is a bridge between jdbc and some driver like "odbc", and conn string looks like this odbc:server
|
||||
if split := strings.Split(key, ":"); len(split) > 1 {
|
||||
key = split[1]
|
||||
}
|
||||
|
||||
switch strings.ToLower(key) {
|
||||
case "password", "spring.datasource.password", "pwd":
|
||||
password = value
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
|
||||
"github.com/brianvoe/gofakeit/v7"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/testcontainers/testcontainers-go"
|
||||
"github.com/testcontainers/testcontainers-go/modules/mssql"
|
||||
logContext "github.com/trufflesecurity/trufflehog/v3/pkg/context"
|
||||
)
|
||||
|
||||
func TestSqlServer(t *testing.T) {
|
||||
@@ -21,8 +21,8 @@ func TestSqlServer(t *testing.T) {
|
||||
sqlServerPass := gofakeit.Password(true, true, true, false, false, 10)
|
||||
sqlServerDB := "master"
|
||||
|
||||
mssqlContainer, err := mssql.RunContainer(ctx,
|
||||
testcontainers.WithImage("mcr.microsoft.com/azure-sql-edge"),
|
||||
mssqlContainer, err := mssql.Run(ctx,
|
||||
"mcr.microsoft.com/azure-sql-edge",
|
||||
mssql.WithAcceptEULA(),
|
||||
mssql.WithPassword(sqlServerPass),
|
||||
)
|
||||
@@ -61,7 +61,7 @@ func TestSqlServer(t *testing.T) {
|
||||
want: result{pingOk: true, pingDeterminate: true},
|
||||
},
|
||||
{
|
||||
input: "//server=badhost;user id=sa;database=master;password=",
|
||||
input: fmt.Sprintf("//server=badhost;user id=sa;database=master;password=%s", sqlServerPass),
|
||||
want: result{pingOk: false, pingDeterminate: false},
|
||||
},
|
||||
{
|
||||
@@ -81,7 +81,8 @@ func TestSqlServer(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.input, func(t *testing.T) {
|
||||
j, err := parseSqlServer(tt.input)
|
||||
ctx := logContext.AddLogger(context.Background())
|
||||
j, err := ParseSqlServer(ctx, tt.input)
|
||||
|
||||
if err != nil {
|
||||
got := result{parseErr: true}
|
||||
|
||||
@@ -118,6 +118,42 @@ func TestParseSqlServerUserIgnoredBug2(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseSqlServerWithJdbcAndOdbcBridgeString(t *testing.T) {
|
||||
subname := "//odbc:server=localhost;port=1433;database=testdb;password=testpassword"
|
||||
|
||||
wantHost := "localhost"
|
||||
wantPort := "1433"
|
||||
wantPassword := "testpassword"
|
||||
wantDatabase := "testdb"
|
||||
|
||||
ctx := logContext.AddLogger(context.Background())
|
||||
|
||||
j, err := parseSqlServer(ctx, subname)
|
||||
if err != nil {
|
||||
t.Fatalf("parseSqlServer() error = %v", err)
|
||||
}
|
||||
|
||||
if j == nil {
|
||||
t.Fatalf("parseSqlServer() returned nil, expected valid connection.")
|
||||
}
|
||||
|
||||
sqlServerConn, ok := j.(*SqlServerJDBC)
|
||||
if !ok {
|
||||
t.Fatalf("parseSqlServer() returned unexpected type %T, expected *SqlServerJDBC", j)
|
||||
}
|
||||
|
||||
if sqlServerConn.Host != wantHost+":"+wantPort {
|
||||
t.Errorf("Host mismatch. Got: %s, Want: %s", sqlServerConn.Host, wantHost+":"+wantPort)
|
||||
}
|
||||
|
||||
if sqlServerConn.Password != wantPassword {
|
||||
t.Errorf("Password mismatch. Got: %s, Want: %s", sqlServerConn.Password, wantPassword)
|
||||
}
|
||||
|
||||
if sqlServerConn.Database != wantDatabase {
|
||||
t.Errorf("Database mismatch. Got: %s, Want: %s", sqlServerConn.Database, wantDatabase)
|
||||
}
|
||||
}
|
||||
func TestSQLServerHandler_ParseJDBCURL(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
||||
Reference in New Issue
Block a user