N
n8n Store
Workflow Market
Subdomain Enumeration with Subfinder, HTTPX & GPT-4-Mini for Security Reconnaissance

Subdomain Enumeration with Subfinder, HTTPX & GPT-4-Mini for Security Reconnaissance

by pyus3r0 views

Description

Categories

🤖 AI & Machine Learning

Nodes Used

n8n-nodes-base.setn8n-nodes-base.setn8n-nodes-base.setn8n-nodes-base.sshn8n-nodes-base.sshn8n-nodes-base.sshn8n-nodes-base.sshn8n-nodes-base.sshn8n-nodes-base.sshn8n-nodes-base.code
PriceFree
Views0
Last Updated11/28/2025
workflow.json
{
  "meta": {
    "instanceId": "68ae635f382a7fb7d5b4702b14c90c7fb0be459b7fa5f4b9851d8f84f561c82b",
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "4996550b-24ba-453f-aa6e-72df81080db8",
      "name": "SSH Subfinder",
      "type": "n8n-nodes-base.ssh",
      "onError": "continueRegularOutput",
      "position": [
        -160,
        -208
      ],
      "parameters": {
        "command": "=subfinder -d  {{ $json.domain }} -silent -all"
      },
      "credentials": {
        "sshPassword": {
          "id": "NMiZzSVngDiy18DK",
          "name": "SSH Password account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "81397a0c-4a35-48b3-ba7b-c7e0abdcdf16",
      "name": "SSH Assetfinder",
      "type": "n8n-nodes-base.ssh",
      "onError": "continueRegularOutput",
      "position": [
        -160,
        -64
      ],
      "parameters": {
        "command": "=assetfinder -subs-only {{ $('Loop Over Domains').item.json.domain }}"
      },
      "credentials": {
        "sshPassword": {
          "id": "NMiZzSVngDiy18DK",
          "name": "SSH Password account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "5904eb02-d052-4cb0-a5dc-510577291c91",
      "name": "WayBack Machine",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        -160,
        80
      ],
      "parameters": {
        "url": "=https://web.archive.org/cdx/search/cdx?url=*.{{ $('Loop Over Domains').item.json.domain }}/*&fl=original&collapse=urlkey",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "58558723-de7f-4959-bcde-663537b348d0",
      "name": "Filter Subdomains WayBack Machine",
      "type": "n8n-nodes-base.code",
      "onError": "continueRegularOutput",
      "position": [
        0,
        80
      ],
      "parameters": {
        "jsCode": "const text = items[0].json.data;\n\nconst lines = text.split(\"\\n\");\n\nconst subs = lines.map(line => {\n    try {\n        const url = line.replace(/^https?:\\/\\//, '');\n        return url.split(\"/\")[0];\n    } catch {\n        return null;\n    }\n}).filter(Boolean);\n\nconst subdomains = [...new Set(subs)];\n\nreturn [{\n  json: {\n    subdomains\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "b93bdf3a-b653-419f-b7c6-9d119dd152c2",
      "name": "Filter Subdomains Assetfinder",
      "type": "n8n-nodes-base.code",
      "onError": "continueRegularOutput",
      "position": [
        0,
        -64
      ],
      "parameters": {
        "jsCode": "const data = items[0].json;\nconst stdout = data.stdout || \"\";\n\nconst subdomains = stdout\n  .split('\\n')\n  .filter(s => s.trim() !== '')\n  .map(s => s.trim());\n\nreturn [{\n  json: {\n    subdomains\n  }\n}];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "00ee30d2-5d1a-44e8-a441-1700c8ce2037",
      "name": "Filter Subdomains Subfinder",
      "type": "n8n-nodes-base.code",
      "onError": "continueRegularOutput",
      "position": [
        0,
        -208
      ],
      "parameters": {
        "jsCode": "const data = items[0].json;\nconst stdout = data.stdout || \"\";\n\nconst subdomains = stdout\n  .split('\\n')\n  .filter(s => s.trim() !== '')\n  .map(s => s.trim());\n\nreturn [{\n  json: {\n    subdomains\n  }\n}];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "f3bbca4d-3866-437c-be4b-7d0ddec1ba49",
      "name": "TXT to JSON",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        112,
        -608
      ],
      "parameters": {
        "options": {},
        "operation": "text",
        "destinationKey": "file",
        "binaryPropertyName": "=File0"
      },
      "typeVersion": 1
    },
    {
      "id": "eb1fcd3d-dfb9-4863-b599-57aec3e8ab96",
      "name": "SSH HTTPX",
      "type": "n8n-nodes-base.ssh",
      "position": [
        1584,
        -352
      ],
      "parameters": {
        "command": "=httpx -silent -tech-detect -l /tmp/reconAI/subdomains.txt -no-color -threads 50 -timeout 4 -retries 1"
      },
      "credentials": {
        "sshPassword": {
          "id": "NMiZzSVngDiy18DK",
          "name": "SSH Password account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "a8b13916-3e9b-4a2f-82d5-b178e80b7e9d",
      "name": "Subdomain Generator AI",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "onError": "continueRegularOutput",
      "position": [
        1216,
        304
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini",
          "cachedResultName": "GPT-4.1-MINI"
        },
        "options": {
          "n": 1
        },
        "messages": {
          "values": [
            {
              "content": "=URLs -> {{ $json.appended_content }}"
            },
            {
              "role": "system",
              "content": "=# Rol\nEres un experto en Ciberseguridad, especializado en la enumeración de subdominios ocultos o difíciles de detectar mediante diccionarios. Tienes más de 20 años de experiencia identificando patrones y tecnologías en subdominios, y eres capaz de sugerir subdominios plausibles que no suelen aparecer en fuentes pasivas ni en herramientas automáticas.\n# Contexto\nEsta herramienta debe encontrar subdominios que otras técnicas no detectan, generando la lista más exhaustiva posible. Úsala solo en entornos controlados y con autorización.\n# Tareas\nAnaliza la lista de subdominios y URLs proporcionada para identificar patrones, tecnologías, y heurísticas.\nGenera subdominios plausibles y realistas, incluyendo variantes comunes, subdominios de servicios, entornos de desarrollo, pruebas, históricos, y combinaciones creativas.\nAsegúrate de que todos los subdominios generados sean únicos y no estén en la lista de entrada.\n# Proceso\nAnaliza patrones y tecnologías en la entrada.\nSugiere subdominios asociados a esos patrones y tecnologías.\nIncluye variantes como: admin, dev, test, staging, api, mail, old, beta, preprod, internal, legacy, backup, vpn, portal, dashboard, mobile, app, static, cdn, files, assets, docs, blog, shop, payments, etc.\nGenera subdominios históricos, de servicios comunes y de entornos de desarrollo.\nNo repitas subdominios y asegúrate de que todos sean plausibles para el dominio objetivo.\n# Reglas\nGenera exactamente 5,000 subdominios únicos y plausibles, todos distintos de los de entrada.\nNo uses negritas ni símbolos especiales.\nLa respuesta debe ser un objeto JSON con una sola clave llamada \"subdomains\", cuyo valor es una lista de exactamente 5,000 subdominios (cadenas de texto).\nSi la entrada no es válida, responde estrictamente con: {\"subdomains\": []}\nNo incluyas mensajes adicionales ni explicaciones fuera del JSON de respuesta.\n# Output Format\n{\n\"subdomains\": [\n\"admin.example.com\",\n\"dev.example.com\",\n...\n// hasta 5,000 subdominios únicos\n]\n}"
            }
          ]
        },
        "jsonOutput": true
      },
      "credentials": {
        "openAiApi": {
          "id": "OHRPLyUXrUoOHSJL",
          "name": "OpenAi account 2"
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "9c8737ef-bf9b-42f2-873d-18cd7da88085",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -912,
        -720
      ],
      "parameters": {
        "color": 6,
        "width": 528,
        "height": 1232,
        "content": "# HOW USE\n\n### 1. Create Scope File\n#### Format Required (**txt File**): \n```\nscope.example.com\nscope2.example.com\nscope3.scope.example.com\n```\n\n---\n### 2. Send Request \n#### Curl:\n```\ncurl -X POST -F \"file=@[PATH TO FILE]\" [WEBHOOK URL]\n```\n\n#### Python Request:\n\n```\nimport requests\n\nurl = \"http://localhost:5678/webhook-test/7b8f0377-a5e8-455c-9909-9bfc1d7acc08\"\nfile_path = r\"C:\\Users\\pyuser\\Desktop\\domains.txt\"\n\nwith open(file_path, \"rb\") as f:\n    files = {\"file\": f}\n    response = requests.post(url, files=files)\n\nprint(response.status_code)\nprint(response.text)\n```\n"
      },
      "typeVersion": 1
    },
    {
      "id": "875248ed-2028-4776-b63b-64311b64d55b",
      "name": "Summarize",
      "type": "n8n-nodes-base.summarize",
      "onError": "continueRegularOutput",
      "position": [
        0,
        224
      ],
      "parameters": {
        "options": {},
        "fieldsToSummarize": {
          "values": [
            {
              "field": "name_value",
              "aggregation": "append"
            }
          ]
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "2a080f31-13df-495f-8e1d-54a0991e3685",
      "name": "Subdomain Format Validation",
      "type": "n8n-nodes-base.code",
      "position": [
        960,
        -352
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\n\n// Regex para validar subdominios (sin asterisco al inicio)\nconst validRegex = /^(?!\\*)(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,}$/;\n\n// Extrae y filtra los subdominios desde el input dinámico\nconst allSubdomains = items\n  .flatMap(item => {\n    const data = item.json.subdomains || item.json.subdomain || item.json.domain || \"\";\n    return data\n      .toString()\n      .split(/\\s*,\\s*|\\s+/)\n      .map(str => str.trim().replace(/:\\d+$/, \"\"));\n  })\n  .filter(str => validRegex.test(str));\n\n// Genera la salida como texto con saltos de línea\nconst txtOutput = allSubdomains.join(\"\\n\");\n\nreturn [{ json: { subdomain: txtOutput } }];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "220a9679-c3f5-42a8-bb35-f581ba67cd5d",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -304,
        -608
      ],
      "webhookId": "e0a62a2b-6669-4f09-bd16-e548ae1386cb",
      "parameters": {
        "path": "e0a62a2b-6669-4f09-bd16-e548ae1386cb",
        "options": {
          "binaryPropertyName": "File"
        },
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2.1
    },
    {
      "id": "15d10935-aa41-4998-aaa3-f2fd330b69ea",
      "name": "Respond to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        2656,
        -208
      ],
      "parameters": {
        "options": {},
        "respondWith": "allIncomingItems"
      },
      "typeVersion": 1.4
    },
    {
      "id": "bb770fcd-2b90-49b6-adf5-7587ad19caa1",
      "name": "Convert Subdomains to TXT",
      "type": "n8n-nodes-base.convertToFile",
      "position": [
        1152,
        -352
      ],
      "parameters": {
        "options": {
          "fileName": "subdomains.txt"
        },
        "operation": "toText",
        "sourceProperty": "subdomain"
      },
      "typeVersion": 1.1
    },
    {
      "id": "1ac7c809-2fc4-49f6-870f-b044ddf1e95c",
      "name": "SSH create subdomains.txt into /tmp/reconAI",
      "type": "n8n-nodes-base.ssh",
      "position": [
        1376,
        -352
      ],
      "parameters": {
        "path": "/tmp/reconAI",
        "options": {},
        "resource": "file"
      },
      "credentials": {
        "sshPassword": {
          "id": "NMiZzSVngDiy18DK",
          "name": "SSH Password account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "f7adf9fd-1560-4e70-b37f-728b8c4864cc",
      "name": "Prettify File Content",
      "type": "n8n-nodes-base.code",
      "position": [
        560,
        -608
      ],
      "parameters": {
        "jsCode": "const results = [];\n\nfor (const item of items) {\n  const lines = item.json.file\n    .split(/\\r?\\n/)\n    .map(line => line.trim())\n    .filter(line => line.length > 0);\n  \n  for (const domain of lines) {\n    results.push({ json: { domain } });\n  }\n}\n\nreturn results;"
      },
      "typeVersion": 2
    },
    {
      "id": "5f0b95d3-e083-4b59-bf15-71f90f0ca482",
      "name": "crt.sh",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        -160,
        224
      ],
      "parameters": {
        "url": "=https://crt.sh/?q=%25.{{ $('Loop Over Domains').item.json.domain }}&output=json",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "f5c5af94-c424-45d2-9320-ba7b6c9e3780",
      "name": "Split AI Response",
      "type": "n8n-nodes-base.splitOut",
      "onError": "continueRegularOutput",
      "position": [
        960,
        -112
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "message.content.subdomains"
      },
      "typeVersion": 1
    },
    {
      "id": "179b1486-2308-40f6-995b-44a47c80c231",
      "name": "AI Subdomain Format Validation",
      "type": "n8n-nodes-base.code",
      "onError": "continueRegularOutput",
      "position": [
        1152,
        -112
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\n\n// Regex para validar subdominios (sin asterisco al inicio)\nconst validRegex = /^(?!\\*)(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,}$/;\n\n// Extrae y filtra los subdominios desde el input dinámico\nconst allSubdomains = items\n  .map(item => item.json[\"message.content.subdomains\"] || \"\")\n  .flatMap(data =>\n    data\n      .toString()\n      .split(/\\s*,\\s*|\\s+/)\n      .map(str => str.trim().replace(/:\\d+$/, \"\"))\n  )\n  .filter(str => validRegex.test(str));\n\n// Elimina duplicados\nconst uniqueSubdomains = [...new Set(allSubdomains)];\n\n// Genera la salida como texto con saltos de línea\nconst txtOutput = uniqueSubdomains.join(\"\\n\");\n\nreturn [{ json: { subdomain: txtOutput } }];\n\n"
      },
      "typeVersion": 2
    },
    {
      "id": "2519c503-85a9-4c64-9671-a9a4096edc58",
      "name": "Rename crt.sh Content",
      "type": "n8n-nodes-base.set",
      "onError": "continueRegularOutput",
      "position": [
        176,
        224
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "41008265-8f41-4629-9db6-e68540346166",
              "name": "subdomains",
              "type": "array",
              "value": "={{ $json.appended_name_value }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "20e795d7-78f6-43a4-a31b-9b9b304cd099",
      "name": "Merge all Results",
      "type": "n8n-nodes-base.merge",
      "onError": "continueRegularOutput",
      "position": [
        448,
        -64
      ],
      "parameters": {
        "numberInputs": 4
      },
      "typeVersion": 3.2
    },
    {
      "id": "cf6269d5-95d7-4b01-a3da-f4d72a5bbec1",
      "name": "Unique Subdomains",
      "type": "n8n-nodes-base.code",
      "position": [
        560,
        304
      ],
      "parameters": {
        "jsCode": "let allSubdomains = [];\n\nfor (const item of items) {\n  const values = Object.values(item.json).flat();\n\n  for (let value of values) {\n    if (typeof value === 'string') {\n      const parts = value\n        .split(/[\\n,]+/)\n        .map(v => v.trim())\n        .filter(v => v);\n      allSubdomains.push(...parts);\n    }\n  }\n}\n\nconst unique = [...new Set(allSubdomains)];\n\nreturn [\n  {\n    json: {\n      subdomains: unique\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "7d843980-23fa-4634-b19a-7746f4637e98",
      "name": "Append all Loop Items",
      "type": "n8n-nodes-base.code",
      "position": [
        752,
        -352
      ],
      "parameters": {
        "jsCode": "let allSubdomains = [];\n\nfor (const item of items) {\n  const values = Object.values(item.json).flat();\n\n  for (let value of values) {\n    if (typeof value === 'string') {\n      const parts = value\n        .split(/[\\n,]+/)\n        .map(v => v.trim())\n        .filter(v => v);\n      allSubdomains.push(...parts);\n    }\n  }\n}\n\nconst unique = [...new Set(allSubdomains)];\n\nreturn [\n  {\n    json: {\n      subdomains: unique\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "d607e8a5-601f-4c63-8b28-ee3e6e7374a0",
      "name": "AI Convert Subdomains to TXT",
      "type": "n8n-nodes-base.convertToFile",
      "position": [
        1376,
        -112
      ],
      "parameters": {
        "options": {
          "fileName": "subdomains.txt"
        },
        "operation": "toText",
        "sourceProperty": "subdomain"
      },
      "typeVersion": 1.1
    },
    {
      "id": "a7a00079-51f3-4ebe-bb11-cc70fcab1a94",
      "name": "AI SSH create subdomains.txt into /tmp/reconAI",
      "type": "n8n-nodes-base.ssh",
      "position": [
        1568,
        -112
      ],
      "parameters": {
        "path": "/tmp/reconAI",
        "options": {},
        "resource": "file"
      },
      "credentials": {
        "sshPassword": {
          "id": "NMiZzSVngDiy18DK",
          "name": "SSH Password account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "96b396c8-4557-4514-97f3-38a176580972",
      "name": "AI SSH HTTPX",
      "type": "n8n-nodes-base.ssh",
      "onError": "continueRegularOutput",
      "position": [
        1744,
        -112
      ],
      "parameters": {
        "command": "=httpx -silent -tech-detect -l /tmp/reconAI/subdomains.txt -no-color -threads 50 -timeout 4 -retries 1"
      },
      "credentials": {
        "sshPassword": {
          "id": "NMiZzSVngDiy18DK",
          "name": "SSH Password account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "af6a04ba-fb3d-4120-8b78-9b6bd0832852",
      "name": "Rename AI Results",
      "type": "n8n-nodes-base.set",
      "position": [
        1968,
        -112
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "52121e37-4eaa-4157-b913-20240456c381",
              "name": "AI Results",
              "type": "string",
              "value": "={{ $json.stdout }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "a786670b-beac-48df-8882-f6a554194ea4",
      "name": "Rename Passive Results",
      "type": "n8n-nodes-base.set",
      "position": [
        1776,
        -352
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "922911de-2b61-407b-aa07-55d632eae785",
              "name": "Passive Results",
              "type": "string",
              "value": "={{ $json.stdout }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "81395278-355a-4de1-866e-62ade74f5a21",
      "name": "Merge AI & Passive Results",
      "type": "n8n-nodes-base.merge",
      "position": [
        2272,
        -208
      ],
      "parameters": {},
      "typeVersion": 3.2
    },
    {
      "id": "0b1b82e3-bfb5-476f-8981-6301af6b1b0a",
      "name": "Loop Over Domains",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -304,
        -336
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "6c285113-76df-4d75-bb41-6c33194951c5",
      "name": "Split HTTPX Results (400 Items max)",
      "type": "n8n-nodes-base.code",
      "position": [
        1968,
        -352
      ],
      "parameters": {
        "jsCode": "const input = $input.first().json[\"Passive Results\"];\n\nconst lines = input.split(\"\\n\").filter(line => line.trim() !== \"\");\n\nconst results = lines\n  .map(line => {\n    const match = line.match(/https:\\/\\/([a-zA-Z0-9.-]+)/);\n    if (match) {\n      return { content: line.trim() };\n    }\n    return null;\n  })\n  .filter(Boolean)\n  .slice(0, 400);\n\nreturn results.map(r => ({ json: r }));"
      },
      "typeVersion": 2
    },
    {
      "id": "b5ccfc5a-564a-44cb-bd7c-ea713161b184",
      "name": "Loop Over 30 Subdomains",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        752,
        32
      ],
      "parameters": {
        "options": {
          "reset": false
        },
        "batchSize": 30
      },
      "executeOnce": false,
      "typeVersion": 3
    },
    {
      "id": "897da008-6914-4e73-8f80-d3543f973cf1",
      "name": "Append 30 Subdomains",
      "type": "n8n-nodes-base.summarize",
      "position": [
        960,
        48
      ],
      "parameters": {
        "options": {},
        "fieldsToSummarize": {
          "values": [
            {
              "field": "content",
              "aggregation": "append"
            }
          ]
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "29a01c0b-6b49-4768-b48a-9ceae7d49e8d",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -384,
        -720
      ],
      "parameters": {
        "color": 7,
        "width": 3216,
        "height": 1232,
        "content": ""
      },
      "typeVersion": 1
    },
    {
      "id": "69344543-9f53-4602-af51-b2b0b3d09b76",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -352,
        -688
      ],
      "parameters": {
        "color": 4,
        "width": 1056,
        "height": 256,
        "content": "## INPUT - Get File (txt) with Domains"
      },
      "typeVersion": 1
    },
    {
      "id": "9338450e-bbae-4013-9cfe-1e6dbd35faed",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -352,
        -432
      ],
      "parameters": {
        "color": 5,
        "width": 1056,
        "height": 912,
        "content": "## Step 1 – Execute Passive Scanning Tools via SSH"
      },
      "typeVersion": 1
    },
    {
      "id": "f358e247-1b19-4358-b035-1e4acedae5d7",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        704,
        -432
      ],
      "parameters": {
        "color": 5,
        "width": 1408,
        "height": 256,
        "content": "## Step 2 - Execute HTTPX via SSH"
      },
      "typeVersion": 1
    },
    {
      "id": "f2d40ba1-69d4-4c03-afdb-a83846b0d67b",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        704,
        -176
      ],
      "parameters": {
        "color": 5,
        "width": 1408,
        "height": 656,
        "content": "## Step 3 - Generate via OpenAI (GPT-4-Mini) & Execute HTTPX via SSH"
      },
      "typeVersion": 1
    },
    {
      "id": "e7e893b6-5984-4550-8481-de344bb997ed",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2112,
        -432
      ],
      "parameters": {
        "color": 3,
        "width": 688,
        "height": 912,
        "content": "## Step 4 - Append & Send Results"
      },
      "typeVersion": 1
    },
    {
      "id": "7f132a15-bafc-4629-85ea-a40943edc282",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1392,
        -720
      ],
      "parameters": {
        "width": 480,
        "height": 1232,
        "content": "# SET UP\n\n### 1. Set Up SSH Enviroment\n#### VPS SSH\n##### 1. VPS Options (Linux):\n- [Hostinger](https://www.hostinger.com/vps-hosting)\n- [DigitalOcean](https://www.digitalocean.com/pricing)\n- [Hapi Host](https://www.hapihhost.in/vps-hosting/self-managed-vps-hosting/)\n- [WebDedis](https://webdedis.com/cheap-vps-hosting/)\n##### 2. Install Tools\n- [Subfinder](https://docs.projectdiscovery.io/opensource/subfinder/install)\n- [Assetfinder](https://dev.to/vabro/how-to-install-assetfinder-tool-on-any-linunx-distro-353d)\n- [HTTPX](https://docs.projectdiscovery.io/opensource/httpx/install)\n##### 3. Create new SSH Password (root user) in n8n:\n- With Password\n- With Private Key\n\n#### Local SSH\n##### 1. Configure OpenSSH Server\n- [Install OpenSSH](https://www.tecmint.com/install-openssh-server-in-linux/)\n- [Enable Root Login](https://linuxconfig.org/allow-ssh-root-login-on-ubuntu-20-04-focal-fossa-linux)\n##### 2. Install Tools\n- [Subfinder](https://docs.projectdiscovery.io/opensource/subfinder/install)\n- [Assetfinder](https://dev.to/vabro/how-to-install-assetfinder-tool-on-any-linunx-distro-353d)\n- [HTTPX](https://docs.projectdiscovery.io/opensource/httpx/install)\n##### 3. Create new SSH Password (root user) in n8n:\n- With Password\n- With Private Key\n\n### 2. Set Up OpenAI Connection\n#### Get Your API Key\n1. Visit the [OpenAI API Keys](https://platform.openai.com/api-keys) page.\n2. Go to [OpenAI Billing](https://platform.openai.com/settings/organization/billing/overview).\n3. Add funds to your billing account.\n4. Copy your API key into your **OpenAI credentials** in n8n (or your chosen platform).\n"
      },
      "typeVersion": 1
    },
    {
      "id": "0f852116-a546-4643-b8d1-0d776b76c708",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1248,
        288
      ],
      "parameters": {
        "color": 7,
        "width": 720,
        "height": 128,
        "content": "# 📬 Need Help or Want to Customize This?\n## **Contact me for consulting and support:** [LinkedIn](https://www.linkedin.com/in/javier-rieiro-2900b5354/) / [Email](mailto:[email protected])"
      },
      "typeVersion": 1
    },
    {
      "id": "13db1c2d-2712-43ab-96aa-9f57fd1dfd2c",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1472,
        -608
      ],
      "parameters": {
        "color": 4,
        "width": 150,
        "height": 80,
        "content": "## INPUT"
      },
      "typeVersion": 1
    },
    {
      "id": "ee951bf8-f745-4887-bf97-c9fc5f39c7a5",
      "name": "Sticky Note11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1616,
        -608
      ],
      "parameters": {
        "color": 5,
        "width": 150,
        "height": 80,
        "content": "## CORE"
      },
      "typeVersion": 1
    },
    {
      "id": "415903ca-7edd-4788-baab-379c32cd9c11",
      "name": "Sticky Note12",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1760,
        -608
      ],
      "parameters": {
        "color": 3,
        "width": 150,
        "height": 80,
        "content": "## OUTPUT"
      },
      "typeVersion": 1
    },
    {
      "id": "ed82e71c-b87c-42c9-80d0-651255bd443c",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2016,
        -640
      ],
      "parameters": {
        "color": 7,
        "width": 560,
        "height": 144,
        "content": "## $$ Avarage Cost (GPT-4-Mini) $$\n```\nSmall Scope (0 - 30 Scan Results) ≈ 2000 Tokens --> 0.02$\nMedium Scope (30 - 200) ≈ 7000 Tokens --> 0.17$\nBig Scope (200 - 400) ≈ 14000 Tokens --> 0.35 $\n```"
      },
      "typeVersion": 1
    },
    {
      "id": "bc55c7e5-4645-4bf8-adeb-296b0a59fe52",
      "name": "Prettify Results",
      "type": "n8n-nodes-base.code",
      "position": [
        2464,
        -208
      ],
      "parameters": {
        "jsCode": "let combined = {\n  \"Passive Results\": [],\n  \"AI Results\": []\n};\n\nfor (const item of items) {\n  const data = item.json;\n\n  if (data[\"Passive Results\"] && data[\"Passive Results\"].trim() !== \"\") {\n    combined[\"Passive Results\"] = data[\"Passive Results\"]\n      .split(\"\\n\")\n      .map(line => line.trim())\n      .filter(line => line !== \"\");\n  }\n\n  if (data[\"AI Results\"] && data[\"AI Results\"].trim() !== \"\") {\n    combined[\"AI Results\"] = data[\"AI Results\"]\n      .split(\"\\n\")\n      .map(line => line.trim())\n      .filter(line => line !== \"\");\n  }\n}\n\nreturn [{ json: combined }];"
      },
      "typeVersion": 2
    },
    {
      "id": "37051a88-8a87-45d4-86eb-5bc5e012804d",
      "name": "Sticky Note13",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        800,
        -688
      ],
      "parameters": {
        "color": 7,
        "width": 576,
        "height": 224,
        "content": "## Objective of the workflow\n\n#### This workflow automates passive reconnaissance for a given scope, with the added advantage of generating up to 20,000 additional subdomains using an AI agent. This significantly enhances coverage and provides a competitive edge in bug bounty programs by uncovering potential attack surfaces that traditional tools may miss"
      },
      "typeVersion": 1
    }
  ],
  "pinData": {},
  "connections": {
    "crt.sh": {
      "main": [
        [
          {
            "node": "Summarize",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook": {
      "main": [
        [
          {
            "node": "TXT to JSON",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SSH HTTPX": {
      "main": [
        [
          {
            "node": "Rename Passive Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Summarize": {
      "main": [
        [
          {
            "node": "Rename crt.sh Content",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "TXT to JSON": {
      "main": [
        [
          {
            "node": "Prettify File Content",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI SSH HTTPX": {
      "main": [
        [
          {
            "node": "Rename AI Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SSH Subfinder": {
      "main": [
        [
          {
            "node": "Filter Subdomains Subfinder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SSH Assetfinder": {
      "main": [
        [
          {
            "node": "Filter Subdomains Assetfinder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "WayBack Machine": {
      "main": [
        [
          {
            "node": "Filter Subdomains WayBack Machine",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prettify Results": {
      "main": [
        [
          {
            "node": "Respond to Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Domains": {
      "main": [
        [
          {
            "node": "Append all Loop Items",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "crt.sh",
            "type": "main",
            "index": 0
          },
          {
            "node": "WayBack Machine",
            "type": "main",
            "index": 0
          },
          {
            "node": "SSH Assetfinder",
            "type": "main",
            "index": 0
          },
          {
            "node": "SSH Subfinder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge all Results": {
      "main": [
        [
          {
            "node": "Unique Subdomains",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Rename AI Results": {
      "main": [
        [
          {
            "node": "Merge AI & Passive Results",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Split AI Response": {
      "main": [
        [
          {
            "node": "AI Subdomain Format Validation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Unique Subdomains": {
      "main": [
        [
          {
            "node": "Loop Over Domains",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append 30 Subdomains": {
      "main": [
        [
          {
            "node": "Subdomain Generator AI",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append all Loop Items": {
      "main": [
        [
          {
            "node": "Subdomain Format Validation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prettify File Content": {
      "main": [
        [
          {
            "node": "Loop Over Domains",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Rename crt.sh Content": {
      "main": [
        [
          {
            "node": "Merge all Results",
            "type": "main",
            "index": 3
          }
        ]
      ]
    },
    "Rename Passive Results": {
      "main": [
        [
          {
            "node": "Split HTTPX Results (400 Items max)",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge AI & Passive Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Subdomain Generator AI": {
      "main": [
        [
          {
            "node": "Loop Over 30 Subdomains",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over 30 Subdomains": {
      "main": [
        [
          {
            "node": "Split AI Response",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Append 30 Subdomains",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert Subdomains to TXT": {
      "main": [
        [
          {
            "node": "SSH create subdomains.txt into /tmp/reconAI",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge AI & Passive Results": {
      "main": [
        [
          {
            "node": "Prettify Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Subdomains Subfinder": {
      "main": [
        [
          {
            "node": "Merge all Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Subdomain Format Validation": {
      "main": [
        [
          {
            "node": "Convert Subdomains to TXT",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Convert Subdomains to TXT": {
      "main": [
        [
          {
            "node": "AI SSH create subdomains.txt into /tmp/reconAI",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Subdomains Assetfinder": {
      "main": [
        [
          {
            "node": "Merge all Results",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "AI Subdomain Format Validation": {
      "main": [
        [
          {
            "node": "AI Convert Subdomains to TXT",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Subdomains WayBack Machine": {
      "main": [
        [
          {
            "node": "Merge all Results",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Split HTTPX Results (400 Items max)": {
      "main": [
        [
          {
            "node": "Loop Over 30 Subdomains",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SSH create subdomains.txt into /tmp/reconAI": {
      "main": [
        [
          {
            "node": "SSH HTTPX",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI SSH create subdomains.txt into /tmp/reconAI": {
      "main": [
        [
          {
            "node": "AI SSH HTTPX",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

相关工作流