Prevent OS command injection vulnerabilities in Python by shlex.quote()
Credit Img : https://www.immuniweb.com/vulnerability/os-command-injection.html
Date | 10-01-2021 |
---|---|
Author | Thanakorn P. |
ปกติการเขียนโปรแกรมนั้น สิ่งแรกที่คนเขียนโปรแกรมจะคิดถึงเป็นส่วนใหญ่ ก็คือ โปรแกรมต้องทำงานตาม requirement ที่ได้รับเป็นอันดับแรก เช่นโปรแกรมตามด้านล่างนี้ requirement ก็คือการรับค่า domain name จากผู้ใช้งาน และนำไปหาค่า IP address ของ Domain นั้นๆ มาแสดง
Source code
import subprocess
domain_name = input("Enter your domain name: ")
command = f'nslookup {domain_name}'
response = subprocess.check_output(command, shell=True, encoding='UTF-8')
print(response)
Program result
Enter your domain name: google.com
Server: 115.178.58.26
Address: 115.178.58.26#53
Non-authoritative answer:
Name: google.com
Address: 216.58.196.46
จะเห็นได้ว่า โปรแกรมนั้นสามารถทำงานได้ตาม requirement อย่างถูกต้อง
แต่การเขียน code ที่นำ input จาก user มาต่อเข้ากับ command ของ OS สามารถทำให้เกิดช่องโหว่ OS command injection ได้ ตามตัวอย่างต่อไปนี้
Program result (OS Command Injection)
Enter your domain name: google.com && ls -la
Server: 115.178.58.26
Address: 115.178.58.26#53
Non-authoritative answer:
Name: google.com
Address: 172.217.174.174
total 8
drwxr-xr-x 5 korn staff 160 Jan 6 23:29 .
drwxr-xr-x 6 korn staff 192 Jan 6 23:13 ..
drwxr-xr-x 8 korn staff 256 Jan 6 23:29 .idea
-rw-r--r-- 1 korn staff 197 Jan 6 23:29 os_command_injection_sample.py
drwxr-xr-x 6 korn staff 192 Jan 6 23:14 venv
จะเห็นได้ว่า เมื่อทำการเพิ่ม “&& ls -la” ที่เป็น OS command ต่อจาก domain name ที่เป็น input ปกติ โปรแกรมจะทำการ list directory ออกมาหลังจากที่ทำงาน nslookup เรียบร้อยแล้ว
วันนี้เรามีทางออกมานำเสนอ โดยการใช้ function shlex.quote() โดยเมื่อนำมาใช้แล้ว หน้าตาของ code ก็จะประมาณนี้ และเมื่อทำการทดสอบ
Source code (with shlex)
import subprocess
import shlex
domain_name = input("Enter your domain name: ")
command = f'nslookup {shlex.quote(domain_name)}'
response = subprocess.check_output(command, shell=True, encoding='UTF-8')
print(response)
เมื่อทดสอบโปรแกรมดู จะพบว่า สามารถทำงานได้ถาม requirement ปกติ
Program result(with shlex)
Enter your domain name: google.com
Server: 115.178.58.26
Address: 115.178.58.26#53
Non-authoritative answer:
Name: google.com
Address: 216.58.221.206
และเมื่อทดสอบด้วย OS command injection ดูจะพบว่าโปรแกรม พัง… ไม่สามารถทำงานได้
Program result (with shlex and OS Command Injection)
Enter your domain name: google.com && ls -la
Traceback (most recent call last):
File "/Users/korn/PycharmProjects/Code4Sec/os_command_injection_sample.py", line 7, in <module>
response = subprocess.check_output(command, shell=True, encoding='UTF-8')
File "/usr/local/Cellar/python@3.9/3.9.0_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/subprocess.py", line 420, in check_output
return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
File "/usr/local/Cellar/python@3.9/3.9.0_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/subprocess.py", line 524, in run
raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command 'nslookup 'google.com && ls -la'' returned non-zero exit status 1.
Process finished with exit code 1
อธิบาย
เนื่องจากการใช้ function shlex.quote() จะทำให้ input ที่เข้าสู่โปรแกรมจะถูกใส่ ‘[input]’ (quote) ทำให้ OS คิดว่า input ที่เข้ามาเป็น string ชุดเดียว เสมอ
จากนั้น คำสั่ง nslookup ก็นำ string ที่ได้รับมานั้น มาใช้ในการหา IP address ซึ่งโดยปกติแล้ว domain name จะไม่มีช่องว่าง หรือ อักขระพิเศษ ตามหลัง ทำให้ คำสั่ง nslookup ไม่สามารถทำงานได้นั่นเอง จบ…