├── README.md └── g1t-3xpl01t3.sh /README.md: -------------------------------------------------------------------------------- 1 | # G1t-3xpl01t v. 2.0 2 | ![image](https://github.com/user-attachments/assets/2278bba2-6d53-4ee5-952e-7793e4f76fcc) 3 | ## Descrição 4 | 5 | O **G1t-3xpl01t** é uma ferramenta destinada a profissionais de segurança, entusiastas de hacking e equipes de Red Team. O script automatiza a busca de informações relacionadas a CVEs (Common Vulnerabilities and Exposures) e explora o GitHub para encontrar repositórios relacionados a exploits, PoCs (Proof of Concept) e vulnerabilidades. 6 | 7 | Esta ferramenta pode ser usada para: 8 | 9 | - Localizar CVEs associadas a palavras-chave específicas. 10 | - Localiza CVEs, score e descrição das mesma 11 | - Buscar por repositórios no GitHub que contenham informações sobre exploits, PoCs e vulnerabilidades associadas a essas CVEs. 12 | - Obter escores EPS e percentis das CVEs para avaliar a gravidade e o impacto potencial. 13 | - utiliza sleep para contornar os limites de pesquisa do github sem utilização de API. 14 | - Quebra a pesquisa de CVEs ao pesquisar scores no EPS, bypassando o limite de pesquisa de 100 por vez. 15 | 16 | ## Aviso Legal 17 | 18 | Este script é fornecido "como está" e é destinado apenas para fins educacionais e de pesquisa. O uso inadequado desta ferramenta para atividades maliciosas é estritamente proibido. Qualquer uso da ferramenta para atividades ilegais é de inteira responsabilidade do usuário. 19 | 20 | ## Requisitos 21 | 22 | - `curl`: Para realizar requisições HTTP. 23 | - `jq`: Para processar e manipular dados JSON. 24 | - `grep`: Para filtrar textos. 25 | - `awk`: Para formatar a saída. 26 | - `sort` e `uniq`: Para manipulação e organização de dados. 27 | 28 | ### ScreeShot #### 29 | 30 | 31 | 32 | ![image](https://github.com/user-attachments/assets/77f7f6ec-cc42-4100-a100-316f1be562d3) 33 | 34 | ![image](https://github.com/user-attachments/assets/a05ff485-c83a-4da3-8fec-f219885fe7b7) 35 | 36 | ![image](https://github.com/user-attachments/assets/41882b8b-038d-4f56-b54f-a5ed3e75585a) 37 | 38 | ![image](https://github.com/user-attachments/assets/5b7f5d2e-dfd5-47e5-94c9-bd642456fdbd) 39 | 40 | ![image](https://github.com/user-attachments/assets/50df860a-da24-4572-ba7a-d86402199d27) 41 | 42 | ![image](https://github.com/user-attachments/assets/b6cc75d1-b0bb-4f37-b440-8bd237808486) 43 | 44 | 45 | ![image](https://github.com/user-attachments/assets/b25c8149-9fd4-4006-9158-772701d7c509) 46 | 47 | 48 | ## Como Usar 49 | 50 | - chmod +x G1t-3xpl01t.sh 51 | 52 | - ./G1t-3xpl01t.sh -a confluence 53 | 54 | - ./G1t-3xpl01t.sh -b confluence 55 | 56 | - ./G1t-3xpl01t.sh -c confluence 57 | 58 | procurando por anos especificos separados por espaço 2021 2022 59 | 60 | - ./G1t-3xpl01t.sh -c confluence 2021 2022 61 | 62 | - ./G1t-3xpl01t.sh -d confluence 63 | 64 | procurando por anos especificos separados por espaço 2021 2022 65 | - ./G1t-3xpl01t.sh -d confluence 2021 2022 66 | 67 | Ps. Caso a pesquisa, utilize palavra composta. utilize o "%20" para espaço 68 | 69 | Ex: ./G1t-3xpl01t.sh -a Microsoft%20Outlook 70 | 71 | ### Passo 1: Preparação 72 | 73 | Certifique-se de ter as dependências necessárias instaladas: 74 | 75 | sudo apt-get install curl jq grep awk 76 | 77 | 78 | ### Desenvolvedor 79 | 80 | By Carlos Tuma - bl4dsc4n 81 | -------------------------------------------------------------------------------- /g1t-3xpl01t3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Definir cores 4 | green="\033[0;32m" 5 | yellow="\033[0;33m" 6 | blue="\033[0;34m" 7 | magenta="\033[0;35m" 8 | cyan="\033[0;36m" 9 | red="\033[0;31m" 10 | reset="\033[0m" 11 | 12 | 13 | 14 | banner(){ 15 | 16 | 17 | echo ' @@@@@@@@ @@@ @@@@@@@ @@@@@@@@ @@@ @@@ @@@@@@@ @@@ @@@@@@ @@@ @@@@@@@ ' 18 | echo '@@@@@@@@@ @@@@ @@@@@@@ @@@@@@@@ @@@ @@@ @@@@@@@@ @@@ @@@@@@@@ @@@@ @@@@@@@ ' 19 | echo '!@@ @@@!! @@! @@! @@! !@@ @@! @@@ @@! @@! @@@ @@@!! @@! ' 20 | echo '!@! !@! !@! !@! !@! @!! !@! @!@ !@! !@! @!@ !@! !@! ' 21 | echo '!@! @!@!@ @!@ @!! @!!!:! !@@!@! @!@@!@! @!! @!@ !@! @!@ @!! ' 22 | echo '!!! !!@!! !@! !!! !!!!!: @!!! !!@!!! !!! !@! !!! !@! !!! ' 23 | echo ':!! !!: !!: !!: !!: !: :!! !!: !!: !!: !!! !!: !!: ' 24 | echo ':!: !:: :!: :!: :!: :!: !:! :!: :!: :!: !:! :!: :!: ' 25 | echo ' ::: :::: ::: :: :: :::: :: ::: :: :: :::: ::::: :: ::: :: ' 26 | echo ' :: :: : :: : : :: :: : :: : : :: : : : : : :: : ' 27 | echo 28 | echo ' _ _ _ _ _ _ _ _ _ _ ' 29 | echo ' / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ ' 30 | echo '( b | y ) ( b | l | 4 | d | s | c | 4 | n )' 31 | echo ' \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ ' "version 2.0" 32 | 33 | } 34 | 35 | mododeuso(){ 36 | 37 | echo "Funções disponíveis:" 38 | echo -e "${yellow}-a ${reset} : Buscar e comparar CVEs" 39 | echo -e "${yellow}-b ${reset} : Buscar e processar escores EPS" 40 | echo -e "${yellow}-c ${reset} : Buscar e filtrar CVEs por anos" 41 | echo -e "${yellow}-d ${reset} : Buscar CVEs no GitHub" 42 | echo "" 43 | 44 | } 45 | 46 | 47 | 48 | 49 | retry_request() { 50 | local url="$1" 51 | local attempts=5 52 | local wait_time=10 53 | local attempt=0 54 | while [ $attempt -lt $attempts ]; do 55 | response=$(curl -s "$url") 56 | if echo "$response" | grep -q "API rate limit exceeded"; then 57 | echo "API rate limit exceeded. Waiting $wait_time seconds before retrying..." 58 | sleep $wait_time 59 | ((attempt++)) 60 | else 61 | echo "$response" 62 | return 63 | fi 64 | done 65 | echo "Failed to get a valid response after $attempts attempts." 66 | exit 1 67 | } 68 | 69 | 70 | 71 | fetch_and_compare_cves() { 72 | local keyword=$1 73 | local cve_url="https://services.nvd.nist.gov/rest/json/cves/2.0?keywordSearch=${keyword}" 74 | local cve_file="${keyword}_cves.txt" 75 | 76 | echo "Buscando CVEs relacionadas à palavra-chave: $keyword" 77 | local response=$(retry_request "$cve_url") 78 | local new_cves=$(echo "$response" | jq -r '.vulnerabilities[].cve.id' | grep -o 'CVE-[0-9]\{4\}-[0-9]\+' | sort -u) 79 | 80 | if [[ -f "$cve_file" ]]; then 81 | echo "Arquivo $cve_file encontrado. Comparando CVEs..." 82 | local existing_cves=$(cat "$cve_file") 83 | local new_entries=$(comm -13 <(echo "$existing_cves") <(echo "$new_cves")) 84 | 85 | if [[ -n "$new_entries" ]]; then 86 | echo -e "\033[1;32mNOVAS CVEs encontradas:\033[0m" 87 | echo "$new_entries" 88 | echo "$new_cves" > "$cve_file" 89 | echo "CVEs atualizadas salvas em $cve_file" 90 | else 91 | echo "Nenhuma nova CVE encontrada. O arquivo está atualizado." 92 | fi 93 | else 94 | echo "Arquivo $cve_file não encontrado. Criando e salvando novas CVEs..." 95 | echo "$new_cves" > "$cve_file" 96 | echo "CVEs localizadas salvas em $cve_file" 97 | fi 98 | 99 | 100 | echo -e "\nConteúdo do arquivo $cve_file:" 101 | } 102 | 103 | 104 | fetch_and_process_eps() { 105 | local keyword=$1 106 | local cve_file="${keyword}_cves.txt" 107 | local eps_filtro=$2 108 | 109 | 110 | if [[ ! -f "$cve_file" || ! -s "$cve_file" ]]; then 111 | echo -e "\033[0;33mArquivo $cve_file não encontrado ou vazio\033[0m" 112 | fetch_and_compare_cves "$keyword" 113 | fi 114 | 115 | local cve_ids=$(cat "$cve_file" | tr '\n' ' ') 116 | local cve_ids_array=($cve_ids) 117 | local total_cves=${#cve_ids_array[@]} 118 | local chunk_size=100 119 | 120 | 121 | local eps_file="${keyword}_eps.txt" 122 | local sorted_eps_file="${keyword}_sorted_eps.txt" 123 | local colored_eps_file="${keyword}_colored_eps.txt" 124 | 125 | 126 | 127 | > "$eps_file" 128 | > "$sorted_eps_file" 129 | > "$colored_eps_file" 130 | 131 | 132 | for (( i=0; i<$total_cves; i+=chunk_size )); do 133 | chunk="${cve_ids_array[@]:i:chunk_size}" 134 | echo "Buscando scores EPS das CVEs..." 135 | local eps_url="https://api.first.org/data/v1/epss?cve=$(echo "$chunk" | tr ' ' ',')" 136 | local response=$(retry_request "$eps_url") 137 | 138 | 139 | echo "$response" | jq -r ' 140 | .data[] | 141 | [.cve, (.epss | tonumber | (. * 100 | tostring | .[0:5])), (.percentile | tonumber | (. * 100 | tostring | .[0:5])), .date] | 142 | @tsv' >> "$eps_file" 143 | 144 | 145 | sleep 3 146 | done 147 | 148 | 149 | sort -k2,2nr "$eps_file" | awk '{print $1 "\t" $2}' >> "$sorted_eps_file" 150 | 151 | 152 | awk ' 153 | BEGIN { 154 | # Definir cores 155 | green="\033[0;32m" 156 | yellow="\033[0;33m" 157 | blue="\033[0;34m" 158 | magenta="\033[0;35m" 159 | cyan="\033[0;36m" 160 | red="\033[0;31m" 161 | reset="\033[0m" 162 | } 163 | { 164 | eps=$2 165 | # Definir cor com base no valor do EPS 166 | if (eps > 90) color=red # Verde 167 | else if (eps >= 80) color=yellow # Amarelo 168 | else if (eps >= 70) color=blue # Azul 169 | else if (eps >= 50) color=magenta # Magenta 170 | else if (eps >= 30) color=cyan # Ciano 171 | else color=green # Vermelho 172 | 173 | # Aplicar cor ao EPS e CVE 174 | printf "%s%-20s %s%-10s%s\n", color, $1, color, $2, reset 175 | }' "$sorted_eps_file" > "$colored_eps_file" 176 | 177 | } 178 | 179 | 180 | 181 | funcao_c() { 182 | local keyword=$1 183 | shift 184 | local years=("$@") 185 | 186 | 187 | curl -s "https://services.nvd.nist.gov/rest/json/cves/2.0?keywordSearch=${keyword}" | jq -r ' 188 | .vulnerabilities[] | 189 | { 190 | id: .cve.id, 191 | description: .cve.descriptions[0].value, 192 | cvss_v3_base_score: ( 193 | if .cve.metrics.cvssMetricV31 then 194 | .cve.metrics.cvssMetricV31[0].cvssData.baseScore // "N/A" 195 | elif .cve.metrics.cvssMetricV30 then 196 | .cve.metrics.cvssMetricV30[0].cvssData.baseScore // "N/A" 197 | else 198 | "N/A" 199 | end 200 | ), 201 | cvss_v3_severity: ( 202 | if .cve.metrics.cvssMetricV31 then 203 | .cve.metrics.cvssMetricV31[0].cvssData.baseSeverity // "N/A" 204 | elif .cve.metrics.cvssMetricV30 then 205 | .cve.metrics.cvssMetricV30[0].cvssData.baseSeverity // "N/A" 206 | else 207 | "N/A" 208 | end 209 | ), 210 | cvss_v2_base_score: ( 211 | if .cve.metrics.cvssMetricV2 then 212 | .cve.metrics.cvssMetricV2[0].cvssData.baseScore // "N/A" 213 | else 214 | "N/A" 215 | end 216 | ), 217 | cvss_v2_severity: ( 218 | if .cve.metrics.cvssMetricV2 then 219 | .cve.metrics.cvssMetricV2[0].baseSeverity // "N/A" 220 | else 221 | "N/A" 222 | end 223 | ), 224 | cwe: ( 225 | if .cve.weaknesses then 226 | .cve.weaknesses[0].description[0].value // "NVD-CWE-Other" 227 | else 228 | "NVD-CWE-Other" 229 | end 230 | ), 231 | year: (.cve.id | match("[0-9]{4}") | .string) 232 | } | 233 | { 234 | id: .id, 235 | description: .description, 236 | cvss_v3_base_score: .cvss_v3_base_score, 237 | cvss_v3_severity: .cvss_v3_severity, 238 | cvss_v2_base_score: .cvss_v2_base_score, 239 | cvss_v2_severity: .cvss_v2_severity, 240 | cwe: .cwe, 241 | year: .year 242 | } 243 | ' | jq -s '.' > results.json 244 | } 245 | 246 | filter_and_color() { 247 | local years=("$@") 248 | 249 | if [ ${#years[@]} -eq 0 ]; then 250 | 251 | cat results.json | jq -r ' 252 | .[] | { 253 | id: .id, 254 | description: .description, 255 | cvss_v3_base_score: .cvss_v3_base_score, 256 | cvss_v3_severity: .cvss_v3_severity, 257 | cvss_v2_base_score: .cvss_v2_base_score, 258 | cvss_v2_severity: .cvss_v2_severity, 259 | cwe: .cwe 260 | } | 261 | "\(.id)\nDescription: \(.description)\nCVSS v3 Base Score: \(.cvss_v3_base_score)\nCVSS v3 Severity: \(.cvss_v3_severity)\nCVSS v2 Base Score: \(.cvss_v2_base_score)\nCVSS v2 Severity: \(.cvss_v2_severity)\nCWE: \(.cwe)\n" 262 | ' | awk ' 263 | BEGIN { RS="\n\n"; ORS="\n\n" } 264 | /^[^CVE]/ { next } 265 | { 266 | # Colorir as partes específicas 267 | gsub(/^(CVE-[0-9\-]+.*)$/, "\033[1;32m&\033[0m") # Verde para toda a linha com CVE 268 | gsub(/Description: /, "\033[1;34mDescription: \033[0m") # Azul para Description 269 | gsub(/CVSS v3 Base Score: /, "\033[1;35mCVSS v3 Base Score: \033[0m") # Magenta para CVSS v3 Base Score 270 | gsub(/CVSS v3 Severity: /, "\033[1;36mCVSS v3 Severity: \033[0m") # Ciano para CVSS v3 Severity 271 | gsub(/CVSS v2 Base Score: /, "\033[1;35mCVSS v2 Base Score: \033[0m") # Magenta para CVSS v2 Base Score 272 | gsub(/CVSS v2 Severity: /, "\033[1;36mCVSS v2 Severity: \033[0m") # Ciano para CVSS v2 Severity 273 | gsub(/CWE:/, "\033[1;33mCWE:\033[0m") # Amarelo para CWE: 274 | gsub(/NVD-CWE-Other/, "\033[1;33mNVD-CWE-Other\033[0m") # Amarelo para NVD-CWE-Other 275 | print 276 | } 277 | ' 278 | else 279 | 280 | cat results.json | jq -r --argjson years "$(echo "${years[@]}" | jq -R '[split(" ")[] | select(length > 0)]')" ' 281 | .[] | select(.year as $y | $years | index($y)) | 282 | { 283 | id: .id, 284 | description: .description, 285 | cvss_v3_base_score: .cvss_v3_base_score, 286 | cvss_v3_severity: .cvss_v3_severity, 287 | cvss_v2_base_score: .cvss_v2_base_score, 288 | cvss_v2_severity: .cvss_v2_severity, 289 | cwe: .cwe 290 | } | 291 | "\(.id)\nDescription: \(.description)\nCVSS v3 Base Score: \(.cvss_v3_base_score)\nCVSS v3 Severity: \(.cvss_v3_severity)\nCVSS v2 Base Score: \(.cvss_v2_base_score)\nCVSS v2 Severity: \(.cvss_v2_severity)\nCWE: \(.cwe)\n" 292 | ' | awk ' 293 | BEGIN { RS="\n\n"; ORS="\n\n" } 294 | /^[^CVE]/ { next } 295 | { 296 | # Colorir as partes específicas 297 | gsub(/^(CVE-[0-9\-]+.*)$/, "\033[1;32m&\033[0m") # Verde para toda a linha com CVE 298 | gsub(/Description: /, "\033[1;34mDescription: \033[0m") # Azul para Description 299 | gsub(/CVSS v3 Base Score: /, "\033[1;35mCVSS v3 Base Score: \033[0m") # Magenta para CVSS v3 Base Score 300 | gsub(/CVSS v3 Severity: /, "\033[1;36mCVSS v3 Severity: \033[0m") # Ciano para CVSS v3 Severity 301 | gsub(/CVSS v2 Base Score: /, "\033[1;35mCVSS v2 Base Score: \033[0m") # Magenta para CVSS v2 Base Score 302 | gsub(/CVSS v2 Severity: /, "\033[1;36mCVSS v2 Severity: \033[0m") # Ciano para CVSS v2 Severity 303 | gsub(/CWE:/, "\033[1;33mCWE:\033[0m") # Amarelo para CWE: 304 | gsub(/NVD-CWE-Other/, "\033[1;33mNVD-CWE-Other\033[0m") # Amarelo para NVD-CWE-Other 305 | print 306 | } 307 | ' 308 | fi 309 | } 310 | 311 | funcao_d() { 312 | local keyword=$1 313 | local github_results_file="${keyword}_github_results.txt" 314 | shift 315 | local years=($@) 316 | local cve_file="${keyword}_cves.txt" 317 | 318 | 319 | if [[ ! -f "$cve_file" || ! -s "$cve_file" ]]; then 320 | echo -e "\033[0;33mArquivo $cve_file não encontrado ou vazio\033[0m" 321 | fetch_and_compare_cves "$keyword" 322 | fi 323 | 324 | > "$github_results_file" 325 | 326 | 327 | if [ ${#years[@]} -eq 0 ]; then 328 | 329 | echo "Nenhum ano fornecido. Buscando todas as CVEs..." 330 | 331 | 332 | local cve_file="${keyword}_cves.txt" 333 | local cve_ids=$(cat "$cve_file") 334 | 335 | process_cves "$cve_ids" "$github_results_file" 336 | else 337 | 338 | echo "Anos fornecidos: ${years[@]}. Buscando CVEs desses anos..." 339 | 340 | local cve_file="${keyword}_cves.txt" 341 | > resultado2.txt 342 | for i in ${years[@]}; do cat $cve_file | grep -E $i; done >> resultado2.txt 343 | echo $keyword >> resultado2.txt 344 | local cve_ids=$(cat resultado2.txt) 345 | 346 | process_cves "$cve_ids" "$github_results_file" 347 | fi 348 | 349 | echo -e "\nResultados da pesquisa no GitHub salvos em $github_results_file" 350 | echo -e "\nConteúdo do arquivo $github_results_file:" 351 | cat "$github_results_file" | sort -u 352 | } 353 | 354 | process_cves() { 355 | local cve_ids=$1 356 | local github_results_file=$2 357 | local filter_terms=("exploit" "poc" "pentest" "hack") 358 | 359 | 360 | for term in "${filter_terms[@]}"; do 361 | while IFS= read -r cve; do 362 | query="${term}+${cve}" 363 | echo "Pesquisando por: $query" 364 | local query_url="https://api.github.com/search/repositories?q=${query// /%20}" 365 | local response=$(retry_request "$query_url") 366 | 367 | echo "$response" | jq -r '.items[] | "\(.full_name) - \(.html_url)"' >> "$github_results_file" 368 | echo "Pesquisa $query - Finalizada OK" 369 | 370 | sleep 10 371 | done <<< "$cve_ids" 372 | done 373 | 374 | while IFS= read -r cve; do 375 | query="${cve}" 376 | echo "Pesquisando por: $query" 377 | local query_url="https://api.github.com/search/repositories?q=${query// /%20}" 378 | local response=$(retry_request "$query_url") 379 | 380 | echo "$response" | jq -r '.items[] | "\(.full_name) - \(.html_url)"' >> "$github_results_file" 381 | echo "Pesquisa $query - Finalizada OK" 382 | 383 | sleep 10 384 | done <<< "$cve_ids" 385 | } 386 | 387 | 388 | 389 | if [ $# -eq 0 ]; then 390 | banner 391 | mododeuso 392 | exit 1 393 | 394 | elif [[ "$1" != "-a" && "$1" != "-b" && "$1" != "-c" && "$1" != "-d" && "$1" != "-h" ]]; then 395 | banner 396 | mododeuso 397 | exit 1 398 | elif [ -z "$2" ]; then 399 | banner 400 | mododeuso 401 | exit 1 402 | fi 403 | 404 | 405 | 406 | 407 | 408 | while getopts ":a:b:c:d:h:" opt; do 409 | case ${opt} in 410 | a ) 411 | keyword=$2 412 | fetch_and_compare_cves "$keyword" 413 | a=$(cat "${keyword}_cves.txt" | wc -l) 414 | echo -e "\nForam localizadas: $a CVE" 415 | cat "${keyword}_cves.txt" | column 416 | 417 | ;; 418 | b ) 419 | keyword=$2 420 | fetch_and_process_eps "$keyword" 421 | if [[ "$3" =~ ^[0-9]+$ ]]; then 422 | 423 | head -n "$3" "${keyword}_colored_eps.txt" | column 424 | else 425 | 426 | echo -e "\033[0;32mCVE\t\t EPS Score \033[0m" 427 | cat "${keyword}_colored_eps.txt" | column 428 | fi 429 | 430 | ;; 431 | c ) 432 | shift 433 | keyword=$1 434 | shift 435 | years=("$@") 436 | 437 | if [ ${#years[@]} -eq 0 ]; then 438 | echo "Nenhum ano fornecido. Exibindo todas as CVEs." 439 | funcao_c "$keyword" 440 | filter_and_color 441 | else 442 | echo "Anos fornecidos: ${years[@]}" 443 | funcao_c "$keyword" "${years[@]}" 444 | filter_and_color "${years[@]}" 445 | fi 446 | 447 | ;; 448 | d ) 449 | shift 450 | keyword=$1 451 | shift 452 | years=("$@") 453 | 454 | if [ ${#years[@]} -eq 0 ]; then 455 | funcao_d "$keyword" 456 | else 457 | 458 | funcao_d "$keyword" "${years[@]}" 459 | fi 460 | ;; 461 | h ) 462 | banner 463 | mododeuso 464 | ;; 465 | * ) 466 | banner 467 | mododeuso 468 | 469 | exit 1 470 | ;; 471 | esac 472 | done 473 | --------------------------------------------------------------------------------