Sitemap

Command injection 101

3 min readMay 28, 2025

สวัสดีครับท่านผู้อ่านทุกท่าน วันนี้ผมมีบทความเกี่ยวกับ OS command injection เบื้องต้น มาเล่าให้ฟังคร่าวๆ มาฝากกันครับ ซึ่ง OS command injection จะอยู่ในหมวด OWASP Top 10 Web Application Security Risks ข้อ 3 หรือ A03:2021-Injection ช่องโหว่นี้หลักๆแล้วมักเกิดจากการที่รับข้อมูลจากผู้ใช้โดยที่ไม่ได้มีการกรองหรือตรวจสอบอย่างเหมาะสม และนำข้อมูลดังกล่าวไปใช้ในคำสั่งระบบปฏิบัติการ (OS Command) โดยตรง ทำให้ผู้ไม่หวังดีสามารถ แทรกคำสั่งอันตราย เข้าไปรันบนระบบได้

ยกตัวอย่าง ลองนึกภาพว่าเรามีฟอร์มในหน้าเว็บที่ให้ผู้ใช้กรอก IP address เพื่อให้เซิร์ฟเวอร์สั่ง ping ไปยัง IP นั้น แล้วแสดงผลลัพธ์ให้ดูบนเว็บ นี่คือฟีเจอร์ธรรมดามาก และใช้กันจริงในหลายระบบ เช่น หน้า status ตรวจสอบ server หรือ router แต่ถ้าผู้ใช้กรอก IP ว่า 8.8.8.8;id แล้วเซิร์ฟเวอร์ดันรันคำสั่งนี้แบบตรง ๆ เช่น ping -c 4 8.8.8.8;id จะเกิดอะไรขึ้น?

คำตอบคือ ระบบจะ ping ไปยัง IP ปกติ แล้วต่อด้วยการรันคำสั่ง id ซึ่งจะแสดงชื่อผู้ใช้และสิทธิของ process ที่รันอยู่ นี่คือจุดเริ่มต้นของการโจมตีแบบ Command Injection นั่นเองครับ (ในส่วนของการโจมตีเราจะไปพูดในภายหลัง ว่าทำไมการที่ใช้ ; ถึงทำให้ระบบทำงานแบบนั้น) แต่ก่อนอื่นเราต้องรู้ก่อนว่า Command Injection คืออะไร?

https://www.acunetix.com/blog/web-security-zone/os-command-injection/

Command Injection คืออะไร?

