New FAMILUG

The PyMiers

Tuesday 30 September 2014

[bash] shellshock - từ gốc đến ngọn

Shellshock là gì?
shellshock là tên của lỗi bảo mật của phần mềm bash mới được phát hiện (tháng 9/2014) và hiện đang gây một cơn sốc trên Internet. Nó không phải sốc theo kiểu "cộng đồng mạng phát cuồng", hay "cộng đồng mạng bị sốc", mà là kiểu sốc "cộng đồng mạng" cơ bản là không tham gia vào :D

Shellshock có nguy hiểm không?
Cực kỳ nguy hiểm! cực kỳ là đến mức nào? Hãy google với từ khoá "shellshock dangerous" để tìm ra câu trả lời cho chính mình.
Nói thẳng ra thì người dùng Windows không bị ảnh hưởng (trực tiếp), còn ai không biết thì chẳng thấy nguy hiểm gì. Giống như dịch Ebola, ai biết nó gây chết người trong vài ngày thì thấy sợ, ai không biết nó là cái gì thì làm sao mà thấy nó nguy hiểm?!!!

Lỗi này có từ năm 1993 1989 [Thanks Le Manh Cuong] và đến nay đã 25 năm từ khi nó ra đời, nhưng đến giờ mới được phát hiện. Hãy tưởng tượng trong 25 năm ấy, hacker có thể dễ dàng vào máy tính của bạn với quyền root (tức muốn làm gì thì làm),  chẳng phải login hay ssh gì hết, và không để lại dấu vết của một cuộc xâm nhập :3

Bài viết này phân tích câu lệnh dùng để tìm ra xem phiên bản bash đang dùng có bị dính lỗi bảo mật shellshock hay không.

Câu lệnh sau giúp thực hiện điều đó (theo link wikipedia ở cuối bài):
env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
Nếu sau khi gõ enter mà thấy hiện ra
vulnerable
this is a test
Tức là phiên bản bash bạn đang dùng có dính lỗi bảo mật này.

Để hiểu rõ chuyện gì đã xảy ra, ta sẽ từ từ phân tích câu thần chú vừng ơi mở ra đầy thần bí này. Lần lượt dạo qua một vài khái niệm của bash để có thể hiểu câu lệnh quá xúc tích trên:

1. function 
Có hai cách định nghĩa function trong bash, trích cú pháp từ man 1 bash:

       name () compound-command [redirection]
       function name [()] compound-command [redirection]

Cách 1 ngắn gọn hơn, là dùng: tên_function () body
Cách 2 dài dòng hơn, dùng từ khóa "function": function tên_function body

Ví dụ sau định nghĩa function lần lượt theo 2 cách tương ứng trên:
hvn@archhvn: ~ () $ pika() { echo pikachu; }
hvn@archhvn: ~ () $ pika
pikachu
hvn@archhvn: ~ () $ function chipu { echo chukapi; }
hvn@archhvn: ~ () $ chipu
chukapi
Trong câu thần chú, phần định nghĩa function là:
() { :;}
Nó định nghĩa function theo cách 1, nhưng không đưa ra tên function.

2. semi-colon (dấu ;)
để viết nhiều câu lệnh trên cùng 1 dòng.

Có thể thấy 2 cách viết sau là tương đương:
hvn@archhvn: ~ () $ meomeo() {
> echo meomeomeo
> }
hvn@archhvn: ~ () $ meomeo
meomeomeo

hvn@archhvn: ~ () $ meomeo() { echo gaugaugau; }
hvn@archhvn: ~ () $ meomeo
gaugaugau
Và hoàn toàn có thể chạy một câu lệnh khác sau khi định nghĩa 1 function:
hvn@archhvn: ~ () $ fml() { echo FML; }; echo sau func
sau func
hvn@archhvn: ~ () $ fml
FML
3. env
đọc kỹ lại câu thần chú:
env x='() { :;}; echo vulnerable' bash -c "echo this is a test" 
nó tuân theo cú pháp của câu lệnh env:
hvn@archhvn: ~ () $ env --help
Usage: env [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]
ở đây, set cho NAME x bằng VALUE string '() { :;}; echo vulnerable'

rồi chạy COMMAND bash với các arg: -c "echo this is a test"

Lệnh env làm gì?
$ whatis env
env (1)              - run a program in a modified environment
nó chạy một chương trình trong một môi trường đã bị thay đổi. Nói cách khác, env export các variable vào "environment" của câu lệnh theo sau nó.
hvn@archhvn: ~ () $ unset var1 #unset trước đảm bảo var1 không được gán giá trị nào.
# Câu lệnh sau không export var1=5 vào môi trường của câu lệnh bash -c 'echo var1 la $var1", vì vậy nó không in ra gì cả cho giá trị var1:
hvn@archhvn: ~ () $ var1=5; bash -c 'echo var1 la so $var1'
var1 la so
# dưới đây là 3 cách để export var1=5 sang environment của câu lệnh theo sau nó.
hvn@archhvn: ~ () $ env var1=5; bash -c 'echo var1 la so $var1'
var1 la so 5
hvn@archhvn: ~ () $ var1=5 bash -c 'echo var1 la so $var1'
var1 la so 5 # chú ý ở trên không có dấu ;
hvn@archhvn: ~ () $ bash -c 'echo var1 la so $var1'
var1 la so
hvn@archhvn: ~ () $ export var1=5; bash -c 'echo var1 la so $var1'
var1 la so 5
hvn@archhvn: ~ () $ env | grep var1
var1=5
hvn@archhvn: ~ () $ bash -c 'echo var1 la so $var1'
var1 la so 5 
# đừng ngạc nhiên, vì export đã set biến var1 thành biến environment của bash shell hiện tại nên nó sẽ được kế thừa bởi mọi sub-process của process này (nói dễ hiểu là mọi câu lệnh chạy từ shell này). Để hủy tác dụng của nó, dùng ``unset var1``.

