สรุปสั้น

ทีมผู้ดูแล Model Context Protocol (MCP) Python SDK ซึ่งเป็น SDK ทางการสำหรับสร้างเซิร์ฟเวอร์และไคลเอนต์ MCP ออกประกาศเตือนความปลอดภัยว่าเวอร์ชันที่มีช่องโหว่ยอมให้เซิร์ฟเวอร์ MCP ที่เป็นอันตรายหลอกแอปพลิเคชันฝั่งไคลเอนต์ให้ส่งมอบ credentials ที่ใช้ล็อกอินเข้าบริการจริง ทั้ง client secret, authorization code และ PKCE proof key ไปยัง token endpoint ที่ผู้โจมตีควบคุม เมื่อได้ credentials เหล่านี้ ผู้โจมตีก็นำไปขอ access token ที่ใช้งานได้จริงจากบริการล็อกอินตัวจริง โดย token ที่ได้จะมีสิทธิ์เท่ากับที่แอปได้รับ และเพราะ client secret เป็นค่าอายุยาว มันจึงใช้ได้เรื่อย ๆ จนกว่าจะถูกเปลี่ยน บริษัท Cycode ผู้รายงานช่องโหว่ได้สาธิตการแลก credentials เป็น token ได้สำเร็จในการทดสอบ ช่องโหว่ได้คะแนนความรุนแรงสูง (7.5) สำหรับผู้ให้บริการแบบ machine-to-machine สองรายที่ทำงานโดยไม่ต้องมีคนอยู่ และ 6.5 สำหรับผู้ให้บริการแบบโต้ตอบ ณ วันที่ 29 กันยายนยังไม่มีการกำหนดหมายเลข CVE และการแก้ไขอยู่ในเวอร์ชัน 1.30.0 (สาย 1.x) และ 2.2.0 (สาย 2.x)

รายละเอียดข่าว

เว็บไซต์ The Hacker News รายงานเมื่อวันที่ 29 กันยายน 2569 ว่าทีมผู้ดูแล MCP Python SDK ได้ออกประกาศความปลอดภัยเกี่ยวกับช่องโหว่ในกระบวนการ OAuth ของ SDK ตัวนี้ ซึ่ง MCP เป็นมาตรฐานเปิดสำหรับเชื่อมต่อแอปพลิเคชัน AI เข้ากับเครื่องมือและข้อมูลภายนอก และแพ็กเกจนี้คือ SDK ภาษา Python ทางการสำหรับสร้างทั้งเซิร์ฟเวอร์และไคลเอนต์ตามมาตรฐานดังกล่าว บริษัท Cycode ซึ่งเป็นบริษัทความปลอดภัยที่รายงานช่องโหว่ ระบุว่าเวอร์ชันที่ได้รับผลกระทบส่ง client secret, authorization code และ PKCE proof key ไปยัง token endpoint ที่ผู้โจมตีกำหนดได้ ทำให้ผู้โจมตีสามารถขอ access token ที่ถูกต้องมาใช้แทนเหยื่อ โดย token นั้นแบกสิทธิ์ทั้งหมดที่แอปได้รับไว้ ที่น่ากังวลคือ client secret เป็นค่าอายุยาวจึงใช้งานได้ต่อเนื่องจนกว่าจะถูกเปลี่ยน สำหรับผู้ให้บริการแบบ machine-to-machine สองรายที่ทำงานอัตโนมัติไม่ต้องมีคนกดยืนยัน ช่องโหว่ถูกให้คะแนน 7.5 ส่วนกรณีผู้ให้บริการแบบโต้ตอบที่ต้องมีคนเริ่มการเข้าสู่ระบบ คะแนนอยู่ที่ 6.5 ทั้งนี้ ณ วันที่ 29 กันยายนยังไม่มีการกำหนด CVE ให้กับช่องโหว่นี้

วิธีการโจมตี

