Skip to content

Instantly share code, notes, and snippets.

@betillogalvanfbc
Created January 30, 2025 00:40
Show Gist options
  • Save betillogalvanfbc/ed69c0f03098ebde8d76d4a3a29fe59b to your computer and use it in GitHub Desktop.
Save betillogalvanfbc/ed69c0f03098ebde8d76d4a3a29fe59b to your computer and use it in GitHub Desktop.
onelinerendpointsfull.js
javascript:(async function() {
// Crear una ventana emergente para mostrar el progreso
const scanningDiv = document.createElement("div");
scanningDiv.style.position = "fixed";
scanningDiv.style.bottom = "0";
scanningDiv.style.left = "0";
scanningDiv.style.width = "100%";
scanningDiv.style.maxHeight = "50%";
scanningDiv.style.overflowY = "scroll";
scanningDiv.style.backgroundColor = "white";
scanningDiv.style.color = "black";
scanningDiv.style.padding = "10px";
scanningDiv.style.zIndex = "9999";
scanningDiv.style.borderTop = "2px solid black";
scanningDiv.innerHTML = "<h4>Scanning resources...</h4>";
document.body.appendChild(scanningDiv);
// Variables para almacenar resultados
let paths = [];
const processedUrls = new Set();
// Función para obtener el contenido de una URL
async function fetchContent(url) {
try {
const response = await fetch(url);
return response.ok ? await response.text() : null;
} catch (error) {
console.error(`Error fetching ${url}:`, error);
return null;
}
}
// Función para extraer rutas de un texto
function extractPaths(text) {
return [...text.matchAll(/['"`]((?:\/|\.\.\/|\.\/)[^'"`]+)['"`]/g)]
.map(match => match[1])
.filter(isValidPath);
}
// Función para validar rutas
function isValidPath(path) {
const ignoredExtensions = [".png", ".jpg", ".jpeg", ".gif", ".css", ".woff", ".woff2"];
return (path.startsWith("/") || path.startsWith("./") || path.startsWith("../")) &&
!path.includes(" ") &&
!/[^\x20-\x7E]/.test(path) &&
path.length > 1 &&
path.length < 200 &&
!ignoredExtensions.some(ext => path.endsWith(ext));
}
// Función recursiva para procesar una URL
async function processUrl(url) {
if (processedUrls.has(url)) return;
processedUrls.add(url);
console.log(`Fetching and processing: ${url}`);
const content = await fetchContent(url);
if (content) {
const foundPaths = extractPaths(content);
paths.push(...foundPaths);
// Si es un archivo JavaScript, buscar endpoints y procesarlos recursivamente
if (url.endsWith(".js")) {
const endpoints = extractEndpoints(content);
for (const endpoint of endpoints) {
const fullUrl = new URL(endpoint.url, url).href;
await processUrl(fullUrl); // Llamada recursiva
}
}
}
}
// Función para extraer endpoints y métodos HTTP de un archivo JavaScript
function extractEndpoints(content) {
// Expresión regular para buscar URLs y métodos HTTP en fetch, axios, XMLHttpRequest, etc.
const regex = /(?:fetch|axios\.(?:get|post|put|delete)|XMLHttpRequest\.open)\s*\(\s*['"`]([^'"`]+)['"`]\s*(?:,\s*{.*?method\s*:\s*['"`]([^'"`]+)['"`]|,\s*['"`]([^'"`]+)['"`])?/g;
const endpoints = [];
let match;
while ((match = regex.exec(content)) !== null) {
const url = match[1];
const method = match[2] || match[3] || "GET"; // Si no se especifica, asumir GET
endpoints.push({ url, method });
}
return [...new Set(endpoints.map(e => JSON.stringify(e)))].map(e => JSON.parse(e)); // Devolver endpoints únicos
}
// Obtener todos los recursos de la página
const resources = performance.getEntriesByType("resource").map(res => res.name);
console.log("Resources found:", resources);
// Procesar recursos en paralelo
await Promise.all(resources.map(processUrl));
// Filtrar rutas únicas
const uniquePaths = [...new Set(paths)];
console.log("Final list of unique paths:", uniquePaths);
console.log("All scanned resources:", Array.from(processedUrls));
// Mostrar resultados en la ventana emergente
scanningDiv.innerHTML = `
<h4>Unique Paths Found:</h4>
<ul>${uniquePaths.map(path => `<li>${path}</li>`).join("")}</ul>
<h4>All Scanned Resources:</h4>
<ul>${Array.from(processedUrls).map(resource => `<li>${resource}</li>`).join("")}</ul>
<button id="downloadButton">Download as TXT</button>
`;
// Función para descargar el archivo TXT
function downloadTxtFile(content, filename) {
const blob = new Blob([content], { type: "text/plain" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = filename;
a.click();
URL.revokeObjectURL(url);
}
// Añadir evento al botón de descarga
document.getElementById("downloadButton").addEventListener("click", () => {
const content = `
=== Unique Paths Found ===
${uniquePaths.join("\n")}
=== All Scanned Resources ===
${Array.from(processedUrls).join("\n")}
=== Endpoints with HTTP Methods ===
${extractEndpointsFromProcessedUrls().join("\n")}
`;
downloadTxtFile(content, "scan_results.txt");
alert("File downloaded successfully!");
});
// Función para extraer endpoints con métodos HTTP de los recursos procesados
function extractEndpointsFromProcessedUrls() {
const endpoints = [];
for (const url of processedUrls) {
if (url.endsWith(".js")) {
const content = fetchContentSync(url);
if (content) {
const foundEndpoints = extractEndpoints(content);
endpoints.push(...foundEndpoints.map(e => `${e.method} ${e.url}`));
}
}
}
return [...new Set(endpoints)]; // Devolver endpoints únicos
}
// Función síncrona para obtener el contenido de una URL (solo para uso interno)
function fetchContentSync(url) {
const xhr = new XMLHttpRequest();
xhr.open("GET", url, false); // Síncrono
xhr.send();
return xhr.status === 200 ? xhr.responseText : null;
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment