Python ile Basit Bir Web Uygulaması Güvenlik Tarayıcısı Oluşturma: Yeni Başlayan Kılavuz


Bu makalede, web uygulamalarındaki yaygın güvenlik açıklarını belirlemede yardımcı olabilecek temel bir güvenlik aracı oluşturmayı öğreneceksiniz.

Burada iki hedefim var. Birincisi, web sitelerinizin genel güvenlik duruşunu geliştirmeye yardımcı olabilecek araçlar geliştirme becerileri ile güçlendirmektir. İkincisi, bazı Python programlamaları uygulamanıza yardımcı olmaktır.

Bu kılavuzda, XSS, SQL enjeksiyonu ve hassas PII (kişisel olarak tanımlanabilir bilgiler) tespit edebilen Python tabanlı bir güvenlik tarayıcısı oluşturacaksınız.

Güvenlik açıkları türleri

Genel olarak, web güvenlik açıklarını aşağıdaki kovalara kategorize edebiliriz (daha fazla kova için OWASP Top 10'u kontrol edin):

  • SQL enjeksiyonu: Saldırganların, doğrulanmamış girişler aracılığıyla SQL sorgularına kötü amaçlı SQL kodu ekleyebildiği ve veritabanı içeriğini değiştirmelerine/okumalarına olanak tanıyan bir teknik.

  • Siteler Arası Komut Dosyası Çalıştırma (XSS): Saldırganların güvenilen web sitelerine kötü amaçlı JavaScript yerleştirdiği bir teknik. Bu, onların tarayıcı bağlamında JavaScript kodunu yürütmelerine, hassas bilgileri çalmalarına veya yetkisiz işlemler gerçekleştirmelerine olanak tanır.

  • Hassas bilgilerin açığa çıkması: Bir uygulamanın günlükler, güvenli olmayan depolama ve diğer güvenlik açıkları aracılığıyla şifreler, API anahtarları vb. gibi hassas verileri istemeden açığa çıkardığı bir güvenlik sorunu.

  • Yaygın güvenlik yanlış yapılandırmaları: Yönetici hesapları için varsayılan kimlik bilgileri, etkinleştirilen hata ayıklama modu, zayıf kimlik bilgilerine sahip herkese açık yönetici kontrol panelleri vb. gibi web sunucularının hatalı yapılandırılması nedeniyle ortaya çıkan güvenlik sorunları.

  • Temel Kimlik Doğrulama Zayıf Yönleri : Parola politikalarındaki turlar, kullanıcı kimlik doğrulaması işlemleri, uygunsuz oturum yönetimi vb.

İçindekiler

  • Önkoşul

  • Geliştirme Ortamımızı Kurma

  • Temel Tarayıcı Sınıfımızı Oluşturuyoruz

  • Tarayıcının Uygulanması

  • Güvenlik Kontrollerinin Tasarlanması ve Uygulanması

    • SQL Enjeksiyon Algılama Kontrolü

    • XSS (Siteler Arası Komut Dosyası) Kontrol

    • Hassas Bilgi Maruz Kalma Kontrolü

  • Ana tarama mantığını uygulamak

  • Güvenlik Tarayıcısını Genişletme

  • Sarma

Önkoşullar

Bu öğreticiyi takip etmek için aşağıdakilere ihtiyacınız olacak:

  • Python 3.x

  • HTTP protokollerinin temel anlayışı

  • Web uygulamalarının temel anlayışı

  • XSS, SQL enjeksiyonu ve temel güvenlik saldırılarının nasıl çalıştığına dair temel anlayış

Geliştirme Ortamımızı Kurma

Aşağıdaki komutla gerekli bağımlılıklarımızı yükleyelim:

pip install requests beautifulsoup4 urllib3 colorama

Bu bağımlılıkları kod dosyamızda kullanacağız:

# Required packages
import requests
from bs4 import BeautifulSoup
import urllib.parse
import colorama
import re
from concurrent.futures import ThreadPoolExecutor
import sys
from typing import List, Dict, Set

Temel Tarayıcı Sınıfımızı Oluşturma

Bağımlılıklara sahip olduğunuzda, çekirdek tarayıcı sınıfını yazmanın zamanı geldi.

Bu sınıf, web güvenliği tarama işlevini yürütecek ana sınıfımız olarak görev yapacak. Ziyaret ettiğimiz sayfalarımızı takip edecek ve bulgularımızı da saklayacak.

Daha önce görülmüş olan URL'leri yeniden yayınlamadığınızdan emin olmak için kullanacağımız normalize_url işlevine sahibiz. Bu işlev esasen HTTP Get parametrelerini URL'den kaldıracaktır. Örneğin, https://example.com/page?id=1 normalleştirdikten sonra https://example.com/page olur.

class WebSecurityScanner:
    def __init__(self, target_url: str, max_depth: int = 3):
        """
        Initialize the security scanner with a target URL and maximum crawl depth.

        Args:
            target_url: The base URL to scan
            max_depth: Maximum depth for crawling links (default: 3)
        """
        self.target_url = target_url
        self.max_depth = max_depth
        self.visited_urls: Set[str] = set()
        self.vulnerabilities: List[Dict] = []
        self.session = requests.Session()

        # Initialize colorama for cross-platform colored output
        colorama.init()

    def normalize_url(self, url: str) -> str:
        """Normalize the URL to prevent duplicate checks"""
        parsed = urllib.parse.urlparse(url)
        return f"{parsed.scheme}://{parsed.netloc}{parsed.path}"

Paletli uygulama

Tarayıcımızdaki ilk adım, belirli bir hedef uygulamadaki sayfaları ve URL'leri keşfedecek bir web tarayıcısı uygulamaktır. Bu işlevleri WebSecurityScanner sınıfımıza yazdığınızdan emin olun.

def crawl(self, url: str, depth: int = 0) -> None:
    """
    Crawl the website to discover pages and endpoints.

    Args:
        url: Current URL to crawl
        depth: Current depth in the crawl tree
    """
    if depth > self.max_depth or url in self.visited_urls:
        return

    try:
        self.visited_urls.add(url)
        response = self.session.get(url, verify=False)
        soup = BeautifulSoup(response.text, 'html.parser')

        # Find all links in the page
        links = soup.find_all('a', href=True)
        for link in links:
            next_url = urllib.parse.urljoin(url, link['href'])
            if next_url.startswith(self.target_url):
                self.crawl(next_url, depth + 1)

    except Exception as e:
        print(f"Error crawling {url}: {str(e)}")

Bu tarama işlevi, bir web sitesinde derinlemesine tarama yapmamıza yardımcı olur. Belirtilen etki alanı içinde kalarak bir web sitesinin tüm sayfalarını keşfedecektir.

Örneğin, bu tarayıcıyı https://google.com üzerinde kullanmayı planlıyorsanız, işlev önce tüm URL'leri alacak ve ardından bunların belirtilen alana ait olup olmadığını tek tek kontrol edecektir ( yani google.com). Eğer öyleyse, görülen URL'yi, işleve argüman olarak derinlik parametresi ile sağlanan belirli bir derinliğe kadar yinelemeli olarak taramaya devam edecektir. Ayrıca hataları sorunsuz bir şekilde ele aldığımızdan ve tarama sırasında hataları bildirdiğimizden emin olmak için bazı istisna işleme yöntemlerimiz de vardır.

Güvenlik kontrollerinin tasarlanması ve uygulanması

Şimdi nihayet işin ilginç kısmına geçelim ve güvenlik kontrollerimizi uygulayalım. İlk olarak SQL Injection ile başlayacağız.

SQL Enjeksiyon Algılama Kontrolü

def check_sql_injection(self, url: str) -> None:
    """Test for potential SQL injection vulnerabilities"""
    sql_payloads = ["'", "1' OR '1'='1", "' OR 1=1--", "' UNION SELECT NULL--"]

    for payload in sql_payloads:
        try:
            # Test GET parameters
            parsed = urllib.parse.urlparse(url)
            params = urllib.parse.parse_qs(parsed.query)

            for param in params:
                test_url = url.replace(f"{param}={params[param][0]}", 
                                     f"{param}={payload}")
                response = self.session.get(test_url)

                # Look for SQL error messages
                if any(error in response.text.lower() for error in 
                    ['sql', 'mysql', 'sqlite', 'postgresql', 'oracle']):
                    self.report_vulnerability({
                        'type': 'SQL Injection',
                        'url': url,
                        'parameter': param,
                        'payload': payload
                    })

        except Exception as e:
            print(f"Error testing SQL injection on {url}: {str(e)}")

Bu işlev esas olarak, URL'yi ortak SQL enjeksiyon yüklerine karşı test ederek ve güvenlik açığı için ipucu verebilecek hata mesajları arayarak temel SQL enjeksiyon kontrollerini gerçekleştirir.

URL'de basit bir GET isteği gerçekleştirdikten sonra alınan hata mesajına dayanarak, bu mesajın bir veritabanı hatası olup olmadığını kontrol ediyoruz. Eğer öyleyse, son raporumuzda bu komut dosyasının oluşturulacağını bildirmek için report_vulnerability işlevini kullanırız. Bu örnek uğruna, yaygın olarak test edilmiş birkaç SQL enjeksiyon yükü seçiyoruz, ancak daha fazla test etmek için bunu genişletebilirsiniz.

XSS (Siteler Arası Komut Dosyası) Kontrol

Şimdi XSS payloadları için ikinci güvenlik kontrolünü uygulayalım.

def check_xss(self, url: str) -> None:
    """Test for potential Cross-Site Scripting vulnerabilities"""
    xss_payloads = [
        "<script>alert('XSS')</script>",
        "<img src=x onerror=alert('XSS')>",
        "javascript:alert('XSS')"
    ]

    for payload in xss_payloads:
        try:
            # Test GET parameters
            parsed = urllib.parse.urlparse(url)
            params = urllib.parse.parse_qs(parsed.query)

            for param in params:
                test_url = url.replace(f"{param}={params[param][0]}", 
                                     f"{param}={urllib.parse.quote(payload)}")
                response = self.session.get(test_url)

                if payload in response.text:
                    self.report_vulnerability({
                        'type': 'Cross-Site Scripting (XSS)',
                        'url': url,
                        'parameter': param,
                        'payload': payload
                    })

        except Exception as e:
            print(f"Error testing XSS on {url}: {str(e)}")

Bu işlev, tıpkı SQL enjeksiyon test cihazı gibi, bir dizi ortak XSS verisi kullanır ve aynı fikri uygular. Ancak buradaki temel fark, bir hata mesajı aramak yerine, enjekte edilen yükümüzün yanıtımızda değiştirilmemiş görünmesini aramamızdır.

Enjekte edilen yükümüzü görebiliyorsanız, büyük olasılıkla mağdurun tarayıcısı bağlamında yansıtılan bir XSS saldırısı olarak yürütülecektir.

Hassas Bilgi Maruz Kalma Kontrolü

Şimdi hassas PII için son kontrolümüzü uygulayalım.

def check_sensitive_info(self, url: str) -> None:
    """Check for exposed sensitive information"""
    sensitive_patterns = {
        'email': r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}',
        'phone': r'\b\d{3}[-.]?\d{3}[-.]?\d{4}\b',
        'ssn': r'\b\d{3}-\d{2}-\d{4}\b',
        'api_key': r'api[_-]?key[_-]?([\'"|`])([a-zA-Z0-9]{32,45})\1'
    }

    try:
        response = self.session.get(url)

        for info_type, pattern in sensitive_patterns.items():
            matches = re.finditer(pattern, response.text)
            for match in matches:
                self.report_vulnerability({
                    'type': 'Sensitive Information Exposure',
                    'url': url,
                    'info_type': info_type,
                    'pattern': pattern
                })

    except Exception as e:
        print(f"Error checking sensitive information on {url}: {str(e)}")