OS Command Injection หรือ บางคนก็รู้จักในชื่อ Shell Injection คือ ช่องโหว่ที่เกิดขึ้นเมื่อตัว application นำ input ของผู้ใช้งาน ไปต่อกับคำสั่งของระบบปฏิบัติการผ่าน shell โดยตรง เช่น Bash, sh หรือ cmd.exe โดยที่ไม่มีการตรวจสอบหรือกรองตัวของ Input ให้ดีก่อน ส่งผลให้ผู้โจมตีสามารถแทรกคำสั่งใหม่ลงไปในบรรทัดเดียวกันได้ผ่าน metacharacters เช่น ;, &&, |, ` และ $()

ถ้าจะให้อธิบายแบบสั้น ๆ ง่าย ๆ ก็คือการที่เรานำค่าจากผู้ใช้ไปต่อกับคำสั่งของระบบ (ผ่าน shell) โดยไม่กรองก่อน ส่งผลให้ผู้ใช้สามารถแทรกคำสั่งของตัวเองเข้ามาได้แบบชิลๆ

ตัวอย่าง เช่น เราส่งคำสั่งแบบนี้ไปให้ shell:

ping -c 4 8.8.8.8; id

Shell ก็จะพูดว่า “โอเคครับ เดี๋ยว ping ให้ แล้วตามด้วยใช้คำสั่ง id ให้ด้วย “

นั่นแปลว่าถ้าเราไม่ระวัง Hacker สามารถพ่วงคำสั่งตามที่ต้องการเข้าสู่ระบบได้เต็มที่เลย

Command Injection ต่างจาก SQL Injection ยังไง? ⚔️

แม้ Command Injection และ SQL Injection จะถูกจัดอยู่ในกลุ่ม A03:2021-Injection เหมือนกัน อ้างอิงจาก OWASP Top 10 Web Application Security แถมยังมีจุดเริ่มต้นเหมือนกันคือ เกิดจากการที่ระบบเอา Input จากผู้ใช้งานไป process โดยที่ไม่ได้มีการตรวจสอบหรือกรองให้ดี แต่ความต่างของทั้งสองอยู่ที่ ‘’เป้าหมาย” และ “ผลลัพธ์” ครับ

SQL Injection คือการแทรก (Injection) SQL Query ผ่าน input ที่ผู้ใช้ส่งเข้ามา เพื่อ ควบคุม หรือ เปลี่ยนแปลง การทำงานของ SQL Query เดิม ของแอปพลิเคชัน ส่วน Command Injection คือการแทรกคำสั่งระบบปฏิบัติการ (OS Command) ลงไปในโปรแกรมที่นำ Input ของผู้ใช้ไปสร้างคำสั่ง Shell หรือรันบน Command Line โดยตรง ทำให้ผู้โจมตีสามารถสั่งการ OS ได้ เช่นการรันคำสั่ง whoami, id, หรือแม้กระทั่งเปิด Reverse Shell

ถ้าจะเปรียบให้เห็นภาพ:

  • SQL Injection ก็เหมือน Hacker ปลอมตัวเป็นเจ้าหน้าที่บัญชี แอบเข้าไปอ่านและแก้ไขสมุดบัญชีได้
  • Command Injection คือ Hacker งัดประตูหลัง เข้าไปนั่งที่โต๊ะเซิร์ฟเวอร์แล้วพิมพ์คำสั่งอะไรก็ได้ในระบบเลย

อีกจุดที่ควรรู้คือ SQL Injection จะเกิดขึ้นเฉพาะกับระบบที่ใช้ฐานข้อมูลและมีการสร้างคำสั่ง SQL จาก input ของผู้ใช้

ส่วน Command Injection ไม่จำกัดแพลตฟอร์ม เพราะแค่มีการเรียก shell แบบไม่ระวัง ก็เปิดช่องได้แล้ว

สรุปง่ายๆกว่านั้นก็คือ :

  • SQL Injection = เล่นกับคำสั่งใน Database
  • Command Injection = เล่นกับคำสั่งใน OS
https://fossbytes.com/what-is-linux-shell/

แล้ว shell มันเกี่ยวอะไรกับ command injection ด้วยล่ะ?

Shell ที่เรากล่าวถึงในบทความนี้ไม่ใช่ shell ที่เป็นสัตว์ไม่มีกระดูกสันหลังแต่อย่างใด Shell ที่เรากำลังจะกล่าวถึงคือ ผู้ช่วยส่วนตัวที่แปลคำสั่งเป็นการกระทำ เช่น ls, ping, cat คือคำสั่งที่ shell เข้าใจดี

แต่ด้วยการที่ shell มี fundamental feature ที่ดีเกินไปทำให้ มันสามารถตีความบางตัวอักษรพิเศษให้มีความหมายได้ หรือที่เรียกกันว่า metacharacters ซึ่งเป็นตัวการหลักๆที่ทำให้ Hacker สามารถแทรกคำสั่งอันตรายเข้าสู่ระบบได้

โดย shell มันจะตีความอักขระพิเศษ(metacharacters) ในลักษณะแบบนี้ :

  • ; = “เอาอีกคำสั่งมารันต่อได้เลย”
  • && = “ถ้าคำสั่งแรกสำเร็จ เดี๋ยวรันต่อให้นะ”
  • `whoami` = “ไปรัน whoami แล้วเอาผลลัพธ์มาใส่ตรงนี้นะ”

ซึ่ง Hacker ก็ยิ้มหวานเลยครับ ถ้าโค้ดไม่มีการกรองกับใช่อักษรพิเศษพวกนีได้

Command Injection มักเกิดจากอะไร? ⚠️

ลองมาดูตัวอย่างของจริงจาก DVWA (Damn Vulnerable Web Application) กันครับ ซึ่งเป็นหนึ่ง lab ที่ค่อนข้างดีเลยสำหรับฝึกมือสำหรับ การโจมตีท่าต่างๆ:

$target = $_REQUEST[‘ip’];
$cmd = shell_exec("ping -c 4 " . $target);
echo "<pre>{$cmd}</pre>";

จะเห็นได้ว่าโค้ดนี้ดูธรรมดามากเลยใช่ไหมครับ แต่โค้ดนี่แหละเป็นจุดเริ่มต้นของ Command Injection เลย เพราะว่าจะเห็นได้ว่า มันเอาค่าจาก $_REQUEST[‘ip’] ไปต่อกับคำสั่ง shell โดยตรง โดยไม่มีการป้องกันใดๆทั้งสิ้น

แล้วทำไมมันถึงเสี่ยง? เพราะ shell มันมี metacharacter หรืออักขระพิเศษ(ที่เราคุยกันในหัวข้อก่อนหน้า) ที่มันเอาไว้ “แปลว่าให้รันอีกคำสั่ง” ได้ เช่น:

  • ; → รันคำสั่งถัดไปทันที
  • && → รันคำสั่งถัดไปถ้าคำสั่งแรกสำเร็จ
  • | → ส่ง output จากคำสั่งแรกไปให้คำสั่งถัดไป
  • `command` หรือ $(command) → รัน command ย่อยแล้วแทนค่าผลลัพธ์เข้าไป

ยกตัวอย่างง่าย ๆโดยปกติตาม function นี้คนทั่วไปก็จะส่งค่าแค่นี้:

?ip=8.8.8.8

ก็จะกลายเป็น ping -c 4 8.8.8.8 แต่ที่นี่เราไม่ทำกันแบบนั้น !!!

โดย Hacker จะแทรก ; (รันคำสั่งถัดไปทันที) แล้วต่อด้วยชุดคำสั่งที่ต้องการ เช่น id

?ip=8.8.8.8 ;id

ก็จะกลายเป็น ping -c 4 8.8.8.8 และ id ถูกรันต่อท้าย

แล้วเราจะป้องกันยังไง ?

หากอ้างอิงจาก OWASP จะแยกวิธีแก้ไขช่องโหว่หลักๆ ได้ 3 วิธีหลักๆดังนี้

วิธีที่ 1: หลีกเลี่ยงการเรียกใช้คำสั่งระบบปฏิบัติการโดยตรง

ตามหัวข้อเลยครับ การป้องกันที่ดีที่สุดคือการไม่ใช้งาน OS command โดยตรง แต่ให้ใช้ฟังก์ชันในไลบรารีของภาษาโปรแกรมนั้นๆแทน เช่น

  • ใช้ mkdir() แทน system(“mkdir /dir_name”)

วิธีที่ 2: Escape ค่าที่จะนำไปใช้กับคำสั่งระบบ

หากจำเป็นต้องใช้คำสั่ง OS จริงๆ ควร Escape ข้อมูลที่ผู้ใช้ป้อนเข้ามา ให้เหมาะกับระบบปฏิบัติการนั้น ๆ ตัวอย่างเช่นในภาษา PHP:

  • escapeshellarg() จะครอบค่าที่รับเข้ามาด้วย single quotes เช่น
    หากผู้ใช้ป้อน & echo “hello”
    เมื่อผ่าน escapeshellarg() จาก & echo “hello” จะกลายเป็น ‘& echo “hello”’
    ซึ่งระบบจะมองว่าเป็น argument เดียวของคำสั่ง ไม่ใช่คำสั่งใหม่

อย่างไรก็ตาม escapeshellarg() เพียงป้องกันการ inject คำสั่งใหม่ แต่ผู้โจมตียังสามารถส่ง argument ที่เป็นอันตรายได้อยู่ดี

วิธีที่ 3: ใช้ Parameterization ควบคู่กับ Input Validation

· Parameterization คือกลไกของภาษาหรือไลบรารีที่ช่วยแยก “ข้อมูล” ออกจาก “คำสั่ง” อย่างชัดเจน โดยระบบจะจัดการเรื่องการใส่เครื่องหมาย quote และการเข้ารหัส (encoding) ให้โดยอัตโนมัติ เพื่อไม่ให้ input ที่รับมาจากผู้ใช้ถูกตีความเป็นส่วนหนึ่งของคำสั่ง — ช่วยป้องกันไม่ให้ข้อมูลกลายเป็นคำสั่งที่เป็นอันตรายได้

· Input Validation คือการตรวจสอบว่าข้อมูลที่ผู้ใช้กรอกเข้ามา “ถูกต้อง” และ “ปลอดภัย” ก่อนนำไปใช้งาน รับแค่ข้อมูลที่จำเป็น เช่น หาก application ต้องการรับค่า 1–10 ก็ให้ application รับค่าได้แค่ 1–10 เท่านั้น

ซึ่งผมจะทิ้ง Lab ไว้ให้ฝึกมือตาม list ด้านล่างเลยครับ

References:

https://owasp.org/www-community/attacks/Command_Injection

https://www.imperva.com/learn/application-security/command-injection/

https://portswigger.net/web-security/os-command-injection

https://www.invicti.com/learn/os-command-injection/

https://cheatsheetseries.owasp.org/cheatsheets/OS_Command_Injection_Defense_Cheat_Sheet.html

https://cheatsheetseries.owasp.org/cheatsheets/OS_Command_Injection_Defense_Cheat_Sheet.html

https://cheatsheetseries.owasp.org/cheatsheets/OS_Command_Injection_Defense_Cheat_Sheet.html

--

--

No responses yet