NeuroStrike

The Attack Surface Nobody Monitors

NeuroStrike Research

Security Research Team

|3 min read
The Attack Surface Nobody Monitors: Internal API Security

When we gain initial access during an internal penetration test, the first thing we do is map internal APIs. Not external endpoints — the service-to-service communication between your microservices, orchestrators, and backend systems. In 82% of internal engagements, these APIs are the fastest path to sensitive data and privilege escalation.

The reason is straightforward: internal APIs are designed for machine-to-machine communication within a "trusted" network. Security controls that are standard on external APIs — authentication, authorization, rate limiting, input validation — are frequently absent on internal endpoints.

The 'Behind the Firewall' Fallacy

We hear this in every pre-engagement meeting: "Those APIs don't need authentication because they're only accessible from inside the network." This assumption breaks the moment an attacker achieves any form of internal access — through phishing, a compromised VPN, a vulnerable web application, or a supply chain attack.

Once inside, the attacker has the same network access as your microservices. Every unauthenticated internal API is now directly accessible.

Our internal testing data:

  • 73% of internal APIs have no authentication
  • 89% have no authorization (even among those with authentication, most accept any valid token regardless of the caller's identity)
  • 91% have no rate limiting
  • 64% have no input validation (they trust that callers send well-formed data)
  • 47% expose admin or debug endpoints (health checks, metrics, pprof, debug logs)

Test your internal network

Deploy an autonomous agent inside your network for continuous internal penetration testing.

Learn About On-Prem

What We Find in Internal APIs

Kubernetes Service Discovery

In Kubernetes environments, services are discoverable via DNS. An attacker on any pod can enumerate services:

# Enumerate services in all namespaces
# From any compromised pod
for ns in $(kubectl get ns -o name 2>/dev/null | cut -d/ -f2); do
  echo "=== $ns ===" 
  nslookup -type=srv _http._tcp.$ns.svc.cluster.local 2>/dev/null
done

# Or just scan common ports
for svc in api-gateway user-service payment-service admin-service; do
  curl -s http://$svc.default.svc.cluster.local/health && echo " => $svc is alive"
done

From there, the attacker probes each service for unauthenticated endpoints, admin interfaces, and sensitive data.

GraphQL Introspection on Internal APIs

Internal GraphQL APIs almost always have introspection enabled. This gives the attacker a complete schema of every query, mutation, and type — a roadmap to the data model.

# GraphQL introspection query
curl -s http://internal-api:4000/graphql \
  -H "Content-Type: application/json" \
  -d '{"query":"{__schema{types{name fields{name type{name}}}}}"}'

gRPC Reflection

gRPC services with reflection enabled expose their entire API surface. Tools like grpcurl can enumerate and call any method:

# List all gRPC services and methods
grpcurl -plaintext internal-service:50051 list
grpcurl -plaintext internal-service:50051 describe my.package.UserService

Test your internal network

Deploy an autonomous agent inside your network for continuous internal penetration testing.

Learn About On-Prem

How to Secure Internal APIs

Implement mTLS for Service-to-Service Communication

Mutual TLS ensures both sides of a connection present valid certificates. Service meshes like Istio and Linkerd automate this, but you can implement it directly:

// Node.js server with mTLS
import https from "https";
import fs from "fs";

const server = https.createServer({
  key: fs.readFileSync("server-key.pem"),
  cert: fs.readFileSync("server-cert.pem"),
  ca: fs.readFileSync("ca-cert.pem"),
  requestCert: true,        // Require client certificate
  rejectUnauthorized: true,  // Reject invalid certificates
}, app);

server.listen(443);

Use Network Policies in Kubernetes

Kubernetes NetworkPolicies restrict pod-to-pod communication. By default, all pods can communicate with all other pods. Define explicit policies:

# Only allow payment-service to talk to database
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: payment-db-access
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: payment-service
    ports:
    - protocol: TCP
      port: 5432

Disable Introspection and Reflection in Production

GraphQL introspection and gRPC reflection are development tools. Disable them in production. If you need them for internal documentation, restrict them to specific service accounts.

Testing Your Internal API Security

External scanners can't see internal APIs. You need an agent inside the network that:

  • Discovers all services on the internal network (DNS enumeration, port scanning)
  • Tests authentication on every endpoint (sends requests without credentials)
  • Tests authorization across services (uses one service's credentials to access another)
  • Checks for exposed admin and debug endpoints
  • Validates network segmentation between service tiers
The perimeter is a speed bump. Internal API security is the moat. Test it like an attacker would — from inside, with the access a compromised pod or endpoint would have.

Test your internal network

Deploy an autonomous agent inside your network for continuous internal penetration testing.

Learn About On-Prem

Related Posts

The Attack Surface Nobody Monitors | NeuroStrike | NeuroStrike