Web Site Pentester (Web Site Güvenlik Analiz Aracı)
# main.py - SitePenTest v1.0
import sys
import os
from PyQt6.QtWidgets import (
QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
QLabel, QLineEdit, QPushButton, QProgressBar, QTextBrowser,
QFrame, QMessageBox, QDialog
)
from PyQt6.QtCore import Qt, QThread, pyqtSignal, QUrl
from PyQt6.QtGui import QFont, QIcon, QDesktopServices, QPixmap
from scanner import WebScanner
# PyInstaller ve Geliştirme ortamı için dosya yolu bulucu
def resource_path(relative_path):
""" PyInstaller için mutlak yolu bulur """
try:
# PyInstaller geçici klasörü
base_path = sys._MEIPASS
except Exception:
# Normal çalışma yolu
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
class AboutDialog(QDialog):
def __init__(self):
super().__init__()
self.setWindowTitle("Hakkında")
self.setFixedSize(480, 580) # Uyarı metni uzadığı için boyutu biraz artırdık
# Pencere İkonunu Ekle (YENİ)
icon_path = resource_path("assets/logo.png")
if os.path.exists(icon_path):
self.setWindowIcon(QIcon(icon_path))
# Koyu Tema (Dark Mode)
self.setStyleSheet("""
QDialog { background-color: #1e1e1e; }
QLabel { color: #e0e0e0; font-family: 'Segoe UI'; }
""")
layout = QVBoxLayout(self)
layout.setSpacing(10)
layout.setContentsMargins(20, 30, 20, 20)
# --- 1. Logo ---
logo_label = QLabel()
pixmap = QPixmap(resource_path("assets/logo.png"))
if not pixmap.isNull():
# Logoyu ortala ve boyutlandır
scaled = pixmap.scaled(100, 100, Qt.AspectRatioMode.KeepAspectRatio,
Qt.TransformationMode.SmoothTransformation)
logo_label.setPixmap(scaled)
logo_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
layout.addWidget(logo_label)
# --- 2. Başlık ve Versiyon ---
title_label = QLabel("SitePenTest")
title_label.setFont(QFont("Segoe UI", 24, QFont.Weight.Bold))
title_label.setStyleSheet("color: #33b5e5; margin-top: 10px;") # Mavi başlık
title_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
layout.addWidget(title_label)
version_label = QLabel("Sürüm v1.0 (Stable)")
version_label.setFont(QFont("Segoe UI", 10, QFont.Weight.Bold))
version_label.setStyleSheet("color: #ffffff;")
version_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
layout.addWidget(version_label)
# --- 3. Açıklama ---
desc_label = QLabel(
"Linux (Pardus/Debian) sistemler için geliştirilmiş;\n"
"WAF bypass özellikli web güvenlik tarama aracı."
)
desc_label.setWordWrap(True)
desc_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
desc_label.setStyleSheet("color: #bbbbbb; font-size: 13px; margin: 10px 0;")
layout.addWidget(desc_label)
# --- 4. Yasal Uyarı (GÜNCELLENDİ) ---
warning_text = (
"<b>⚠️ YASAL UYARI:</b> Kendinize ait olmayan ya da yazılı izin almadığınız "
"web site ve sistemleri taramak kanunen suçtur.<br><br>"
"Tüm sorumluluk kullanana aittir."
)
warning_label = QLabel(warning_text)
warning_label.setWordWrap(True)
warning_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
warning_label.setStyleSheet("color: #ff4444; font-size: 12px; font-weight: bold;") # Kırmızı ve kalın
layout.addWidget(warning_label)
# --- 5. Geliştirici Bilgileri ---
dev_label = QLabel("Geliştirici: <b>Tarık Vardar</b>")
dev_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
dev_label.setStyleSheet("color: #ffffff; font-size: 13px; margin-top: 15px;")
layout.addWidget(dev_label)
# Linkler
links_browser = QTextBrowser()
links_browser.setOpenExternalLinks(True)
links_browser.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
links_browser.setStyleSheet("border: none; background: transparent;")
links_browser.setFixedHeight(40)
links_html = """
<div style="text-align:center; font-family: 'Segoe UI'; font-size: 13px;">
<a href="mailto:info@tarikvardar.com.tr" style="color:#33b5e5; text-decoration:none;">📧 İletişim</a> |
<a href="https://www.tarikvardar.com.tr" style="color:#33b5e5; text-decoration:none;">🌐 Web Site</a> |
<a href="https://github.com/tvardar" style="color:#33b5e5; text-decoration:none;">💻 GitHub</a>
</div>
"""
links_browser.setHtml(links_html)
layout.addWidget(links_browser)
layout.addStretch()
# --- 6. Lisans Kutusu ---
license_frame = QFrame()
license_frame.setStyleSheet("background-color: #2d2d2d; border-radius: 6px;")
lic_layout = QVBoxLayout(license_frame)
lic_layout.setContentsMargins(10, 10, 10, 10)
lic_title = QLabel("MIT License")
lic_title.setAlignment(Qt.AlignmentFlag.AlignCenter)
lic_title.setFont(QFont("Segoe UI", 9, QFont.Weight.Bold))
lic_title.setStyleSheet("color: #e0e0e0;")
lic_layout.addWidget(lic_title)
lic_text = QLabel(
"Bu yazılım özgürdür; MIT Lisansı koşulları altında\n"
"değiştirebilir ve/veya dağıtabilirsiniz."
)
lic_text.setAlignment(Qt.AlignmentFlag.AlignCenter)
lic_text.setStyleSheet("color: #aaaaaa; font-size: 10px;")
lic_layout.addWidget(lic_text)
layout.addWidget(license_frame)
# Copyright
copy_label = QLabel("© 2025 - Tüm Hakları Saklıdır")
copy_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
copy_label.setStyleSheet("color: #666666; font-size: 10px; margin-top: 5px;")
layout.addWidget(copy_label)
class ScanThread(QThread):
progress = pyqtSignal(int, str)
finished = pyqtSignal(str, int, int, int)
def __init__(self, url):
super().__init__()
self.url = url
def run(self):
scanner = WebScanner(self.url)
scanner.scan(lambda p, msg: self.progress.emit(int(p), msg))
report_path = scanner.generate_report()
kritik = len([f for f in scanner.findings if f["risk"] in ["KRİTİK", "YÜKSEK"]])
self.finished.emit(os.path.abspath(report_path), len(scanner.findings), kritik, len(scanner.goods))
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("SitePenTest v1.0 - Security Scanner")
self.resize(750, 580)
self.center_window()
# Uygulama İkonu (Sol Üst)
icon_path = resource_path("assets/logo.png")
if os.path.exists(icon_path):
self.setWindowIcon(QIcon(icon_path))
central = QWidget()
self.setCentralWidget(central)
layout = QVBoxLayout(central)
layout.setContentsMargins(30, 30, 30, 30)
layout.setSpacing(15)
# --- Header (Logo ve Başlık) ---
header_layout = QHBoxLayout()
# Header Logosu
logo_label = QLabel()
pixmap = QPixmap(icon_path)
if not pixmap.isNull():
# Logo büyütüldü (100x100)
scaled = pixmap.scaled(100, 100, Qt.AspectRatioMode.KeepAspectRatio,
Qt.TransformationMode.SmoothTransformation)
logo_label.setPixmap(scaled)
header_layout.addWidget(logo_label)
# Başlık Yazısı
title_box = QVBoxLayout()
title_box.setSpacing(0)
title_box.setAlignment(Qt.AlignmentFlag.AlignVCenter) # Dikey ortalama
title_text = QLabel("SitePenTest")
title_text.setFont(QFont("Segoe UI", 32, QFont.Weight.Bold)) # Font biraz daha büyütüldü
title_text.setStyleSheet("color: #0f172a;")
title_box.addWidget(title_text)
# Alt başlık kaldırıldı
header_layout.addLayout(title_box)
header_layout.addStretch()
# Hakkında Butonu
about_btn = QPushButton("Hakkında")
about_btn.setCursor(Qt.CursorShape.PointingHandCursor)
about_btn.setStyleSheet("""
QPushButton { background: #f1f5f9; color: #334155; border: 1px solid #e2e8f0; border-radius: 6px; padding: 6px 15px; font-weight: 600; font-size: 12px;}
QPushButton:hover { background: #e2e8f0; color: #0f172a; }
""")
about_btn.clicked.connect(self.show_about)
header_layout.addWidget(about_btn)
layout.addLayout(header_layout)
# --- URL Input Alanı ---
input_frame = QFrame()
input_frame.setStyleSheet("background: #f8fafc; border-radius: 12px; border: 1px solid #e2e8f0;")
input_layout = QHBoxLayout(input_frame)
input_layout.setContentsMargins(8, 8, 8, 8)
self.url_input = QLineEdit()
self.url_input.setPlaceholderText("https://ornek-site.com")
self.url_input.setFont(QFont("Consolas", 12))
self.url_input.setStyleSheet("border: none; background: transparent; color: #334155;")
input_layout.addWidget(self.url_input)
self.scan_btn = QPushButton(" Analizi Başlat ")
self.scan_btn.setFont(QFont("Segoe UI", 11, QFont.Weight.Bold))
self.scan_btn.setCursor(Qt.CursorShape.PointingHandCursor)
self.scan_btn.setStyleSheet("""
QPushButton { background: #4f46e5; color: white; padding: 10px 20px; border-radius: 8px; }
QPushButton:hover { background: #4338ca; }
QPushButton:disabled { background: #94a3b8; }
""")
self.scan_btn.clicked.connect(self.start_scan)
input_layout.addWidget(self.scan_btn)
layout.addWidget(input_frame)
# --- Progress Bar ---
self.progress_bar = QProgressBar()
self.progress_bar.setRange(0, 100)
self.progress_bar.setTextVisible(False)
self.progress_bar.setFixedHeight(6)
self.progress_bar.setStyleSheet("""
QProgressBar { border-radius: 3px; background: #e2e8f0; border: none; }
QProgressBar::chunk { background: #22c55e; border-radius: 3px; }
""")
layout.addWidget(self.progress_bar)
self.status_label = QLabel("Taramaya hazır")
self.status_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.status_label.setStyleSheet("color: #64748b; font-size: 11px;")
layout.addWidget(self.status_label)
# --- Sonuç Ekranı ---
self.result_text = QTextBrowser()
self.result_text.setOpenExternalLinks(False)
self.result_text.anchorClicked.connect(self.open_link)
self.result_text.setStyleSheet("""
QTextBrowser {
border: 1px solid #e2e8f0;
border-radius: 12px;
padding: 15px;
background: #ffffff;
color: #334155;
font-family: 'Segoe UI';
font-size: 13px;
}
""")
layout.addWidget(self.result_text)
def center_window(self):
screen = QApplication.primaryScreen().geometry()
window = self.frameGeometry()
window.moveCenter(screen.center())
self.move(window.topLeft())
def show_about(self):
dialog = AboutDialog()
dialog.exec()
def start_scan(self):
url = self.url_input.text().strip()
if not url:
QMessageBox.warning(self, "Uyarı", "Lütfen geçerli bir URL giriniz.")
return
self.scan_btn.setEnabled(False)
self.url_input.setEnabled(False)
self.progress_bar.setValue(0)
self.result_text.clear()
self.status_label.setText("Bağlantı kuruluyor...")
self.result_text.setHtml(
"<h3 style='color:#64748b; text-align:center; margin-top:40px;'>Analiz Başlatılıyor...</h3>")
self.thread = ScanThread(url)
self.thread.progress.connect(self.update_progress)
self.thread.finished.connect(self.scan_finished)
self.thread.start()
def update_progress(self, value: int, message: str):
self.progress_bar.setValue(value)
self.status_label.setText(message)
def scan_finished(self, report_path: str, total: int, critical: int, good: int):
self.scan_btn.setEnabled(True)
self.url_input.setEnabled(True)
self.progress_bar.setValue(100)
self.status_label.setText("Tamamlandı.")
report_url = QUrl.fromLocalFile(report_path).toString()
color = "#ef4444" if critical > 0 else "#22c55e"
title_text = "Riskler Tespit Edildi" if critical > 0 else "Sistem Güvenli"
html = f"""
<div style="text-align:center; font-family: 'Segoe UI';">
<h2 style="color:{color}; margin: 0;">{title_text}</h2>
<p style="color: #64748b; margin-top:5px;">Toplam <b>{total}</b> bulgu</p>
<div style="background:#f8fafc; border:1px dashed #cbd5e1; padding:20px; border-radius:10px; margin: 20px 0;">
<b style="color:#0f172a; font-size:14px;">📄 Rapor Oluşturuldu</b><br><br>
<a href="{report_url}" style="background-color:{color}; color:white; text-decoration:none; padding:10px 20px; border-radius:6px; font-weight:bold;">
Raporu Görüntüle / Aç
</a>
<br><br>
<span style="font-size:11px; color:#94a3b8;">Dosya Yolu: {report_path}</span>
</div>
<p style="color:#94a3b8; font-size:11px;">
PDF kaydetmek için açılan raporda "PDF Olarak Kaydet" butonunu kullanın.
</p>
</div>
"""
self.result_text.setHtml(html)
def open_link(self, url):
QDesktopServices.openUrl(url)
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setStyle("Fusion")
window = MainWindow()
window.show()
sys.exit(app.exec())
Bu uygulamayı yalnızca kendi web siteniz / hostinginiz ya da yazılı izin aldığınız yerlerde kullanınız. Kanunen şahsınıza ait olmayan ya da yetkilendirilmediğiniz web site/ hosting vb. ortamlarda bu araçları kullanmak kanunen suçtur !!
Hiç bir sorumluluk kabul etmemekteyim. Uygulamanın kullanılmasından kaynaklı her türlü hukuki vb problem kullanana aittir.
-----Program adresini girdiğiniz web sitesinin en çok bilinen güvenlik açıkları (xss, csrf, csp, hi jack, fingerprint vb..) 16 fonksiyon ile taramasını yapar ve size bir sistem raporu ile puanı bildirir.
Bir açık ya da tehdit var ise bunun nasıl zarar verebileceğini ve düzeltmek için neler yapacağınız konusun da tavsiyelerde bulunur.
Web sitenizi zırhlandırmasa da yoldan geçenlerin size tehdit oluşmasını engellemeyi sağlar.
MIT lisansı ile dağıtılmaktadır.
---Pardus 25 / Debian 13 linux tabanlı dağıtımlar için üretilmiştir.
---Kurmak için
İndir
linkinden .deb paketi indiripkurabilirya da
kaynak kod indirip
sudo sh ./build_deb.sh komutu ile paketleyip sudo dpkg -i sitepentest_v1.0_amd64.deb ile kurabilirsiniz. sitepentest yazarak yada başlat menüsünden çalıştırabilirsiniz Meta Veri (Özet)
Web masterlar ya da özellikle ai ile web sitesi yapanlar için siteniz / hosting inizin güvenlik taramasını yapın. Sorunları / açıkları, tehditleri raporlayın