Scan target for SQL injection vulnerabilities.
(self, target: Target)
| 88 | |
| 89 | async def run(self, target: Target) -> ScanResult: |
| 90 | """Scan target for SQL injection vulnerabilities.""" |
| 91 | result = self.create_result(target) |
| 92 | |
| 93 | url = self._build_url(target) |
| 94 | self.logger.info(f"Starting SQLi scan on {url}") |
| 95 | |
| 96 | vulnerabilities = [] |
| 97 | |
| 98 | try: |
| 99 | async with HTTPClient() as client: |
| 100 | # Get baseline response |
| 101 | baseline = await client.get(url) |
| 102 | baseline_length = len(baseline.text) |
| 103 | |
| 104 | parsed = urlparse(str(baseline.url)) |
| 105 | params = parse_qs(parsed.query) |
| 106 | |
| 107 | if not params: |
| 108 | params = {"id": ["1"], "user": ["1"], "page": ["1"]} |
| 109 | |
| 110 | for param_name in params.keys(): |
| 111 | for payload in self.payloads: |
| 112 | test_url = self._inject_payload(url, param_name, payload) |
| 113 | |
| 114 | try: |
| 115 | test_response = await client.get(test_url) |
| 116 | |
| 117 | # Check for SQL errors |
| 118 | error_found = self._check_sql_errors(test_response.text) |
| 119 | if error_found: |
| 120 | vuln = { |
| 121 | "type": "Error-based SQLi", |
| 122 | "url": test_url, |
| 123 | "parameter": param_name, |
| 124 | "payload": payload, |
| 125 | "error": error_found, |
| 126 | } |
| 127 | vulnerabilities.append(vuln) |
| 128 | self.logger.warning(f"SQL error detected: {param_name}") |
| 129 | break |
| 130 | |
| 131 | # Boolean-based detection |
| 132 | length_diff = abs(len(test_response.text) - baseline_length) |
| 133 | if length_diff > 100 and "1=1" in payload: |
| 134 | # Try false condition |
| 135 | false_url = self._inject_payload(url, param_name, payload.replace("1=1", "1=2")) |
| 136 | false_response = await client.get(false_url) |
| 137 | |
| 138 | if abs(len(test_response.text) - len(false_response.text)) > 100: |
| 139 | vuln = { |
| 140 | "type": "Boolean-based SQLi", |
| 141 | "url": test_url, |
| 142 | "parameter": param_name, |
| 143 | "payload": payload, |
| 144 | "evidence": f"Response length varies: true={len(test_response.text)}, false={len(false_response.text)}", |
| 145 | } |
| 146 | vulnerabilities.append(vuln) |
| 147 | self.logger.warning(f"Boolean SQLi detected: {param_name}") |
no test coverage detected