Bu işlev, e-postalar, telefon numaraları, SSN'ler ve API anahtarları (api-key- önekiyle eklenmiştir) gibi PII'leri aramak için önceden tanımlanmış bir dizi Regex modelini kullanır.

Önceki iki işlevde olduğu gibi, yanıt metninde bu PII'leri bulmak için URL'ye ilişkin yanıt metnini ve Regex modellerimizi kullanırız. Herhangi bir şey bulursak report_vulnerability işleviyle bildiririz. Tüm bu işlevlerin WebSecurityScanner sınıfında tanımlandığından emin olun.

Ana Tarama Mantığını Uygulama

Son olarak WebSecurityScanner sınıfında scan ve report_vulnerability işlevini tanımlayarak her şeyi bir araya getirelim:

def scan(self) -> List[Dict]:
    """
    Main scanning method that coordinates the security checks

    Returns:
        List of discovered vulnerabilities
    """
    print(f"\n{colorama.Fore.BLUE}Starting security scan of {self.target_url}{colorama.Style.RESET_ALL}\n")

    # First, crawl the website
    self.crawl(self.target_url)

    # Then run security checks on all discovered URLs
    with ThreadPoolExecutor(max_workers=5) as executor:
        for url in self.visited_urls:
            executor.submit(self.check_sql_injection, url)
            executor.submit(self.check_xss, url)
            executor.submit(self.check_sensitive_info, url)

    return self.vulnerabilities

