183 أسطر
8.2 KiB
Bash
183 أسطر
8.2 KiB
Bash
#!/bin/bash
|
|
# فحص أمني تلقائي لتطبيق منشور على غيمة (ghaymah.systems)
|
|
# يفحص: المنافذ، SSL، الصلاحيات
|
|
|
|
DOMAIN="${1:-myapp.ghaymah.systems}"
|
|
echo "╔════════════════════════════════════════════════════════════╗"
|
|
echo "║ فحص أمني تلقائي لتطبيق على غيمة ║"
|
|
echo "║ Target: $DOMAIN"
|
|
echo "╚════════════════════════════════════════════════════════════╝"
|
|
|
|
PASS=0
|
|
WARN=0
|
|
FAIL=0
|
|
|
|
# دالة للطباعة الملونة
|
|
print_result() {
|
|
case $1 in
|
|
"pass") echo -e "✅ \e[32m$2\e[0m"; ((PASS++));;
|
|
"warn") echo -e "⚠️ \e[33m$2\e[0m"; ((WARN++));;
|
|
"fail") echo -e "❌ \e[31m$2\e[0m"; ((FAIL++));;
|
|
esac
|
|
}
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# 1. فحص المنافذ المفتوحة
|
|
# ═══════════════════════════════════════════════════════════════
|
|
echo -e "\n━━━ [1/3] فحص المنافذ ━━━"
|
|
|
|
check_port() {
|
|
local port=$1
|
|
local expected=$2
|
|
timeout 2 bash -c "echo >/dev/tcp/$DOMAIN/$port" 2>/dev/null
|
|
local result=$?
|
|
|
|
if [ $result -eq 0 ]; then
|
|
if [ "$expected" = "open" ]; then
|
|
print_result "pass" "المنفذ $port مفتوح (متوقع)"
|
|
else
|
|
print_result "fail" "المنفذ $port مفتوح (يجب أن يكون مغلقاً!)"
|
|
fi
|
|
else
|
|
if [ "$expected" = "closed" ]; then
|
|
print_result "pass" "المنفذ $port مغلق (آمن)"
|
|
else
|
|
print_result "warn" "المنفذ $port مغلق (قد يكون مشكلة)"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# المنافذ المتوقع أن تكون مفتوحة
|
|
check_port 80 "open"
|
|
check_port 443 "open"
|
|
|
|
# المنافذ التي يجب أن تكون مغلقة (قواعد البيانات)
|
|
check_port 22 "closed" # SSH
|
|
check_port 3306 "closed" # MySQL
|
|
check_port 5432 "closed" # PostgreSQL
|
|
check_port 6379 "closed" # Redis
|
|
check_port 27017 "closed" # MongoDB
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# 2. فحص شهادة SSL
|
|
# ═══════════════════════════════════════════════════════════════
|
|
echo -e "\n━━━ [2/3] فحص شهادة SSL ━━━"
|
|
|
|
ssl_info=$(echo | openssl s_client -servername "$DOMAIN" -connect "$DOMAIN:443" 2>/dev/null)
|
|
|
|
if [ -z "$ssl_info" ]; then
|
|
print_result "fail" "لا يمكن الاتصال بـ SSL"
|
|
else
|
|
# التحقق من صحة الشهادة
|
|
verify_result=$(echo "$ssl_info" | grep "Verify return code")
|
|
if echo "$verify_result" | grep -q "0 (ok)"; then
|
|
print_result "pass" "شهادة SSL صالحة"
|
|
else
|
|
print_result "fail" "شهادة SSL غير صالحة: $verify_result"
|
|
fi
|
|
|
|
# تاريخ انتهاء الشهادة
|
|
expiry=$(echo "$ssl_info" | openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)
|
|
if [ -n "$expiry" ]; then
|
|
expiry_epoch=$(date -d "$expiry" +%s 2>/dev/null)
|
|
now_epoch=$(date +%s)
|
|
days_left=$(( (expiry_epoch - now_epoch) / 86400 ))
|
|
|
|
if [ $days_left -gt 30 ]; then
|
|
print_result "pass" "الشهادة صالحة لـ $days_left يوم"
|
|
elif [ $days_left -gt 7 ]; then
|
|
print_result "warn" "الشهادة تنتهي خلال $days_left يوم"
|
|
else
|
|
print_result "fail" "الشهادة تنتهي خلال $days_left يوم فقط!"
|
|
fi
|
|
fi
|
|
|
|
# إصدار TLS
|
|
tls_version=$(echo "$ssl_info" | grep "Protocol" | awk '{print $3}')
|
|
if [[ "$tls_version" == "TLSv1.3" ]]; then
|
|
print_result "pass" "يستخدم TLS 1.3 (الأحدث)"
|
|
elif [[ "$tls_version" == "TLSv1.2" ]]; then
|
|
print_result "pass" "يستخدم TLS 1.2 (مقبول)"
|
|
else
|
|
print_result "warn" "يستخدم $tls_version (قديم)"
|
|
fi
|
|
fi
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# 3. فحص Security Headers
|
|
# ═══════════════════════════════════════════════════════════════
|
|
echo -e "\n━━━ [3/3] فحص Security Headers ━━━"
|
|
|
|
headers=$(curl -sI "https://$DOMAIN" 2>/dev/null)
|
|
|
|
if [ -z "$headers" ]; then
|
|
print_result "fail" "لا يمكن جلب الـ headers"
|
|
else
|
|
# Strict-Transport-Security
|
|
if echo "$headers" | grep -qi "Strict-Transport-Security"; then
|
|
print_result "pass" "HSTS مفعّل"
|
|
else
|
|
print_result "warn" "HSTS غير مفعّل"
|
|
fi
|
|
|
|
# X-Content-Type-Options
|
|
if echo "$headers" | grep -qi "X-Content-Type-Options"; then
|
|
print_result "pass" "X-Content-Type-Options موجود"
|
|
else
|
|
print_result "warn" "X-Content-Type-Options غير موجود"
|
|
fi
|
|
|
|
# X-Frame-Options
|
|
if echo "$headers" | grep -qi "X-Frame-Options"; then
|
|
print_result "pass" "X-Frame-Options موجود (حماية من Clickjacking)"
|
|
else
|
|
print_result "warn" "X-Frame-Options غير موجود"
|
|
fi
|
|
|
|
# Content-Security-Policy
|
|
if echo "$headers" | grep -qi "Content-Security-Policy"; then
|
|
print_result "pass" "CSP مفعّل"
|
|
else
|
|
print_result "warn" "CSP غير مفعّل"
|
|
fi
|
|
|
|
# X-Powered-By (يجب أن يكون مخفياً)
|
|
if echo "$headers" | grep -qi "X-Powered-By"; then
|
|
powered_by=$(echo "$headers" | grep -i "X-Powered-By")
|
|
print_result "fail" "X-Powered-By مكشوف: $powered_by"
|
|
else
|
|
print_result "pass" "X-Powered-By مخفي (آمن)"
|
|
fi
|
|
|
|
# Server header
|
|
if echo "$headers" | grep -qi "^Server:"; then
|
|
server=$(echo "$headers" | grep -i "^Server:" | head -1)
|
|
print_result "warn" "Server header مكشوف: $server"
|
|
else
|
|
print_result "pass" "Server header مخفي"
|
|
fi
|
|
fi
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
# ملخص النتائج
|
|
# ═══════════════════════════════════════════════════════════════
|
|
echo -e "\n╔════════════════════════════════════════════════════════════╗"
|
|
echo "║ ملخص الفحص ║"
|
|
echo "╠════════════════════════════════════════════════════════════╣"
|
|
echo -e "║ ✅ نجح: $PASS "
|
|
echo -e "║ ⚠️ تحذير: $WARN "
|
|
echo -e "║ ❌ فشل: $FAIL "
|
|
echo "╚════════════════════════════════════════════════════════════╝"
|
|
|
|
# Exit code based on failures
|
|
if [ $FAIL -gt 0 ]; then
|
|
echo -e "\n⛔ يوجد مشاكل أمنية يجب معالجتها!"
|
|
exit 1
|
|
elif [ $WARN -gt 0 ]; then
|
|
echo -e "\n⚡ يوجد تحذيرات يُنصح بمراجعتها"
|
|
exit 0
|
|
else
|
|
echo -e "\n🎉 جميع الفحوصات ناجحة!"
|
|
exit 0
|
|
fi
|