เมื่อไคลเอนต์ MCP ต้องล็อกอิน มันจะถามเซิร์ฟเวอร์ที่กำลังเชื่อมต่อว่าบริการล็อกอิน (authorization server) ของมันอยู่ที่ไหน บนเวอร์ชันที่มีช่องโหว่ SDK ไม่ได้ตรวจสอบคำตอบนี้เสมอไป เซิร์ฟเวอร์ที่เป็นอันตรายจึงชี้ให้ไคลเอนต์ไปยังบริการล็อกอินที่ผู้โจมตีเลือกเองได้ ไม่ว่าจะด้วยการระบุเซิร์ฟเวอร์ของผู้โจมตีเอง หรือส่งรายละเอียดล็อกอินที่อ้างชื่อบริการจริงของผู้ใช้แต่กลับส่ง credentials ไปที่อื่น จากนั้นไคลเอนต์จะส่ง client secret, authorization code และ PKCE proof key ไปยังผู้โจมตีแทนบริการจริง ตัว proof key นั้นออกแบบมาให้ใช้ครั้งเดียวเพื่อกันไม่ให้ authorization code ที่ถูกขโมยถูกนำกลับมาใช้ซ้ำ การส่งมันให้ผู้โจมตีจึงทำลายการป้องกันชั้นนี้ไปด้วย กรณีผู้ให้บริการแบบโต้ตอบ ผู้ใช้ยังต้องกดอนุมัติการเข้าสู่ระบบ แต่ Cycode ระบุว่าหน้าที่ผู้ใช้อนุมัติคือหน้าล็อกอินจริง ทุกอย่างจึงดูไม่ผิดปกติ ส่วนผู้ให้บริการแบบ machine-to-machine ทั้งสองรายไม่ต้องมีการล็อกอินและไม่ต้องมีคนอยู่เลย

ผลกระทบ

แอปพลิเคชันจะได้รับผลกระทบก็ต่อเมื่อใช้ SDK เป็นไคลเอนต์ MCP ผ่าน HTTP ร่วมกับผู้ให้บริการ OAuth อย่าง OAuthClientProvider, ClientCredentialsOAuthProvider, PrivateKeyJWTOAuthProvider หรือ RFC7523OAuthClientProvider (ตัวที่เลิกใช้แล้วในสาย 1.x) และสามารถเชื่อมต่อไปยังเซิร์ฟเวอร์ที่ตนไม่ได้ควบคุมเต็มที่ในขณะที่ถือ credentials ของบริการล็อกอินจริงอยู่ ในทางกลับกัน เซิร์ฟเวอร์ MCP ที่สร้างด้วย SDK, ไคลเอนต์แบบ local (stdio) และไคลเอนต์ที่แนบ token ของตัวเองไปเอง จะไม่ได้รับผลกระทบ สำหรับสายเวอร์ชัน ตัวที่มีช่องโหว่คือ 1.9.1 ถึง 1.29.1 (แก้ใน 1.30.0) และ 2.0.0 ถึง 2.1.1 (แก้ใน 2.2.0) ทั้งนี้ยังไม่พบว่ามีการนำช่องโหว่ไปใช้โจมตีจริงทั้งจากประกาศของผู้ดูแลและจากรายงานของ Cycode

คำแนะนำ

ผู้ดูแลระบบควรอัปเกรดเป็นเวอร์ชัน 1.30.0 บนสาย 1.x หรือ 2.2.0 บนสาย 2.x ซึ่งในเวอร์ชันที่แก้แล้ว ไคลเอนต์จะคำนวณว่าตนคาดหวังบริการล็อกอินตัวใดก่อนจะดึงรายละเอียดใด ๆ และจะปฏิเสธรายละเอียดที่อ้างชื่อบริการอื่น อย่างไรก็ตาม การอัปเกรดยังไม่ใช่การแก้ที่สมบูรณ์สำหรับผู้ให้บริการสองราย หากใช้ ClientCredentialsOAuthProvider หรือ PrivateKeyJWTOAuthProvider ประกาศระบุว่า “การอัปเกรดจะไม่เปลี่ยนอะไรจนกว่าจะระบุ issuer=” เพื่อบอกว่า credentials นั้นเป็นของบริการล็อกอินใด หากไม่ระบุ มันจะยังตามเซิร์ฟเวอร์ที่เซิร์ฟเวอร์ MCP ชี้ไปอยู่ดี บน 1.30.0 คำเตือนเรื่องนี้เป็น deprecation warning มาตรฐานที่ Python ซ่อนไว้โดยดีฟอลต์จึงพลาดได้ง่าย ส่วน RFC7523OAuthClientProvider ที่เลิกใช้ไม่มีตัวเลือก issuer= เลย จึงควรย้ายไปใช้ผู้ให้บริการอีกสองตัว หลังอัปเกรดควรล้าง OAuth client registration ที่เก็บไว้เสียหนึ่งครั้ง เพราะรายการเก่าไม่ได้ผูกกับบริการล็อกอินและจะคงสภาพนั้นไว้ หากไคลเอนต์เคยเชื่อมต่อไปยังเซิร์ฟเวอร์ที่ไม่น่าเชื่อถือ ควรหมุน client secret ใหม่และเพิกถอน token ที่บริการล็อกอิน สำหรับเวอร์ชันเก่าที่ยังไม่ได้แก้ ไม่มีวิธีแก้ชั่วคราวอื่นนอกจากเชื่อมต่อเฉพาะเซิร์ฟเวอร์ MCP ที่ไว้ใจได้เท่านั้น

แหล่งอ้างอิง