Sensitive Information Extraction Tool for Internal Network Penetration Testing Developed in Python

This is an internal network information collection tool developed based on PyQt6, capable of automatically scanning various text files (including code files, configuration files, log files, etc.) in a specified directory. It uses customizable regular expression scanning rules to detect and identify sensitive information in files, such as passwords, API keys, database connection strings, and other security risks. The tool supports multi-threaded concurrent processing to improve scanning efficiency, provides real-time progress monitoring, and generates detailed HTML format scanning reports. Users can flexibly configure the activation status and risk levels of detection rules according to actual needs, focusing on internal network security audits and sensitive information leakage detection.

Main Features

File Scanning and Information Collection

  • Automatically scans text files in the specified directory to find potential sensitive information
  • Supports various file formats: .txt, .py, .js, .json, .xml, .yaml, .sql, .log, .md, .html, .php, .java, etc.
  • Uses regular expression pattern matching to identify sensitive content

Multi-threaded Processing

  • Supports concurrent scanning with 2-16 threads to improve scanning efficiency
  • Configurable thread count to adapt to different system performances

Intelligent File Filtering

  • Automatically skips system folders (such as .git, node_modules, __pycache__, etc.)
  • Supports various character encodings (UTF-8, GBK, GB2312, Latin-1)

The tool is built using PyQt6 and includes the following features:

1. Scanning

  • Directory Selection: Choose the target directory to scan
  • Scanning Options: Configure the number of threads and report file name
  • Progress Monitoring: Real-time display of scanning progress and currently processed files
  • Action Buttons: Start scan, stop scan, view report

2. Results

  • Statistics: Displays total number of files, scanned files, skipped files, error files, and risk files
  • Results Table: Summarizes found sensitive information by type
  • Detailed View: Double-click to view specific matching results and file locations

3. Configuration

  • Rule Management: View and manage detection rules
  • Rule Switch: Enable or disable specific detection rules
  • Configuration Editing: Supports editing configuration files

Technical Features

Pattern Matching System

  • Detection rules are stored in a JSON configuration file
  • Each rule includes a regular expression, risk level, and description
  • Supports dynamic loading and reloading of configurations

Report Generation

  • Automatically generates detailed scanning reports in HTML format
  • Includes statistics, risk classifications, and specific matching results
  • Supports viewing reports in a browser

Applicable Scenarios

  1. Internal Network Security Check: Detect sensitive information leakage in code and configuration files
  2. Compliance Audit: Ensure sensitive data meets security standards
  3. Code Review: Check for potential security risks before code submission
  4. Data Classification: Identify and classify different types of sensitive information

Code

import sys
import os
import re
import json
import threading
from datetime import datetime
from pathlib import Path
from typing import Dict, List, Tuple, Optional
import mimetypes
from PyQt6.QtGui import QIcon
from concurrent.futures import ThreadPoolExecutor, as_completed
from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,                             QHBoxLayout, QGridLayout, QTabWidget, QGroupBox,                            QLabel, QLineEdit, QPushButton, QProgressBar,                            QTextEdit, QTableWidget, QTableWidgetItem,                            QFileDialog, QMessageBox, QComboBox, QCheckBox,                            QHeaderView, QFrame)
from PyQt6.QtCore import Qt, QThread, pyqtSignal
from PyQt6.QtGui import QFont

class PatternLoader:
    def __init__(self):
        self.config_file = "patterns.json"
        self.patterns = self.load_patterns()

    def load_patterns(self):
        if not os.path.exists(self.config_file):
            return {}

        try:
            with open(self.config_file, 'r', encoding='utf-8') as f:
                data = json.load(f)
                return data
        except Exception as e:
            print(f"Failed to load configuration file: {e}")
            return {}

    def get_active_patterns(self):
        compiled = {}
        for name, config in self.patterns.items():
            if config.get("enabled", True):
                try:
                    compiled[name] = re.compile(config["regex"], re.MULTILINE | re.DOTALL)
                except re.error:
                    continue
        return compiled

