# Cross-Service Trust Boundary Security Detection Module

> Inter-service trust boundaries in microservice architectures, internal authentication, header forgery risks

## Overview (High Priority)

In microservice architectures, inter-service calls often incorrectly assume "internal network is trusted," leading to severe privilege bypass and data leakage.

---

## Detection Categories

### 1. Internal Interfaces Without Authentication

```java
// High: Internal interface without any authentication
@RestController
@RequestMapping("/internal")  // Assuming "internal network is trusted"
public class InternalController {
    @GetMapping("/users/{id}")
    public User getUser(@PathVariable Long id) {
        return userService.findById(id);  // No permission check, SSRF can access
    }
}
```

**Detection**:
```bash
grep -rn "@RequestMapping.*\"/internal\|/admin\|/private\"" --include="*.java" -A 10 | \
  grep -v "@PreAuthorize\|@RequiresPermissions\|checkPermission"
```

### 2. X-Internal-User / X-User-Id Header Forgery

```java
// Critical: Trusting user information in request headers
@GetMapping("/api/profile")
public UserProfile getProfile(HttpServletRequest request) {
    String userId = request.getHeader("X-User-Id");  // Client can forge!
    return profileService.getProfile(userId);  // Privilege escalation
}

// Trusting X-Internal-User flag
String internal = request.getHeader("X-Internal-User");
if ("true".equals(internal)) {
    return adminData;  // Authentication bypass
}
```

**Detection**:
```bash
grep -rn "getHeader.*X-User-Id\|X-Internal-User\|X-Auth-User\|X-Forwarded-User" --include="*.java" -A 5
```

**Security Fix**:
```java
// Use JWT or encrypted/signed headers
String token = request.getHeader("Authorization");
Claims claims = jwtUtil.parseToken(token);  // Verify signature
String userId = claims.getSubject();

// Or use mTLS client certificate
X509Certificate cert = (X509Certificate) request.getAttribute("javax.servlet.request.X509Certificate");
String userId = extractUserIdFromCert(cert);
```

### 3. Inter-Service Token Reuse

```java
// High: User token directly used for inter-service calls
@Service
public class OrderService {
    public void createOrder(String userToken) {
        // User token passed to downstream service
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", "Bearer " + userToken);  // Token reuse, no scope restriction

        restTemplate.exchange("http://payment-service/charge",
                              HttpMethod.POST, new HttpEntity<>(headers), ...);
    }
}
```

**Detection**:
```bash
grep -rn "restTemplate\|feignClient" --include="*.java" -A 10 | \
  grep "Authorization.*userToken\|Bearer.*token"
```

**Security Fix**:
```java
// Use Service Account Token
String serviceToken = tokenService.getServiceAccountToken("order-service");
headers.set("Authorization", "Bearer " + serviceToken);

// Or use Token Exchange (RFC 8693)
TokenExchangeRequest exchangeReq = new TokenExchangeRequest()
    .subject Token(userToken)
    .audience("payment-service")
    .scope("payment:create");
String downstreamToken = tokenService.exchange(exchangeReq);
```

### 4. Feign / gRPC Without mTLS

```java
// High: Feign HTTP call without mTLS
@FeignClient(name = "user-service", url = "http://user-service:8080")  // HTTP!
public interface UserClient {
    @GetMapping("/users/{id}")
    User getUser(@PathVariable Long id);
}

// gRPC insecure channel
ManagedChannel channel = ManagedChannelBuilder
    .forAddress("inventory-service", 9090)
    .usePlaintext()  // No TLS!
    .build();
```

**Detection**:
```bash
grep -rn "@FeignClient.*url.*http://" --include="*.java"
grep -rn "\.usePlaintext()" --include="*.java"
grep -rn "ManagedChannelBuilder\.forAddress" --include="*.java" -A 3
```

**Security Fix**:
```java
// Feign with mTLS
@Configuration
public class FeignConfig {
    @Bean
    public Client feignClient() throws Exception {
        SSLContext sslContext = SSLContextBuilder.create()
            .loadTrustMaterial(trustStore, trustStorePassword)
            .loadKeyMaterial(keyStore, keyStorePassword)
            .build();

        return new Client.Default(sslContext.getSocketFactory(),
                                  new DefaultHostnameVerifier());
    }
}

// gRPC with TLS
ManagedChannel channel = NettyChannelBuilder
    .forAddress("inventory-service", 9443)
    .sslContext(GrpcSslContexts.forClient()
        .trustManager(new File("ca.crt"))
        .keyManager(new File("client.crt"), new File("client.key"))
        .build())
    .build();
```

---

## Detection Checklist

### Critical
- [ ] Trusting forgeable headers like X-User-Id/X-Internal-User
- [ ] Internal interfaces completely without authentication

### High
- [ ] Inter-service HTTP calls without mTLS
- [ ] User tokens directly reused for inter-service calls
- [ ] gRPC usePlaintext()

### Medium
- [ ] Internal interface authentication weaker than external interface
- [ ] IP whitelist-based internal authentication (can be bypassed)

---

## Minimal PoC Examples
```bash
# Forge internal authentication headers
curl -H "X-User-Id: 1" -H "X-Internal-User: true" https://api.example.com/internal/admin

# gRPC plaintext
grpcurl -plaintext internal.example.com:50051 list
```

---

## False Positives

- Headers set by API Gateway and downstream services only reachable within internal network (requires network isolation proof)
- HTTP calls in development/test environments (must be explicitly marked)
- Health check interfaces without authentication (must restrict path such as /actuator/health)

---

## References

- OWASP: Server-Side Request Forgery
- RFC 8693: OAuth 2.0 Token Exchange
- mTLS Best Practices for Microservices
