Warning: Undefined array key "pl" in /home/host1693024/python-3.com/htdocs/www/875348534534.php on line 2036
Tworzenie prostego skanera bezpieczeństwa aplikacji internetowych za pomocą języka Python: przewodnik dla początkujących

Tworzenie prostego skanera bezpieczeństwa aplikacji internetowych za pomocą języka Python: przewodnik dla początkujących


W tym artykule nauczysz się tworzyć podstawowe narzędzie bezpieczeństwa, które może być pomocne w identyfikowaniu typowych luk w aplikacjach internetowych.

Mam tu dwa cele. Pierwszym z nich jest wyposażenie Cię w umiejętności tworzenia narzędzi, które mogą pomóc w poprawie ogólnego stanu bezpieczeństwa Twoich witryn internetowych. Drugim zadaniem jest pomoc w przećwiczeniu programowania w języku Python.

W tym przewodniku zbudujesz skaner bezpieczeństwa oparty na języku Python, który będzie w stanie wykryć XSS, wstrzyknięcie SQL i wrażliwe dane osobowe (PII).

Rodzaje luk

Ogólnie rzecz biorąc, możemy podzielić luki w zabezpieczeniach sieci na następujące grupy (jeszcze więcej grup znajdziesz w OWASP Top 10):

  • Wtrysku SQL : Technika, w której atakujący są w stanie wstawić złośliwy kod SQL do zapytań SQL za pomocą niekolidowanych wejść, umożliwiając im modyfikację/odczyt treści bazy danych.

  • Skrypty krzyżowe (XSS) : Technika, w której atakujący wstrzykują złośliwy JavaScript na zaufanych stronach internetowych. To pozwala im wykonywać kod JavaScript w kontekście przeglądarki i ukraść poufne informacje lub wykonywać nieautoryzowane operacje.

  • poufne informacje na temat informacji : Problem bezpieczeństwa, w którym aplikacja nieumyślnie ujawnia poufne dane, takie jak hasła, klawisze API itd. Za pośrednictwem dzienników, niepewnej pamięci i innych luk.

  • Częste błędne konfiguracje zabezpieczeń: problemy z bezpieczeństwem wynikające z nieprawidłowej konfiguracji serwerów internetowych - takie jak domyślne poświadczenia dla kont administratorów, włączony tryb debugowania, publicznie dostępne panele administratora ze słabymi poświadczeniami i tak dalej.

  • Podstawowe słabości uwierzytelniania: problemy z bezpieczeństwem wynikające z uchybień w zasadach dotyczących haseł, procesów uwierzytelniania użytkowników, niewłaściwego zarządzania sesjami i tak dalej.

Spis treści

  • Wymagania wstępne

  • Konfigurowanie naszego środowiska programistycznego

  • Budowanie naszej klasy skanera podstawowego

  • Implementacja robota

  • Projektowanie i wdrażanie kontroli bezpieczeństwa

    • Kontrola wykrywania iniekcji SQL

    • Sprawdź XSS (skrypty między witrynami).

    • Kontrola narażenia na poufne informacje

  • Implementacja głównej logiki skanowania

  • Rozszerzanie skanera bezpieczeństwa

  • Podsumowanie

Wymagania wstępne

Aby śledzić ten samouczek, będziesz potrzebować:

  • Python 3.x

  • Podstawowa znajomość protokołów HTTP

  • Podstawowa znajomość aplikacji internetowych

  • Podstawowe zrozumienie działania XSS, SQL i podstawowych ataków bezpieczeństwa działają

Konfigurowanie naszego środowiska programistycznego

Zainstalujmy nasze wymagane zależności za pomocą następującego polecenia:

pip install requests beautifulsoup4 urllib3 colorama

Użyjemy tych zależności w naszym pliku kodu:

# 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

Budowanie naszej podstawowej klasy skanera

Po uzyskaniu zależności nadszedł czas, aby napisać podstawową klasę skanera.

Ta klasa będzie służyć jako nasza główna klasa, która będzie obsługiwać funkcję skanowania bezpieczeństwa sieci. Będzie śledzić odwiedzane przez nas strony, a także zapisywać nasze ustalenia.

Mamy funkcję Normalize_Url , której użyjemy, aby upewnić się, że nie ratujesz adresów URL, które były już widziane. Ta funkcja zasadniczo usunie parametry GET HTTP z adresu URL. Na przykład https://example.com/page?id=1 stanie się https://example.com/page po jego normalizacji.

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}"

Wdrożenie The Crawler

Pierwszym krokiem w naszym skanerze jest wdrożenie koła internetowego, który odkryje strony i adresy URL w danej aplikacji docelowej. Upewnij się, że piszesz te funkcje w naszej klasie WebSecurityScanner .

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)}")

Ta funkcja indeksowania pomaga nam dokładnie przeszukać witrynę. Będzie eksplorować wszystkie strony witryny internetowej, pozostając w określonej domenie.

Na przykład, jeśli planujesz użyć tego skanera w https://google.com , funkcja najpierw otrzyma wszystkie adresy URL, a następnie sprawdź, czy należą one do określonej domeny ( to znaczy Google.com ). Jeśli tak, rekurencyjnie będzie nadal skanować widoczny adres URL do określonej głębokości, która jest dostarczana z parametrem głębokości jako argument funkcji. Mamy również obsługę wyjątków, aby upewnić się, że płynnie obsługujemy błędy i zgłaszamy wszelkie błędy podczas pełzania.

