Skip to content
HackIndex logo

HackIndex

Discovering AI Applications and LLM Endpoints

2 min read Mar 18, 2026

AI applications expose themselves differently from traditional web services. LLM endpoints often live under predictable paths, return distinctive response structures, and leak provider information in headers and error messages. The goal here is to map every AI-enabled surface within scope before touching anything actively — chat interfaces, completion APIs, embedding endpoints, agent frameworks, and any AI-powered feature bolted onto existing applications.

Passive Discovery

Start with passive sources before sending a single request to the target. Historical URLs from crawlers and the Wayback Machine frequently surface AI endpoints that have since been removed from navigation but remain live:

┌──(kali㉿kali)-[~]
└─$ gau $TARGET_DOMAIN | grep -iE 'chat|completion|embedding|llm|ai|model|inference|predict|generate|prompt|gpt|claude|gemini'
https://target.com/api/v1/chat/completions
https://target.com/ai/embed
https://target.com/api/generate
┌──(kali㉿kali)-[~]
└─$ waybackurls $TARGET_DOMAIN | grep -iE 'chat|completion|embedding|llm|model|inference|prompt'

Crawl for AI Endpoints

katana crawls the application and follows JavaScript-rendered content where traditional crawlers miss dynamically loaded AI features:

┌──(kali㉿kali)-[~]
└─$ katana -u https://$TARGET_DOMAIN -jc -d 3 -o katana-output.txt
┌──(kali㉿kali)-[~]
└─$ cat katana-output.txt | grep -iE 'chat|completion|embedding|llm|ai|model|inference|predict|generate|prompt'

Brute-Force Common AI Endpoint Paths

AI frameworks and providers expose endpoints under predictable paths. Build a targeted wordlist from common patterns and brute-force with ffuf:

┌──(kali㉿kali)-[~]
└─$ cat > /tmp/ai-paths.txt << 'EOF'
api/chat
api/v1/chat
api/v1/chat/completions
api/completions
api/v1/completions
api/generate
api/v1/generate
api/embed
api/v1/embeddings
api/embeddings
api/v1/models
api/models
v1/chat/completions
chat
chat/completions
openai/deployments
openai/v1/chat/completions
llm/chat
llm/completions
ai/chat
ai/generate
ai/embed
api/ai/chat
api/inference
api/predict
api/v1/predict
EOF
┌──(kali㉿kali)-[~]
└─$ ffuf -u https://$TARGET_DOMAIN/FUZZ -w /tmp/ai-paths.txt -mc 200,201,400,401,403,405,422 -o ffuf-ai-endpoints.json

Include 400, 401, 403, and 422 in the match codes — AI endpoints frequently return these for malformed or unauthenticated requests, which confirms the endpoint exists even when access is denied. A 422 Unprocessable Entity is a strong indicator of an LLM API expecting a specific JSON body.

Scan with Nuclei AI Templates

nuclei has templates specifically for detecting AI services, exposed model APIs, and misconfigured LLM endpoints:

┌──(kali㉿kali)-[~]
└─$ nuclei -u https://$TARGET_DOMAIN -tags ai,llm,openai,ml -o nuclei-ai-results.txt
┌──(kali㉿kali)-[~]
└─$ nuclei -u https://$TARGET_DOMAIN -tags ai,llm,openai,ml -severity medium,high,critical

Identify AI Features in JavaScript

Modern AI applications load model provider SDKs and call AI APIs from the frontend. Extract JavaScript files and search for AI provider references:

┌──(kali㉿kali)-[~]
└─$ katana -u https://$TARGET_DOMAIN -jc -d 2 | grep '\.js$' | httpx -mc 200 | xargs -I{} curl -sk {} | grep -iE 'openai|anthropic|azure.openai|bedrock|gemini|groq|mistral|ollama|langchain|llamaindex|openrouter'

Provider names in JavaScript bundles reveal which AI service the application uses. A reference to azure.openai means the application proxies through Azure OpenAI Service. bedrock means AWS. anthropic means direct API calls to Claude. Each has slightly different endpoint structures and authentication patterns that inform the next steps.

Check for Proxy Pass-Through Endpoints

Many applications proxy AI provider APIs rather than exposing them directly. Send a minimal completion request to candidate endpoints and observe the response structure:

┌──(kali㉿kali)-[~]
└─$ curl -sk -X POST https://$TARGET_DOMAIN/api/v1/chat/completions -H 'Content-Type: application/json' -d '{"model":"gpt-4","messages":[{"role":"user","content":"hi"}]}' | python3 -m json.tool
{
    "error": {
        "message": "Invalid API key",
        "type": "invalid_request_error",
        "code": "invalid_api_key"
    }
}

An OpenAI-format error response on a target's own domain confirms the endpoint is a proxy to an AI provider. The error type and structure identify the backend provider even when access is denied. This endpoint is a target for authentication bypass and API key extraction in later phases.

References