Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Certifique-se de ter o Python 3.x (preferencialmente 3.13, como usado no desenvo

3. **Instale as dependências:**
```bash
pip install Jinja2 reportlab
pip install -r requirements.txt
```

### 3. Execução da Análise
Expand Down
20 changes: 19 additions & 1 deletion gui_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import threading
import subprocess

from script import AnalisadorEstatico
from script import AnalisadorEstatico, collect_php_files_from_path

class SecurityAnalyzerGUI:
def __init__(self, master):
Expand Down Expand Up @@ -42,6 +42,9 @@ def __init__(self, master):
self.btn_add_files = tk.Button(self.top_frame, text="Adicionar Arquivos PHP", command=self.add_files)
self.btn_add_files.pack(side=tk.LEFT, padx=5)

self.btn_add_dir = tk.Button(self.top_frame, text="Adicionar Diretório", command=self.add_directory)
self.btn_add_dir.pack(side=tk.LEFT, padx=5)

self.btn_clear_files = tk.Button(self.top_frame, text="Limpar Lista", command=self.clear_files)
self.btn_clear_files.pack(side=tk.LEFT, padx=5)

Expand Down Expand Up @@ -93,6 +96,21 @@ def add_files(self):
self.listbox_files.insert(tk.END, os.path.basename(f))
self.btn_analyze.config(state=tk.NORMAL)

def add_directory(self):
directory = filedialog.askdirectory(
title="Selecione um Diretório para Análise"
)
if directory:
php_files = collect_php_files_from_path(directory)
if php_files:
for f in php_files:
if f not in self.selected_files:
self.selected_files.append(f)
self.listbox_files.insert(tk.END, os.path.basename(f))
self.btn_analyze.config(state=tk.NORMAL)
else:
messagebox.showinfo("Nenhum Arquivo Encontrado", "Nenhum arquivo .php foi encontrado no diretório selecionado.")

def clear_files(self):
self.selected_files = []
self.listbox_files.delete(0, tk.END)
Expand Down
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Jinja2
reportlab
127 changes: 79 additions & 48 deletions script.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
import sys
import json
from datetime import datetime

# Importa as classes que criamos
Expand Down Expand Up @@ -34,53 +35,62 @@ def __init__(self, vul_config_path: str, diretorio_saida: str = "report"):
self.relatorio = GeradorRelatorio (diretorio_saida)
self.diretorio_saida = diretorio_saida

def analisar_arquivo_php(self, file_path: str):
def analisar_arquivo_php(self, file_path: str, quiet: bool = False):
"""
Analisa um único arquivo PHP em busca de vulnerabilidades.
Se quiet for True, suprime a saída no console.
"""
if not os.path.exists(file_path):
print(f"Erro: Arquivo '{file_path}' não encontrado.", file=sys.stderr)
if not quiet:
print(f"Erro: Arquivo '{file_path}' não encontrado.", file=sys.stderr)
return

print(f"Iniciando análise de: {file_path}")
if not quiet:
print(f"Iniciando análise de: {file_path}")
try:
with open(file_path, 'r', encoding='utf-8') as file:
php_code = file.read()
except Exception as e:
print(f"Erro ao ler o arquivo '{file_path}': {e}", file=sys.stderr)
if not quiet:
print(f"Erro ao ler o arquivo '{file_path}': {e}", file=sys.stderr)
return

vulnerabilidades_encontradas = self.detector.analyze_php_code(php_code, file_path)

if vulnerabilidades_encontradas:
print(f"Vulnerabilidades encontradas em {file_path}:")
if not quiet:
print(f"Vulnerabilidades encontradas em {file_path}:")
for vul in vulnerabilidades_encontradas:
self.relatorio.adicionar_vulnerabilidade(vul)
print(f"- {vul.type} na linha {vul.line} do arquivo: {os.path.basename(vul.file_path)} (Severidade: {vul.severity})")
else:
if not quiet:
print(f"- {vul.type} na linha {vul.line} do arquivo: {os.path.basename(vul.file_path)} (Severidade: {vul.severity})")
elif not quiet:
print(f"Nenhuma vulnerabilidade encontrada em {file_path}.")

def analisar_multiplos_arquivos_php(self, file_paths: list, generate_reports: bool = True) -> list:
def analisar_multiplos_arquivos_php(self, file_paths: list, generate_reports: bool = True, output_format: str = "text") -> list:
"""
Analisa uma lista de arquivos PHP em busca de vulnerabilidades.
Se generate_reports for True, gera os relatórios HTML/PDF.
Retorna a lista de todas as vulnerabilidades encontradas.
"""
self.relatorio.vulnerabilities = []
quiet_mode = output_format == "json"

if not file_paths:
print("Nenhum arquivo para analisar. Abortando.")
if not quiet_mode:
print("Nenhum arquivo para analisar. Abortando.")
return []

for file_path in file_paths:
self.analisar_arquivo_php(file_path)
self.analisar_arquivo_php(file_path, quiet=quiet_mode)

if generate_reports and self.relatorio.get_vulnerabilities():
self._gerar_relatorios_finais()
elif not self.relatorio.get_vulnerabilities():
print("Nenhuma vulnerabilidade encontrada. Relatórios não gerados.")
else:
print("Opção 'gerar relatórios' desativada. Relatórios não gerados.")
if not quiet_mode:
if generate_reports and self.relatorio.get_vulnerabilities():
self._gerar_relatorios_finais()
elif not self.relatorio.get_vulnerabilities():
print("Nenhuma vulnerabilidade encontrada. Relatórios não gerados.")
else:
print("Opção 'gerar relatórios' desativada. Relatórios não gerados.")

return self.relatorio.get_vulnerabilities()

Expand All @@ -104,44 +114,65 @@ def _gerar_relatorios_finais(self):
output_report_dir = "report"
analisador = AnalisadorEstatico(vul_config_json_path, diretorio_saida=output_report_dir)

input_paths_from_cli = []
args = sys.argv[1:]
generate_reports_final = True
output_format_final = "text"

# Processar argumentos da linha de comando
if len(sys.argv) > 1:
if "--no-report" in sys.argv:
generate_reports_final = False
sys.argv.remove("--no-report")
if "--no-report" in args:
generate_reports_final = False
args.remove("--no-report")

input_paths_from_cli = sys.argv[1:] # Pega todos os argumentos restantes

if not input_paths_from_cli: # Se não houver caminhos após remover --no-report
print("Erro: Nenhum arquivo ou diretório para analisar fornecido.")
print("Uso: python script.py <caminho_do_arquivo_ou_diretorio> [outro_caminho...] [--no-report]")
sys.exit(1) # Sai com erro se nao houver caminhos

# Coleta todos os arquivos PHP dos caminhos fornecidos (arquivos ou diretórios)
actual_files_to_analyze = []
for p in input_paths_from_cli:
if not os.path.exists(p):
if "--formato" in args:
try:
format_index = args.index("--formato")
output_format_final = args[format_index + 1]
if output_format_final not in ["text", "json"]:
print(f"Erro: Formato de saída '{output_format_final}' inválido. Use 'text' ou 'json'.")
sys.exit(1)
# Remove o argumento e seu valor da lista
args.pop(format_index)
args.pop(format_index)
except (ValueError, IndexError):
print("Erro: Argumento --formato requer um valor ('text' ou 'json').")
sys.exit(1)

input_paths_from_cli = args

if not input_paths_from_cli:
print("Erro: Nenhum arquivo ou diretório para analisar fornecido.")
print("Uso: python script.py <caminho1> [caminho2...] [--no-report] [--formato <text|json>]")
sys.exit(1)

actual_files_to_analyze = []
for p in input_paths_from_cli:
if not os.path.exists(p):
if output_format_final != "json":
print(f"Aviso: Caminho '{p}' não encontrado. Ignorando.", file=sys.stderr)
continue
collected = collect_php_files_from_path(p)
if not collected:
print(f"Aviso: Nenhum arquivo PHP encontrado em '{p}'. Ignorando.", file=sys.stderr)
actual_files_to_analyze.extend(collected)

if not actual_files_to_analyze:
continue
collected = collect_php_files_from_path(p)
if not collected and output_format_final != "json":
print(f"Aviso: Nenhum arquivo PHP encontrado em '{p}'. Ignorando.", file=sys.stderr)
actual_files_to_analyze.extend(collected)

if not actual_files_to_analyze:
if output_format_final != "json":
print("Erro: Nenhum arquivo PHP válido encontrado para análise nos caminhos fornecidos. Abortando.")
print("Uso: python script.py <caminho_do_arquivo_ou_diretorio> [outro_caminho...] [--no-report]")
sys.exit(1) # Sai com erro se nao encontrar arquivos PHP
print("Uso: python script.py <caminho1> [caminho2...] [--no-report] [--formato <text|json>]")
sys.exit(1)

if output_format_final != "json":
print(f"Modo de linha de comando: Analisando {len(actual_files_to_analyze)} arquivo(s).")
analisador.analisar_multiplos_arquivos_php(actual_files_to_analyze, generate_reports=generate_reports_final)
else:
# Se não houver argumentos na linha de comando, exibe o uso e sai
print("Uso: python script.py <caminho_do_arquivo_ou_diretorio> [outro_caminho...] [--no-report]")
print("Nenhum arquivo ou diretório para análise fornecido. Abortando.")
sys.exit(1) # Sai com erro

print("\nAnálise concluída.")
vulnerabilidades = analisador.analisar_multiplos_arquivos_php(
actual_files_to_analyze,
generate_reports=generate_reports_final,
output_format=output_format_final
)

if output_format_final == "json":
# Converte a lista de vulnerabilidades para um formato serializável
json_output = [v.to_dict() for v in vulnerabilidades]
print(json.dumps(json_output, indent=4))
else:
print("\nAnálise concluída.")