class ScanThread(QThread):
    progress_signal = pyqtSignal(int, str)
    status_signal = pyqtSignal(str)
    finished_signal = pyqtSignal(dict, dict)

    def __init__(self, directory, patterns, threads):
        super().__init__()
        self.directory = directory
        self.patterns = patterns
        self.thread_count = threads
        self.stop_flag = False
        self.results = {}
        self.stats = {"total": 0, "scanned": 0, "skipped": 0, "errors": 0}

    def run(self):
        try:
            self.status_signal.emit("Collecting files...")
            files = self.collect_files()
            self.stats["total"] = len(files)

            if not files:
                self.status_signal.emit("No files found")
                return

            self.status_signal.emit(f"Starting scan of {len(files)} files")
            self.process_files(files)

            if not self.stop_flag:
                self.status_signal.emit("Scan complete")
                self.finished_signal.emit(self.results, self.stats)

        except Exception as e:
            self.status_signal.emit(f"Scan error: {str(e)}")

    def collect_files(self):
        files = []
        text_exts = {'.txt', '.py', '.js', '.json', '.xml', '.yaml', '.yml',                     '.ini', '.cfg', '.conf', '.properties', '.sql', '.log',                     '.md', '.html', '.htm', '.css', '.php', '.java', '.cpp',                     '.c', '.h', '.cs', '.go', '.rs', '.rb', '.pl', '.sh'}

        for root, dirs, filenames in os.walk(self.directory):
            dirs[:] = [d for d in dirs if not d.startswith('.') and                       d not in {'node_modules', '__pycache__', '.git'}]

            for filename in filenames:
                if filename.startswith('.'):  
                    continue

                file_path = os.path.join(root, filename)
                ext = Path(filename).suffix.lower()

                if ext in text_exts:
                    files.append(file_path)
        return files

    def process_files(self, files):
        with ThreadPoolExecutor(max_workers=self.thread_count) as executor:
            futures = {executor.submit(self.scan_file, f): f for f in files}

            completed = 0
            for future in as_completed(futures):
                if self.stop_flag:
                    break

                file_path = futures[future]
                completed += 1

                try:
                    result = future.result()
                    if result:
                        self.results[file_path] = result
                    self.stats["scanned"] += 1
                except Exception:
                    self.stats["errors"] += 1

                progress = int((completed / len(files)) * 100)
                filename = os.path.basename(file_path)
                self.progress_signal.emit(progress, filename)

    def scan_file(self, file_path):
        try:
            content = self.read_file(file_path)
            if not content:
                return {}

            results = {}
            lines = content.split('\n')

            for name, pattern in self.patterns.items():
                matches = []
                for line_num, line in enumerate(lines, 1):
                    for match in pattern.finditer(line):
                        matches.append({
                            'text': match.group(0),
                            'line': line_num
                        })

                if matches:
                    results[name] = matches
            return results
        except Exception:
            return {}

    def read_file(self, file_path):
        encodings = ['utf-8', 'gbk', 'gb2312', 'latin-1']
        for encoding in encodings:
            try:
                with open(file_path, 'r', encoding=encoding) as f:
                    return f.read()
            except UnicodeDecodeError:
                continue
            except Exception:
                break
        return ""

    def stop(self):
        self.stop_flag = True

Sensitive Information Extraction Tool for Internal Network Penetration Testing Developed in PythonSensitive Information Extraction Tool for Internal Network Penetration Testing Developed in PythonSensitive Information Extraction Tool for Internal Network Penetration Testing Developed in PythonSensitive Information Extraction Tool for Internal Network Penetration Testing Developed in PythonSensitive Information Extraction Tool for Internal Network Penetration Testing Developed in PythonReply in the backgroundInformation collectionGet the complete source code and tool

Leave a Comment