Như vậy, ta hòan toàn có thể sửa câu thần chú cho ngắn lại một chút (bỏ env):
$ x='() { :;}; echo vulnerable' bash -c "echo this is a test"
vulnerable
this is a test
Ta có thể định nghĩa một function không có tên, gán nó cho một biến rồi export sang environment của câu lệnh bash:
hvn@archhvn: ~ () $ anon_func='() { echo familug; }'
hvn@archhvn: ~ () $ echo $anon_func # nó chỉ là một string!
() { echo familug; }
hvn@archhvn: ~ () $ anon_func='() { echo familug; }' bash -c 'anon_func'
familug # khi export sang env của câu lệnh bash, nó là một function.

4. noop (no-op)
Trong bash, dấu : là operand (toán tử) no-operate. Tức nó không làm gì cả.

Tổng hợp:

hvn@archhvn: ~ () $ bash --version | grep bash
GNU bash, version 4.3.8(1)-release (x86_64-unknown-linux-gnu)
hvn@archhvn: ~ () $ env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
vulnerable
this is a test

Câu lệnh trên export biến x với giá trị là string '() { :;}; echo vulnerable' vào môi trường của câu lệnh bash tiếp theo.
Khi export, nó export biến x nhưng đồng thời cũng chạy câu lệnh sau phần string định nghĩa function.

Đến đây, bạn đã hiểu đọc code của hacker viết mệt mỏi như thế nào :-s

Làm sao để tấn công? và tại sao nó lại nguy hiểm?

Vì rất nhiều phần mềm trên UNIX-like OSes có sử dụng bash, và bash thì lại  được cài trên hầu hết các UNIX-like servers.

Một ví dụ tấn công điển hình ở đây với kịch bản là hacker đã chiếm được DHCP server, và sử dụng lỗi shellshock để tấn công các máy client.
Bạn sẽ làm gì nếu toàn quyền chiếm được một DHCP server? có thể bạn nghĩ ra nhiều cách, nhưng chẳng có cách nào kinh khủng bằng việc chiếm được quyền root của các máy client. Tức nắm toàn quyền điều khiển hệ điều hành *NIX của người dùng, muốn lấy password, muốn cài backdoor, virus... chỉ là chuyện vặt :3
https://www.trustedsec.com/september-2014/shellshock-dhcp-rce-proof-concept/

Giải thích ngắn:
Do dhclient (client của DHCP) chạy dhcp hook scripts ( thường tìm thấy ở /etc/dhclient-enter-hooks) với quyền root. Khi một DHCP client request xin cấp một IP, nó sẽ nhận được variable gửi xuống từ DHCP server rồi chạy (bash) hook script với variable đó, nếu đó là một bash variable sử dụng lỗi nói trên, phía DHCP client sẽ chạy câu lệnh sau phần định nghĩa function với quyền root ... và BOOM!

Với lỗi nãy, hacker có thể khai thác các service có sử dụng bash variable nhận được từ phía user để chiếm quyền root trên server tương ứng. Tham khảo các cách tấn công đã được thực hiện ở đây:

http://www.fireeye.com/blog/uncategorized/2014/09/shellshock-in-the-wild.html

Làm sao để fix lỗi này?
upgrade bash trên máy/server của bạn đến version mới nhất, hầu hết các OS đều đã đưa ra bản fix cho lỗi này.

Tham khảo:
http://en.wikipedia.org/wiki/Shellshock_%28software_bug%29

patch http://thread.gmane.org/gmane.comp.shells.bash.bugs/22190

man 1 bash
SHELL BUILTIN COMMANDS

       : [arguments]
              No effect; the command does nothing beyond expanding arguments and performing any specified redirections.  A zero exit code is returned.

http://unix.stackexchange.com/questions/157381/when-was-the-shellshock-cve-2014-6271-7169-bug-introduced-and-what-is-the-pat/157495#157495

2 comments:

  1. Lỗi này có từ tháng 5/8/1989, khi Brian Fox triển khai tính năng export function cho bash, và được release 1 tháng sau đó, 1/9/1989.

    Tham khảo: http://www.oldlinux.org/Linux.old/bin/old/bash-1.05/ChangeLog

    ReplyDelete
    Replies
    1. cám ơn bạn, mình đã sửa lại bài viết và trả lại cho lịch sử những gì của nó :D

      Delete