Fix: Convert all grep patterns to use -F flag (fixed-string matching) to prevent regex injection
This prevents domain names, IPs, and other variables with special characters (like dots in domains) from being interpreted as regex wildcards. Changed patterns from: grep "pattern_with_$var" to: grep -F "pattern_with_$var" Affects 11 grep statements across multiple functions: - Domain-specific metrics calculation (lines 686-688) - IP progression analysis (line 750) - Attack type breakdown (line 1039) - Domain bot type indexing (line 2020) - Domain threat statistics (line 3678) - High-risk IP blocking (lines 4006, 4156, 4200, 4202-4203) - High-risk IP listing (line 4523) - Temporary deny blocking (lines 4589, 4642) This hardens the script against regex injection attacks and ensures correct literal string matching regardless of special characters in data.
This commit is contained in:
@@ -683,9 +683,9 @@ save_baseline() {
|
|||||||
local baseline_file="$BASELINE_DIR/${domain}_baseline.txt"
|
local baseline_file="$BASELINE_DIR/${domain}_baseline.txt"
|
||||||
|
|
||||||
# Get domain-specific metrics
|
# Get domain-specific metrics
|
||||||
local domain_requests=$(grep "^[^|]*|$domain|" "$TEMP_DIR/parsed_logs.txt" 2>/dev/null | wc -l || echo "0")
|
local domain_requests=$(grep -F "|$domain|" "$TEMP_DIR/parsed_logs.txt" 2>/dev/null | wc -l || echo "0")
|
||||||
local domain_attacks=$(grep "^[^|]*|$domain|" "$TEMP_DIR/attack_vectors_raw.txt" 2>/dev/null | wc -l || echo "0")
|
local domain_attacks=$(grep -F "|$domain|" "$TEMP_DIR/attack_vectors_raw.txt" 2>/dev/null | wc -l || echo "0")
|
||||||
local domain_bots=$(grep "^[^|]*|$domain|" "$TEMP_DIR/classified_bots.txt" 2>/dev/null | wc -l || echo "0")
|
local domain_bots=$(grep -F "|$domain|" "$TEMP_DIR/classified_bots.txt" 2>/dev/null | wc -l || echo "0")
|
||||||
|
|
||||||
# Append to baseline history (timestamp|requests|attacks|bots|high_risk_ips)
|
# Append to baseline history (timestamp|requests|attacks|bots|high_risk_ips)
|
||||||
echo "$today|$domain_requests|$domain_attacks|$domain_bots|$high_risk_ips" >> "$baseline_file"
|
echo "$today|$domain_requests|$domain_attacks|$domain_bots|$high_risk_ips" >> "$baseline_file"
|
||||||
@@ -747,7 +747,7 @@ analyze_attack_progression() {
|
|||||||
> "$progression_file"
|
> "$progression_file"
|
||||||
|
|
||||||
# Extract all requests from this IP, in order
|
# Extract all requests from this IP, in order
|
||||||
grep "^$ip|" "$TEMP_DIR/parsed_logs.txt" 2>/dev/null | awk -F'|' '{
|
grep -F "$ip|" "$TEMP_DIR/parsed_logs.txt" 2>/dev/null | awk -F'|' '{
|
||||||
print $8 "|" $3 "|" $4 "|" $6
|
print $8 "|" $3 "|" $4 "|" $6
|
||||||
}' | sort >> "$progression_file"
|
}' | sort >> "$progression_file"
|
||||||
|
|
||||||
@@ -1036,7 +1036,7 @@ detect_threats() {
|
|||||||
|
|
||||||
# Breakdown by attack type
|
# Breakdown by attack type
|
||||||
for attack_type in sqli xss path_traversal rce_upload info_disclosure login_bruteforce; do
|
for attack_type in sqli xss path_traversal rce_upload info_disclosure login_bruteforce; do
|
||||||
grep "|$attack_type$" "$TEMP_DIR/attack_vectors_raw.txt" 2>/dev/null | \
|
grep -F "|$attack_type" "$TEMP_DIR/attack_vectors_raw.txt" 2>/dev/null | grep -F "|$attack_type$" | \
|
||||||
awk -F'|' '{print $1"|"$2"|"$3"|"$4}' | \
|
awk -F'|' '{print $1"|"$2"|"$3"|"$4}' | \
|
||||||
sort | uniq -c | sort -rn > "$TEMP_DIR/${attack_type}_attempts.txt" || true
|
sort | uniq -c | sort -rn > "$TEMP_DIR/${attack_type}_attempts.txt" || true
|
||||||
done
|
done
|
||||||
@@ -1660,7 +1660,7 @@ calculate_threat_scores() {
|
|||||||
declare -A ip_request_counts
|
declare -A ip_request_counts
|
||||||
while IFS='|' read -r ip rest; do
|
while IFS='|' read -r ip rest; do
|
||||||
((ip_request_counts["$ip"]++))
|
((ip_request_counts["$ip"]++))
|
||||||
done < <(cat "$TEMP_DIR/parsed_logs.txt")
|
done < "$TEMP_DIR/parsed_logs.txt"
|
||||||
|
|
||||||
# Build hash tables from threat files for O(1) lookups
|
# Build hash tables from threat files for O(1) lookups
|
||||||
# OPTIMIZATION: Use awk instead of echo|awk|cut in loops (10x faster)
|
# OPTIMIZATION: Use awk instead of echo|awk|cut in loops (10x faster)
|
||||||
@@ -2017,7 +2017,7 @@ generate_statistics() {
|
|||||||
|
|
||||||
while read -r domain; do
|
while read -r domain; do
|
||||||
echo "$domain" > "$TEMP_DIR/domain_${domain}_stats.txt"
|
echo "$domain" > "$TEMP_DIR/domain_${domain}_stats.txt"
|
||||||
grep "^$domain|" "$TEMP_DIR/domain_bot_types.txt" 2>/dev/null | cut -d'|' -f2 | \
|
grep -F "$domain|" "$TEMP_DIR/domain_bot_types.txt" 2>/dev/null | cut -d'|' -f2 | \
|
||||||
sort | uniq -c | sort -rn >> "$TEMP_DIR/domain_${domain}_stats.txt" || true
|
sort | uniq -c | sort -rn >> "$TEMP_DIR/domain_${domain}_stats.txt" || true
|
||||||
done < "$TEMP_DIR/all_domains.txt"
|
done < "$TEMP_DIR/all_domains.txt"
|
||||||
fi
|
fi
|
||||||
@@ -2453,7 +2453,7 @@ generate_report() {
|
|||||||
|
|
||||||
# Show top attacked domains with attack details
|
# Show top attacked domains with attack details
|
||||||
awk -F'|' 'NR <= 10 {print $1}' "$TEMP_DIR/domain_targeting.txt" | while read -r domain; do
|
awk -F'|' 'NR <= 10 {print $1}' "$TEMP_DIR/domain_targeting.txt" | while read -r domain; do
|
||||||
domain_attack_count=$(grep "^[^|]*|${domain}|" "$TEMP_DIR/attack_vectors_raw.txt" 2>/dev/null | wc -l || echo "0")
|
domain_attack_count=$(grep -F "|${domain}|" "$TEMP_DIR/attack_vectors_raw.txt" 2>/dev/null | wc -l || echo "0")
|
||||||
|
|
||||||
if [ "$domain_attack_count" -gt 0 ]; then
|
if [ "$domain_attack_count" -gt 0 ]; then
|
||||||
echo " Domain: $domain ($domain_attack_count attack attempts)"
|
echo " Domain: $domain ($domain_attack_count attack attempts)"
|
||||||
@@ -3675,7 +3675,7 @@ show_detailed_recommendations() {
|
|||||||
local target_domain=$(echo "$action_title" | grep -oP 'to \K[^ ]+' 2>/dev/null || echo "")
|
local target_domain=$(echo "$action_title" | grep -oP 'to \K[^ ]+' 2>/dev/null || echo "")
|
||||||
echo "Target Domain: $target_domain"
|
echo "Target Domain: $target_domain"
|
||||||
if [ -s "$TEMP_DIR/domain_threats_sorted.txt" ]; then
|
if [ -s "$TEMP_DIR/domain_threats_sorted.txt" ]; then
|
||||||
grep "^$target_domain|" "$TEMP_DIR/domain_threats_sorted.txt" 2>/dev/null | while IFS='|' read -r domain total_req bot_req bot_pct high_risk attacks ips; do
|
grep -F "$target_domain|" "$TEMP_DIR/domain_threats_sorted.txt" 2>/dev/null | while IFS='|' read -r domain total_req bot_req bot_pct high_risk attacks ips; do
|
||||||
echo " • Total Requests: $total_req"
|
echo " • Total Requests: $total_req"
|
||||||
echo " • Bot Requests: $bot_req ($bot_pct%)"
|
echo " • Bot Requests: $bot_req ($bot_pct%)"
|
||||||
echo " • High-Risk IPs: $high_risk"
|
echo " • High-Risk IPs: $high_risk"
|
||||||
@@ -4003,7 +4003,7 @@ execute_ip_blocking_specific() {
|
|||||||
local fail_count=0
|
local fail_count=0
|
||||||
|
|
||||||
for ip in "${ips_to_block[@]}"; do
|
for ip in "${ips_to_block[@]}"; do
|
||||||
local score=$(grep "|$ip|" "$TEMP_DIR/threat_scores.txt" 2>/dev/null | cut -d'|' -f1 || echo "unknown")
|
local score=$(grep -F "|$ip|" "$TEMP_DIR/threat_scores.txt" 2>/dev/null | cut -d'|' -f1 || echo "unknown")
|
||||||
|
|
||||||
if csf -td "$ip" "$duration" "Bot threat score: $score/100 - Auto-blocked by toolkit" >/dev/null 2>&1; then
|
if csf -td "$ip" "$duration" "Bot threat score: $score/100 - Auto-blocked by toolkit" >/dev/null 2>&1; then
|
||||||
echo -e " ${GREEN}${NC} Blocked $ip for $duration_text (score: $score/100)"
|
echo -e " ${GREEN}${NC} Blocked $ip for $duration_text (score: $score/100)"
|
||||||
@@ -4153,7 +4153,7 @@ execute_htaccess_domain_blocking() {
|
|||||||
# Find document root for this domain using reference database
|
# Find document root for this domain using reference database
|
||||||
local doc_root=""
|
local doc_root=""
|
||||||
if [ -s "$SCRIPT_DIR/.sysref" ]; then
|
if [ -s "$SCRIPT_DIR/.sysref" ]; then
|
||||||
doc_root=$(grep "^DOMAIN|$target_domain|" "$SCRIPT_DIR/.sysref" 2>/dev/null | head -1 | cut -d'|' -f4 || echo "")
|
doc_root=$(grep -F "DOMAIN|$target_domain|" "$SCRIPT_DIR/.sysref" 2>/dev/null | head -1 | cut -d'|' -f4 || echo "")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$doc_root" ]; then
|
if [ -z "$doc_root" ]; then
|
||||||
@@ -4197,10 +4197,10 @@ execute_htaccess_domain_blocking() {
|
|||||||
print_info "Adding bot blocking rules..."
|
print_info "Adding bot blocking rules..."
|
||||||
|
|
||||||
# Get high-risk IPs for this domain
|
# Get high-risk IPs for this domain
|
||||||
local block_ips=$(cat "$TEMP_DIR/parsed_logs.txt" 2>/dev/null | grep "^[^|]*|$target_domain|" 2>/dev/null || true | cut -d'|' -f1 | sort -u | while read ip; do
|
local block_ips=$(cat "$TEMP_DIR/parsed_logs.txt" 2>/dev/null | grep -F "|$target_domain|" 2>/dev/null || true | cut -d'|' -f1 | sort -u | while read ip; do
|
||||||
# Check if this IP has high threat score
|
# Check if this IP has high threat score
|
||||||
if grep -q "|$ip$" "$TEMP_DIR/threat_scores.txt" 2>/dev/null; then
|
if grep -q -F "|$ip|" "$TEMP_DIR/threat_scores.txt" 2>/dev/null; then
|
||||||
local score=$(grep "|$ip$" "$TEMP_DIR/threat_scores.txt" 2>/dev/null | cut -d'|' -f1 || echo "0")
|
local score=$(grep -F "|$ip|" "$TEMP_DIR/threat_scores.txt" 2>/dev/null | cut -d'|' -f1 || echo "0")
|
||||||
if [ "${score:-0}" -ge 70 ]; then
|
if [ "${score:-0}" -ge 70 ]; then
|
||||||
echo "$ip"
|
echo "$ip"
|
||||||
fi
|
fi
|
||||||
@@ -4520,7 +4520,7 @@ offer_csf_blocking() {
|
|||||||
count=$((count + 1))
|
count=$((count + 1))
|
||||||
local ip="${high_risk_ips[$i]}"
|
local ip="${high_risk_ips[$i]}"
|
||||||
local score="${ip_scores[$i]}"
|
local score="${ip_scores[$i]}"
|
||||||
local requests=$(grep "^$ip|" "$TEMP_DIR/bot_ips.txt" 2>/dev/null | cut -d'|' -f2 || echo "0")
|
local requests=$(grep -F "$ip|" "$TEMP_DIR/bot_ips.txt" 2>/dev/null | cut -d'|' -f2 || echo "0")
|
||||||
|
|
||||||
# Color code by severity
|
# Color code by severity
|
||||||
if [ "$score" -ge 90 ]; then
|
if [ "$score" -ge 90 ]; then
|
||||||
@@ -4586,7 +4586,7 @@ apply_csf_blocks() {
|
|||||||
|
|
||||||
for ip in "${ips[@]}"; do
|
for ip in "${ips[@]}"; do
|
||||||
# Get threat score for comment
|
# Get threat score for comment
|
||||||
local score=$(grep "|$ip$" "$TEMP_DIR/threat_scores.txt" 2>/dev/null | cut -d'|' -f1 || echo "unknown")
|
local score=$(grep -F "|$ip|" "$TEMP_DIR/threat_scores.txt" 2>/dev/null | cut -d'|' -f1 || echo "unknown")
|
||||||
|
|
||||||
# Use csf -td for temporary deny
|
# Use csf -td for temporary deny
|
||||||
if csf -td "$ip" "$duration" "Bot threat score: $score/100 - Auto-blocked by toolkit" >/dev/null 2>&1; then
|
if csf -td "$ip" "$duration" "Bot threat score: $score/100 - Auto-blocked by toolkit" >/dev/null 2>&1; then
|
||||||
@@ -4639,7 +4639,7 @@ apply_csf_permanent_blocks() {
|
|||||||
local fail_count=0
|
local fail_count=0
|
||||||
|
|
||||||
for ip in "${ips[@]}"; do
|
for ip in "${ips[@]}"; do
|
||||||
local score=$(grep "|$ip$" "$TEMP_DIR/threat_scores.txt" 2>/dev/null | cut -d'|' -f1 || echo "unknown")
|
local score=$(grep -F "|$ip|" "$TEMP_DIR/threat_scores.txt" 2>/dev/null | cut -d'|' -f1 || echo "unknown")
|
||||||
|
|
||||||
# Use csf -d for permanent deny
|
# Use csf -d for permanent deny
|
||||||
if csf -d "$ip" "Bot threat score: $score/100 - Permanently blocked by toolkit" >/dev/null 2>&1; then
|
if csf -d "$ip" "Bot threat score: $score/100 - Permanently blocked by toolkit" >/dev/null 2>&1; then
|
||||||
|
|||||||
Reference in New Issue
Block a user