Projektowanie i wdrażanie kontroli bezpieczeństwa

Przejdźmy teraz w końcu do pikantnej części i wprowadźmy nasze kontrole bezpieczeństwa. Zaczniemy najpierw od SQL Injection.

Kontrola wykrywania iniekcji SQL

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)}")

Ta funkcja zasadniczo wykonuje podstawowe kontrole wtrysku SQL, testując adres URL w stosunku do wspólnych ładunków iniekcyjnych SQL i szukając komunikatów o błędach, które mogą wskazywać na podatność bezpieczeństwa.

W oparciu o komunikat o błędzie otrzymany po wykonaniu prostego żądania GET w adresie URL, sprawdzamy, czy ta wiadomość jest błędem bazy danych, czy nie. Jeśli tak, używamy funkcji raport_vulneribility , aby zgłosić to jako problem bezpieczeństwa w naszym raporcie końcowym, który wygeneruje ten skrypt. Ze względu na ten przykład wybieramy kilka powszechnie testowanych ładunków wtrysku SQL, ale możesz to rozszerzyć, aby przetestować jeszcze więcej.

Sprawdź XSS (skrypty między witrynami).

Zaimplementujmy teraz drugą kontrolę bezpieczeństwa dla ładunków XSS.

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)}")

Ta funkcja, podobnie jak tester wtrysku SQL, wykorzystuje zestaw wspólnych ładunków XSS i stosuje ten sam pomysł. Ale kluczowa różnica polega na tym, że szukamy naszego wstrzykiwania ładunku, aby wyglądać na niezmodyfikowaną w naszej odpowiedzi, a nie szukać komunikatu o błędzie.

Jeśli widzisz nasz wstrzyknięty ładunek, najprawdopodobniej zostanie on wykonany w kontekście przeglądarki ofiary jako odzwierciedlony atak XSS.

Poufne informacje na temat narażenia informacji

Teraz zaimplementujmy naszą ostatnią kontrolę poufnego PII.

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)}")

Ta funkcja wykorzystuje zestaw predefiniowanych wzorców Regex do wyszukiwania informacji umożliwiających identyfikację, takich jak e-maile, numery telefonów, numery SSN i klucze API (które są poprzedzone api-key-).

Podobnie jak poprzednie dwie funkcje, używamy tekstu odpowiedzi dla wzorów adresu URL i naszych wzorców regex, aby znaleźć te PII w tekście odpowiedzi. Jeśli znajdziemy je, zgłaszamy je z funkcją raport_vulneribity . Upewnij się, że wszystkie te funkcje zostały zdefiniowane w klasie WebSecurityScanner .

Implementacja głównej logiki skanowania

Wreszcie zszyjmy wszystko razem, definiując funkcję skanowania i raport_vulneribility w klasie WebSecurityScanner :

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()

Ten kod określa naszą funkcję Skanowanie , która zasadniczo wywoła funkcję Crawl i rekurencyjnie zaczniekując witrynę. Dzięki wieloczynnikowi zastosujemy wszystkie trzy kontrole bezpieczeństwa odwiedzanych adresów URL.

Zdefiniowaliśmy również funkcję raport_vulneribility , która skutecznie wydrukuje naszą podatność na konsolę, a także przechowuje ją w naszej tablicy podatności .

Teraz wreszcie użyjmy naszego skanera, zapisując go jako scanner.py :

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)}")

Docelowy adres URL zostanie podany jako argument systemowy, a na koniec skanowania otrzymamy podsumowanie przeskanowanych adresów URL i wykrytych luk. Porozmawiajmy teraz, jak rozszerzyć skaner i dodać więcej funkcji.

Rozszerzenie skanera bezpieczeństwa

Oto kilka pomysłów na rozszerzenie tego podstawowego skanera bezpieczeństwa na coś jeszcze bardziej zaawansowanego:

  1. Dodaj więcej kontroli podatności, takich jak wykrywanie CSRF, przejście z katalogu i tak dalej.

  2. Ulepsz raportowanie dzięki wynikom w formacie HTML lub PDF.

  3. Dodaj opcje konfiguracji intensywności skanowania i zakresu wyszukiwania (określanie głębokości skanowania za pomocą argumentu CLI).

  4. Wdrożenie odpowiedniego ograniczenia szybkości.

  5. Dodanie obsługi uwierzytelniania do testowania adresów URL wymagających uwierzytelniania opartego na sesji.

Podsumowanie

Teraz wiesz, jak zbudować podstawowy skaner bezpieczeństwa! Ten skaner pokazuje kilka podstawowych koncepcji bezpieczeństwa sieci.

Należy pamiętać, że ten samouczek powinien być wykorzystywany wyłącznie do celów edukacyjnych. Istnieje kilka profesjonalnie zaprojektowanych aplikacji klasy korporacyjnej, takich jak Burp Suite i OWASP ZAP, które mogą sprawdzić setki luk w zabezpieczeniach na znacznie większą skalę.

Mam nadzieję, że nauczyłeś się podstaw bezpieczeństwa w sieci i trochę programowania w Pythonie.