checkUnionInjection analyzes UNION for potential data extraction.
(stmt *ast.SetOperation, result *ScanResult)
| 849 | |
| 850 | // checkUnionInjection analyzes UNION for potential data extraction. |
| 851 | func (s *Scanner) checkUnionInjection(stmt *ast.SetOperation, result *ScanResult) { |
| 852 | // Check if right side SELECT has suspicious patterns |
| 853 | if rightSelect, ok := stmt.Right.(*ast.SelectStatement); ok { |
| 854 | // Check for NULL placeholders (common in UNION injection) |
| 855 | nullCount := 0 |
| 856 | for _, col := range rightSelect.Columns { |
| 857 | if ident, ok := col.(*ast.Identifier); ok { |
| 858 | if strings.ToUpper(ident.Name) == "NULL" { |
| 859 | nullCount++ |
| 860 | } |
| 861 | } |
| 862 | } |
| 863 | |
| 864 | // Multiple NULLs in UNION SELECT is suspicious |
| 865 | if nullCount >= 2 { |
| 866 | finding := Finding{ |
| 867 | Severity: SeverityHigh, |
| 868 | Pattern: PatternUnionBased, |
| 869 | Description: "UNION SELECT with multiple NULL columns detected", |
| 870 | Risk: "Data extraction via UNION-based injection", |
| 871 | Suggestion: "Verify UNION is intentional and inputs are sanitized", |
| 872 | } |
| 873 | if s.shouldInclude(finding.Severity) { |
| 874 | result.Findings = append(result.Findings, finding) |
| 875 | } |
| 876 | } |
| 877 | |
| 878 | // Check for system table access using precise matching |
| 879 | if rightSelect.TableName != "" { |
| 880 | if s.isSystemTable(rightSelect.TableName) { |
| 881 | finding := Finding{ |
| 882 | Severity: SeverityCritical, |
| 883 | Pattern: PatternUnionBased, |
| 884 | Description: "UNION SELECT accessing system tables detected", |
| 885 | Risk: "Database schema enumeration, privilege escalation", |
| 886 | Suggestion: "Block access to system tables from user queries", |
| 887 | } |
| 888 | if s.shouldInclude(finding.Severity) { |
| 889 | result.Findings = append(result.Findings, finding) |
| 890 | } |
| 891 | } |
| 892 | } |
| 893 | } |
| 894 | } |
| 895 | |
| 896 | // isSystemTable checks if a table name refers to a system table using precise matching. |
| 897 | // Uses prefix matching and exact name matching to avoid false positives. |
no test coverage detected