def report_vulnerability(self, vulnerability: Dict) -> None:
    """Record and display found vulnerabilities"""
    self.vulnerabilities.append(vulnerability)
    print(f"{colorama.Fore.RED}[VULNERABILITY FOUND]{colorama.Style.RESET_ALL}")
    for key, value in vulnerability.items():
        print(f"{key}: {value}")
    print()

Bu kod, esasen tarama işlevini çağıracak ve yinelemeli olarak web sitesini taramaya başlayacak olan tarama işlevimizi tanımlar. Çoklu iş parçacığıyla, ziyaret edilen URL'lere üç güvenlik kontrolünün tümünü uygulayacağız.

Ayrıca, güvenlik açığımızı konsola etkili bir şekilde yazdıracak ve bunları güvenlik açıklarımızda dizimizde saklayacak report_vulnerability işlevini de tanımladık.

Şimdi son olarak tarayıcımızı scanner.py olarak kaydederek kullanalım:

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("Usage: python scanner.py <target_url>")
        sys.exit(1)

    target_url = sys.argv[1]
    scanner = WebSecurityScanner(target_url)
    vulnerabilities = scanner.scan()

    # Print summary
    print(f"\n{colorama.Fore.GREEN}Scan Complete!{colorama.Style.RESET_ALL}")
    print(f"Total URLs scanned: {len(scanner.visited_urls)}")
    print(f"Vulnerabilities found: {len(vulnerabilities)}")

