gate mysql allowAllFiles behind -lfa

Route every mysql DSN through a sandbox that drops allowAllFiles unless -lfa is set, matching the fs.ReadFile restriction.
This commit is contained in:
Doğan Can Bakır committed 2026-06-19 13:45:35 +03:00
1 parent c041bf2922
commit 634cecbb28
3 files changed
+72 -3

No files matched your search

+1 -2
View File
@@ -2,7 +2,6 @@ package mysql
import (
"context"
"database/sql"
"fmt"
"io"
"log"
@@ -227,7 +226,7 @@ func (c *MySQLClient) ExecuteQueryWithOpts(ctx context.Context, opts MySQLOption
return nil, err
}
db, err := sql.Open("mysql", dsn)
db, err := openDB(executionId, dsn)
if err != nil {
return nil, err
}
+29 -1
View File
@@ -7,6 +7,10 @@ import (
"net"
"net/url"
"strings"
"github.com/go-sql-driver/mysql"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
"github.com/projectdiscovery/nuclei/v3/pkg/types"
)
type (
@@ -72,9 +76,33 @@ func BuildDSN(opts MySQLOptions) (string, error) {
return dsn.String(), nil
}
// sandboxDSN enforces the local file access sandbox on a MySQL DSN. The
// driver's allowAllFiles option lets a malicious server read any local file
// off the host via LOAD DATA LOCAL INFILE, so it is only honored when -lfa is
// enabled, mirroring the fs.ReadFile restriction.
func sandboxDSN(dsn string, lfaAllowed bool) (string, error) {
cfg, err := mysql.ParseDSN(dsn)
if err != nil {
return "", err
}
if cfg.AllowAllFiles && !lfaAllowed {
cfg.AllowAllFiles = false
}
return cfg.FormatDSN(), nil
}
// openDB opens a sandboxed MySQL connection from dsn.
func openDB(executionId, dsn string) (*sql.DB, error) {
dsn, err := sandboxDSN(dsn, protocolstate.IsLfaAllowed(&types.Options{ExecutionId: executionId}))
if err != nil {
return nil, err
}
return sql.Open("mysql", dsn)
}
// @memo
func connectWithDSN(ctx context.Context, executionId string, dsn string) (bool, error) {
db, err := sql.Open("mysql", dsn)
db, err := openDB(executionId, dsn)
if err != nil {
return false, err
}
+42
View File
@@ -0,0 +1,42 @@
package mysql
import (
"testing"
"github.com/go-sql-driver/mysql"
"github.com/stretchr/testify/require"
)
func TestSandboxDSN(t *testing.T) {
t.Run("strips allowAllFiles when lfa disabled", func(t *testing.T) {
got, err := sandboxDSN("root:x@nucleitcp(127.0.0.1:3306)/?allowAllFiles=true", false)
require.NoError(t, err)
cfg, err := mysql.ParseDSN(got)
require.NoError(t, err)
require.False(t, cfg.AllowAllFiles)
})
t.Run("keeps allowAllFiles when lfa enabled", func(t *testing.T) {
got, err := sandboxDSN("root:x@nucleitcp(127.0.0.1:3306)/?allowAllFiles=true", true)
require.NoError(t, err)
cfg, err := mysql.ParseDSN(got)
require.NoError(t, err)
require.True(t, cfg.AllowAllFiles)
})
t.Run("leaves dsn without allowAllFiles untouched", func(t *testing.T) {
got, err := sandboxDSN("root:x@nucleitcp(127.0.0.1:3306)/", false)
require.NoError(t, err)
cfg, err := mysql.ParseDSN(got)
require.NoError(t, err)
require.False(t, cfg.AllowAllFiles)
})
t.Run("errors on invalid dsn", func(t *testing.T) {
_, err := sandboxDSN("::not-a-dsn::", false)
require.Error(t, err)
})
}