diff --git a/README.md b/README.md index b34d09c..e68ca20 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/gui_app.py b/gui_app.py index 8a7bf87..5fc29a4 100644 --- a/gui_app.py +++ b/gui_app.py @@ -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): @@ -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) @@ -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) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..f72d2f5 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +Jinja2 +reportlab diff --git a/script.py b/script.py index 3abbd60..534f98c 100644 --- a/script.py +++ b/script.py @@ -1,5 +1,6 @@ import os import sys +import json from datetime import datetime # Importa as classes que criamos @@ -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() @@ -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 [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 [caminho2...] [--no-report] [--formato ]") + 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 [outro_caminho...] [--no-report]") - sys.exit(1) # Sai com erro se nao encontrar arquivos PHP + print("Uso: python script.py [caminho2...] [--no-report] [--formato ]") + 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 [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.") \ No newline at end of file + 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.") \ No newline at end of file