Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions en/docs/administer/admin-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ This section covers administration tasks you need to perform in WSO2 API Manager
- [Multitenancy]({{base_path}}/administer/multitenancy/introduction-to-multitenancy)
- [Key Managers]({{base_path}}/administer/key-managers/overview)
- [Advanced Configurations]({{base_path}}/administer/advanced-configurations)
- [Outbound Request Security]({{base_path}}/administer/outbound-request-security)
189 changes: 189 additions & 0 deletions en/docs/administer/outbound-request-security.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
# Preventing SSRF Attacks in Outbound Requests

## Overview

Server-Side Request Forgery (SSRF) is a vulnerability where an attacker can manipulate a server to make unintended outbound requests to internal or external systems.

In WSO2 API Manager, outbound requests such as endpoint validation, WSDL imports, and other internal HTTP calls are protected using configurable validation mechanisms.

This feature allows administrators to control outbound traffic using platform-level and tenant-level configurations.

---

## How It Works

When an outbound request is initiated:

1. The request URL is validated against platform-level configuration
2. If allowed, tenant-level validation is applied (if enabled)
3. The request proceeds only if all validations pass

---

## Configuration

### Platform-Level Configuration

Global outbound request validation is configured in `deployment.toml`.

This controls system-wide behavior and is enforced for all tenants.

### Tenant-Level Configuration

Tenant-specific validation rules can be configured using `tenant-conf.json`.

These rules provide additional restrictions but cannot override platform-level configurations.

---

## Configuration Precedence

- Platform-level configuration has higher priority
- Tenant-level configuration cannot override platform restrictions
- Tenant rules apply only if the request is allowed at platform level
- If platform-level configuration is not defined, platform validation is skipped

---

## Host Pattern Matching

Outbound request validation supports simple wildcard-based host matching.

| Pattern | Matches |
|--------|--------|
| `*.example.com` | sub.example.com |
| `api.*.com` | api.test.com |
| `*` | all hosts |

### Notes

- Matching is performed only against the hostname (not full URL)
- `*` is treated as a wildcard
- Regular expressions are not required
- Matching is case-insensitive

---

## Blocking Private Network Access

!!! note
`block_private_network_access` is only applicable when `enabled = true` is set under `[apim.outbound_request_security]`. Additionally, this check is applied **after** the host is validated against `mode` and `exceptions` — a request must first pass that validation before the private network check is performed.

When enabled, outbound requests to private or internal IP ranges are blocked after DNS resolution.

This protects against access to internal infrastructure such as:

- `127.0.0.1` (localhost)
- `10.x.x.x`
- `172.16.x.x – 172.31.x.x`
- `192.168.x.x`
- `169.254.x.x` (link-local)

### Behavior

1. Hostname is resolved to an IP address
2. The resolved IP is checked against private ranges
3. Request is blocked if it matches

---

## Platform-Level Configuration Reference

Configure in `deployment.toml`:

```toml
[apim.outbound_request_security]
enabled = false
mode = "allow_all"
exceptions = []
block_private_network_access = false
```

| Parameter | Type | Default | Description |
|-----------|------|---------|---------------------------------------------------------------------------------------------------------------------|
| `enabled` | boolean | `false` | Enables or disables outbound request validation |
| `mode` | string | `allow_all` | `allow_all` permits all hosts except those in `exceptions`; `deny_all` blocks all hosts except those in `exceptions` |
| `exceptions` | array | `[]` | List of host patterns acting as a denylist (`allow_all`) or allowlist (`deny_all`) (e.g., `*.example.com`) |
| `block_private_network_access` | boolean | `false` | Blocks access to private/internal IP ranges after DNS resolution. Only applicable when `enabled = true`; evaluated after `mode` and `exceptions` validation passes |

!!! note
If this configuration block is not defined, platform-level validation is skipped entirely.

---

## Tenant-Level Configuration Reference

Configure in `tenant-conf.json`:

```json
{
"OutboundRequestSecurity": {
"EnableHostAllowlist": false,
"HostAllowlistPatterns": ["*"]
}
}
```

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `EnableHostAllowlist` | boolean | `false` | Enables tenant-level host validation |
| `HostAllowlistPatterns` | array | `["*"]` | List of allowed host patterns; supports wildcard matching (e.g., `*.example.com`) |

!!! note
Tenant-level validation is applied only after the request passes platform-level validation. Tenant configuration cannot override platform restrictions.

---

## Example Scenarios

### 1. Allow all except specific hosts

Configuration:

- Mode: `allow_all`
- Exceptions act as a denylist

Behavior:

- All outbound requests are allowed
- Requests to hosts in `exceptions` are blocked

---

### 2. Deny all except trusted hosts

Configuration:

- Mode: `deny_all`
- Exceptions act as an allowlist

Behavior:

- All outbound requests are blocked
- Only hosts in `exceptions` are allowed

---

### 3. Tenant-specific restrictions

