diff --git a/docker/dvwa/docker-compose.yml b/docker/dvwa/docker-compose.yml new file mode 100644 index 0000000..9afc133 --- /dev/null +++ b/docker/dvwa/docker-compose.yml @@ -0,0 +1,7 @@ +services: + dvwa: + image: vulnerables/web-dvwa + container_name: dvwa + restart: always + ports: + - "80:80" diff --git a/docker/modsecurity/docker-compose.yml b/docker/modsecurity/docker-compose.yml index cb51a92..0f5f43f 100644 --- a/docker/modsecurity/docker-compose.yml +++ b/docker/modsecurity/docker-compose.yml @@ -4,7 +4,18 @@ services: container_name: modsecurity restart: always environment: - BACKEND: "http://localhost:3333" # TODO: CHANGE THIS TO SURICATA'S PORT COS INLINE + BACKEND: "http://localhost:80" SERVER_NAME: "localhost" PORT: "3331" + MODSEC_AUDIT_LOG: "/var/log/modsec_audit.log" + ERRORLOG: "/var/log/modsec_error.log" + ACCESSLOG: "/var/log/apache2/access.log" + BLOCKING_PARANOIA: 4 + DETECTION_PARANOIA: 4 + EXECUTING_PARANOIA: 4 + PARANOIA: 4 network_mode: "host" + volumes: + - "/tmp/host-fs-auditlog.log:/var/log/modsec_audit.log" + - "/tmp/host-fs-errorlog.log:/var/log/modsec_error.log" + - "/tmp/host-fs-accesslog.log:/var/log/apache2/access.log" diff --git a/docker/suricata/docker-compose.yml b/docker/suricata/docker-compose.yml index 2dfe6a6..f460209 100644 --- a/docker/suricata/docker-compose.yml +++ b/docker/suricata/docker-compose.yml @@ -28,4 +28,4 @@ services: - ./suricata/etc:/etc/suricata - ./suricata/logs:/var/log/suricata - ./suricata/lib:/var/lib/suricata - command: ["-c", "/etc/suricata/suricata.yaml", "-q 0"] + command: ["-c", "/etc/suricata/suricata.yaml", "--af-packet"] diff --git a/docker/suricata/suricata/etc/rules/suricata.rules b/docker/suricata/suricata/etc/rules/suricata.rules index 8513a3d..69f365a 100755 --- a/docker/suricata/suricata/etc/rules/suricata.rules +++ b/docker/suricata/suricata/etc/rules/suricata.rules @@ -2,4 +2,4 @@ #drop http any any -> any any (msg:"asdf attempt"; content:"asdf@gmail.com"; http_client_body; nocase; sid:1000007; rev:2;) #drop ip 192.168.0.71 any -> any any (msg:"asdfBlocking ALL traffic from 192.168.0.71"; sid:1000010; rev:1;) #drop http any any -> any any (msg:"dropping ALL shit"; sid:1000123; rev:1;) -#drop http any any -> 192.168.0.69 3333 (msg:"Blocked /health endpoint"; http.uri; content:"/health"; nocase; sid:1000008; rev:2;) +#drop http any any -> 192.168.0.69 80 (msg:"Blocked /health endpoint"; http.uri; content:"/health"; nocase; sid:1000008; rev:2;) diff --git a/docker/suricata/suricata/etc/suricata.yaml b/docker/suricata/suricata/etc/suricata.yaml index 14cf071..56b7fed 100755 --- a/docker/suricata/suricata/etc/suricata.yaml +++ b/docker/suricata/suricata/etc/suricata.yaml @@ -8,7 +8,7 @@ vars: EXTERNAL_NET: "any" port-groups: - HTTP_PORTS: "3333" + HTTP_PORTS: "80" # Define Suricata as an inline IPS af-packet: diff --git a/dvwa/csrf.html b/dvwa/csrf.html new file mode 100644 index 0000000..d1a226d --- /dev/null +++ b/dvwa/csrf.html @@ -0,0 +1,5 @@ + + + asdf + + diff --git a/dvwa/file-inclusion b/dvwa/file-inclusion new file mode 100644 index 0000000..35426be --- /dev/null +++ b/dvwa/file-inclusion @@ -0,0 +1,5 @@ + diff --git a/server-ml/main.py b/server-ml/main.py index 6fbeee3..676ebd0 100644 --- a/server-ml/main.py +++ b/server-ml/main.py @@ -1,22 +1,55 @@ -from transformers import AutoModelForSequenceClassification, AutoTokenizer from flask import Flask, request, jsonify +import torch +from transformers import MobileBertTokenizer, MobileBertForSequenceClassification -ACCESS_TOKEN = "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" - +# Initialize Flask app app = Flask(__name__) -model_path = "maheshj01/sql-injection-classifier" -model = AutoModelForSequenceClassification.from_pretrained(model_path, token=ACCESS_TOKEN) -tokenizer = AutoTokenizer.from_pretrained(model_path, token=ACCESS_TOKEN) +# Set device (GPU if available, otherwise CPU) +device = torch.device("cuda" if torch.cuda.is_available() else "cpu") -# Function to classify a SQL query -def classify_query(query): - inputs = tokenizer(query, return_tensors="pt", truncation=True, padding=True) - outputs = model(**inputs) - prediction = outputs.logits.argmax(-1).item() - return "Vulnerable" if prediction == 1 else "Secure" +# Load tokenizer and model +tokenizer = MobileBertTokenizer.from_pretrained("google/mobilebert-uncased") +model = MobileBertForSequenceClassification.from_pretrained("cssupport/mobilebert-sql-injection-detect") +model.to(device) +model.eval() -# Example usage -query = "SELECT Column" -result = classify_query(query) -print(f"The query is classified as: {result}") \ No newline at end of file +# Function to predict SQL injection +def predict(text): + inputs = tokenizer(text, padding=False, truncation=True, return_tensors="pt", max_length=512) + input_ids = inputs["input_ids"].to(device) + attention_mask = inputs["attention_mask"].to(device) + + with torch.no_grad(): + outputs = model(input_ids=input_ids, attention_mask=attention_mask) + + logits = outputs.logits + probabilities = torch.softmax(logits, dim=1) + predicted_class = torch.argmax(probabilities, dim=1).item() + confidence = probabilities[0][predicted_class].item() + + return predicted_class, confidence + +# Define API endpoint +@app.route("/predict", methods=["POST"]) +def classify_query(): + data = request.json + if "query" not in data: + return jsonify({"error": "Missing 'query' in request"}), 400 + + query = data["query"] + predicted_class, confidence = predict(query) + + # Thresholding (if confidence > 0.7, mark as SQL Injection) + is_vulnerable = predicted_class == 1 and confidence > 0.7 + result = { + "query": query, + "classification": "SQL Injection Detected" if is_vulnerable else "No SQL Injection Detected", + "confidence": round(confidence, 2) + } + + return jsonify(result) + +# Run Flask server +if __name__ == "__main__": + app.run(host="0.0.0.0", port=5000, debug=True) diff --git a/server-ml/test-cases.md b/server-ml/test-cases.md new file mode 100644 index 0000000..5e58c7c --- /dev/null +++ b/server-ml/test-cases.md @@ -0,0 +1,46 @@ +# Test Cases + +## 1. Basic test cases + +[Good] `SELECT _ FROM users WHERE id = 1` +[Bad] `SELECT _ FROM users WHERE id = 1 OR 1=1` + +## 2. Authentication bypass cases + +[Bad] `SELECT _ FROM users WHERE username = 'admin' --` +[Bad] `SELECT _ FROM users WHERE username = 'admin' #` +[Bad] `SELECT \* FROM users WHERE username = 'admin' OR '1'='1'` + +## 3. Union based injection cases + +[Bad] `SELECT id, username FROM users WHERE id = 1 UNION SELECT null, 'hacker'` +[Bad] `SELECT id, username FROM users WHERE id = 1 UNION SELECT 1, 'hacked' FROM dual` +[Bad] `SELECT database() UNION SELECT 1` + +## 4. Error based injection cases + +[Bad] `SELECT _ FROM users WHERE id = 1 AND (SELECT 1 FROM users WHERE id=2)=1` +[Bad] `SELECT _ FROM users WHERE id = (SELECT COUNT(\*) FROM users)` + +## 5. Blind SQL injection cases + +[Bad] `SELECT _ FROM users WHERE id = 1; WAITFOR DELAY '00:00:10' --` +[Bad] `SELECT _ FROM users WHERE username = 'admin' AND 1=1` + +## 6. Hex and Base64 encoded injection cases + +[Bad] `SELECT _ FROM users WHERE username = 0x61646D696E` +[Bad] `SELECT _ FROM users WHERE username = 'YWRtaW4='` + +## 7. False positives cases + +[Good] `SELECT _ FROM users WHERE id = 5` +[Good] `SELECT users.name, orders.amount FROM users JOIN orders ON users.id = orders.user_id` +[Good] `SELECT _ FROM users WHERE username = ? AND password = ?` + +## 8. Edge cases + +[Good] `""` +[Bad] `'; --` +[Good] `12345` +[Good] `asdkjhasdkjh` diff --git a/sqlmap/crontab b/sqlmap/crontab new file mode 100644 index 0000000..9b75c8e --- /dev/null +++ b/sqlmap/crontab @@ -0,0 +1,6 @@ +@reboot sleep 10 && cd /home/vomitblood/build/cspj-application/docker/dvwa && docker compose up -d && sleep 30 && sqlmap -u "http://localhost:80/vulnerabilities/sqli/?id=234&Submit=Submit" --cookie="PHPSESSID=l38mpsp9ksla91tnvglti5jur6; security=low" --tables --batch >> /home/vomitblood/sqlmap.log 2>&1 + +# runs the script on every system startup +# starts the dvwa in the background +# then runs sqlmap +# log all outputs and errors \ No newline at end of file