Hedef URL bir sistem argümanı olarak sağlanacak ve taranan URL'lerin ve taramamızın sonunda bulunan güvenlik açıklarının özetini alacağız. Şimdi tarayıcıyı nasıl genişletebileceğinizi ve daha fazla özellik ekleyebileceğinizi tartışalım.

Güvenlik tarayıcısının genişletilmesi

İşte bu temel güvenlik tarayıcısını daha da gelişmiş bir şeye genişletmek için bazı fikirler:

  1. CSRF tespiti, dizin geçişi vb. gibi daha fazla güvenlik açığı kontrolü ekleyin.

  2. HTML veya PDF çıktısıyla raporlamayı iyileştirin.

  3. Tarama yoğunluğu ve arama kapsamı için yapılandırma seçenekleri ekleyin (bir CLI bağımsız değişkeni aracılığıyla taramaların derinliğini belirterek).

  4. Uygun oran sınırlamasının uygulanması.

  5. Oturum tabanlı kimlik doğrulaması gerektiren URL'leri test etmek için kimlik doğrulama desteği ekleme.

Sarma

Artık temel bir güvenlik tarayıcısının nasıl oluşturulacağını biliyorsunuz! Bu tarayıcı Web Güvenliğinin birkaç temel kavramını göstermektedir.

Bu öğreticinin yalnızca eğitim amaçlı kullanılması gerektiğini unutmayın. Burp Suite ve OWASP ZAP gibi, çok daha büyük bir ölçekte yüzlerce güvenlik açıklığını kontrol edebilen profesyonel olarak tasarlanmış birkaç kurumsal sınıf uygulaması vardır.

Umarım web güvenliğinin temellerini ve biraz da Python programlamayı öğrenmişsinizdir.