OpenAPI plugin SSRF validator: resolved IP is not pinned for the connection (DNS check-time vs use-time gap)
Maintainer thường phản hồi trong vòng 4 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 48/100
Hướng nghiên cứu
Bắt đầu với connectors/openapi_plugin/server_url_validator.py và openapi_runner.py, đặc biệt là validate_server_url và run_operation quanh các dòng được dẫn chiếu. Trước tiên, tái hiện chuỗi tra cứu DNS offline, sau đó xác định cách có thể sử dụng lại địa chỉ đã được kiểm tra cho request mà vẫn giữ nguyên cách xử lý hostname; hoàn tất nghĩa là kết nối không thể tự nó phân giải đến một địa chỉ bị quá trình validation từ chối.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Summary
validate_server_url (connectors/openapi_plugin/server_url_validator.py) protects the
OpenAPI plugin against SSRF by resolving the target host and blocking
private/loopback/link-local/metadata addresses. However, the validated IP is not
reused for the actual request: openapi_runner.run_operation calls
validate_server_url(url, ...) (openapi_runner.py ~L146) with no dns_resolver, then
issues the request via httpx.AsyncClient(...).request(url=<hostname>) (~L172-186),
which re-resolves the hostname independently at connect time. A host that resolves
to a public address during validation and to a private address at connect time
(classic DNS rebinding) passes the check and is then contacted. Because
run_operation also attaches auth_callback credentials to the request, the request
that reaches the rebound address is credential-bearing.
Severity (stated honestly — this is hardening, not a high-severity SSRF)
Impact in the default configuration is low, because other layers already constrain it:
- The validator forces
httpsby default, andhttpxverifies TLS certificates
(verify=True), so a rebind to e.g.169.254.169.254fails the TLS handshake — the
request is not sent and no credential is disclosed over the default https path. The
residual over https is a blind connection attempt (TCP connect + ClientHello) to the
internal IP, not data/credential exfiltration. - Full SSRF + credential disclosure via rebinding requires an operator-configured
httpallowed_base_urlsentry, or a caller-suppliedhttp_clientwith
verify=False, or a host platform that ingests untrusted OpenAPI specs/overrides. - The feature is
@experimental.
I'm filing this as defense-in-depth: the validator is a deliberate anti-SSRF control,
and pinning the resolved IP closes the one check-time/use-time gap in it.
Reproduction (mechanism; offline)
semantic-kernel 1.44.1. Making getaddrinfo return a public IP on the 1st lookup
(validation) and a link-local IP on the 2nd (connect) shows the validator passes while
the connection target is an address it would have blocked:
import asyncio, socket
from semantic_kernel.connectors.openapi_plugin.server_url_validator import (
validate_server_url, try_categorize_non_public_address)
HOST, PUBLIC, META = "rebind.example", "93.184.216.34", "169.254.169.254"
_real, n = socket.getaddrinfo, {"i": 0}
def rebinding(host, *a, **k):
if host == HOST:
n["i"] += 1
ip = PUBLIC if n["i"] == 1 else META
return [(socket.AF_INET, socket.SOCK_STREAM, 6, "", (ip, 0))]
return _real(host, *a, **k)
socket.getaddrinfo = rebinding
async def main():
await validate_server_url(f"https://{HOST}/api/op") # 1st resolution -> public -> PASSES
connect_ip = socket.getaddrinfo(HOST, 443)[0][4][0] # 2nd -> 169.254.169.254 (what httpx uses)
print("validated public; connect IP:", connect_ip, try_categorize_non_public_address(connect_ip))
asyncio.run(main())
I did not stand up a live authoritative rebinding DNS server + real httpx connection;
this demonstrates the resolve-then-connect gap the runner relies on.
Suggested remediation
Resolve once and pin: connect to the validated IP (e.g. a custom httpx transport /
resolver that reuses the vetted address while preserving SNI/Host), or re-validate the
peer IP at connect time. Consider applying the IP check on the allowed_base_urls path
too (it currently matches on hostname strings without resolving), and re-validating
after redirects if a caller-supplied client enables follow_redirects.
- Ngôn ngữ chính
- C#
- Star
- 28.6k
- Fork
- 4.8k
- Merge trung bình
- 1 ngày 3 giờ
- Pull request đã merge (30 ngày)
- 16
Chuẩn bị môi trường
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của microsoft/semantic-kernel
-
python triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
microsoft/semantic-kernel#14512 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 4 ngày
-
.NET python triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
microsoft/semantic-kernel#14511 ·
Maintainer thường phản hồi trong vòng 4 ngày
-
python triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
microsoft/semantic-kernel#14491 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 4 ngày
-
python triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
microsoft/semantic-kernel#14490 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 4 ngày
-
Python: [Python] structured_outputs_transform reuses ChatHistory across calls (prompt pollution)Đang mởpython triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
microsoft/semantic-kernel#14483 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 4 ngày
Tất cả issue của microsoft/semantic-kernel
Issue tương tự
-
Money ExploitsĐang mởS: Untriaged
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
project-wayfarer/wayfarer-14#1628 ·
Maintainer thường phản hồi trong vòng 3 ngày
-
:watch: Not Triaged dotnet-target-version
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 85/100
Maintainer thường phản hồi trong vòng 1 ngày
-
copilot documentation
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
Maintainer thường phản hồi trong vòng 2 ngày
-
untriaged
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 86/100
dotnet/dotnet-api-docs#13124 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
agentic-workflows
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
Maintainer thường phản hồi trong vòng 1 ngày