Configuration:

- Tenant allowlist enabled

Behavior:

- Tenant can only access hosts matching allowlist patterns
- Applied only if platform allows the request

---

### 4. Blocking internal network access

Configuration:

- `block_private_network_access = true`

Behavior:

- Requests to internal/private IPs are blocked even if host matches allowlist

116 changes: 116 additions & 0 deletions en/docs/reference/config-catalog.md
Original file line number Diff line number Diff line change
Expand Up @@ -17242,3 +17242,119 @@ same_site_cookies = "lax"
</section>
</div>



## Outbound Request Security


<div class="mb-config-catalog">
<section>
<div class="mb-config-options">
<div class="superfences-tabs">

<input name="118" type="checkbox" id="_tab_118">
<label class="tab-selector" for="_tab_118"><i class="icon fa fa-code"></i></label>
<div class="superfences-content">
<div class="mb-config-example">
<pre><code class="toml">[apim.outbound_request_security]
enabled = false
mode = "allow_all"
exceptions = []
block_private_network_access = false</code></pre>
</div>
</div>
<div class="doc-wrapper">
<div class="mb-config">
<div class="config-wrap">
<code>[apim.outbound_request_security]</code>
<p>
This includes configurations for protecting WSO2 API Manager against Server-Side Request Forgery (SSRF) attacks by validating outbound requests at the platform level. These settings apply globally across all tenants.
</p>
</div>
<div class="params-wrap">
<div class="param">
<div class="param-name">
<span class="param-name-wrap"> <code>enabled</code> </span>
</div>
<div class="param-info">
<div>
<p>
<span class="param-type string"> boolean </span>
</p>
<div class="param-default">
<span class="param-default-value">Default: <code>false</code></span>
</div>
<div class="param-possible">
<span class="param-possible-values">Possible Values: <code>true, false</code></span>
</div>
</div>
<div class="param-description">
<p>Enables or disables platform-level outbound request validation. If this configuration block is not defined, platform-level validation is skipped entirely.</p>
</div>
</div>
</div><div class="param">
<div class="param-name">
<span class="param-name-wrap"> <code>mode</code> </span>
</div>
<div class="param-info">
<div>
<p>
<span class="param-type string"> string </span>
</p>
<div class="param-default">
<span class="param-default-value">Default: <code>allow_all</code></span>
</div>
<div class="param-possible">
<span class="param-possible-values">Possible Values: <code>allow_all, deny_all</code></span>
</div>
</div>
<div class="param-description">
<p>Determines the base behavior for outbound request filtering. When set to <code>allow_all</code>, all outbound requests are permitted except those matching patterns in <code>exceptions</code> (denylist mode). When set to <code>deny_all</code>, all outbound requests are blocked except those matching patterns in <code>exceptions</code> (allowlist mode).</p>
</div>
</div>
</div><div class="param">
<div class="param-name">
<span class="param-name-wrap"> <code>exceptions</code> </span>
</div>
<div class="param-info">
<div>
<p>
<span class="param-type string"> array </span>
</p>
<div class="param-default">
<span class="param-default-value">Default: <code>[]</code></span>
</div>
</div>
<div class="param-description">
<p>A list of host patterns used to override the base <code>mode</code>. Supports simple wildcard matching against the hostname only (e.g., <code>*.example.com</code>, <code>api.*.com</code>). Matching is case-insensitive. Acts as a denylist when <code>mode = allow_all</code> and as an allowlist when <code>mode = deny_all</code>.</p>
</div>
</div>
</div><div class="param">
<div class="param-name">
<span class="param-name-wrap"> <code>block_private_network_access</code> </span>
</div>
<div class="param-info">
<div>
<p>
<span class="param-type string"> boolean </span>
</p>
<div class="param-default">
<span class="param-default-value">Default: <code>false</code></span>
</div>
<div class="param-possible">
<span class="param-possible-values">Possible Values: <code>true, false</code></span>
</div>
</div>
<div class="param-description">
<p>When enabled, blocks outbound requests whose resolved IP address falls within a private or internal network range (e.g., <code>127.0.0.1</code>, <code>10.x.x.x</code>, <code>172.16.x.x–172.31.x.x</code>, <code>192.168.x.x</code>, <code>169.254.x.x</code>). This check is only applicable when <code>enabled = true</code> and is applied after the request passes the <code>mode</code> and <code>exceptions</code> validation. DNS resolution is performed before this check; if resolution fails, this step is skipped and the request fails naturally.</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</div>

1 change: 1 addition & 0 deletions en/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,7 @@ nav:
- Administrative Capabilities: administer/governance/api-governance-admin-capabilities.md
- CI/CD-Driven Governance: administer/governance/api-governance-cicd.md
- Publisher Portal in Read Only Mode: administer/publisher-portal-in-read-only-mode.md
- Outbound Request Security: administer/outbound-request-security.md


- APIOps:
Expand Down