GNU Bash xuất các hàm shell trong các biến môi trường bao gồm các định nghĩa hàm:
$ function foo { echo bar; }
$ export -f foo
$ env | grep -A1 foo
foo=() { echo bar
}
Khi một cá thể Bash mới được sinh ra, nó sẽ tìm các biến môi trường khớp với một mẫu nhất định. Nội dung của các biến đó được tự động nhập dưới dạng hàm shell. Như Stéphane Chazelas giải thích , do tính năng này được giới thiệu trong Bash 1.03, việc nhập hàm được thực hiện đơn giản bằng cách thay thế =
mục nhập tương ứng trong mảng biến môi trường và diễn giải kết quả dưới dạng định nghĩa hàm. Trước bản vá đã sửa CVE-2014-6271 , biến môi trường đã được diễn giải toàn bộ, bao gồm bất kỳ lệnh nào tuân theo thân hàm thực tế. Bản vá giới thiệu hai chế độ đặc biệt cho parse_and_execute()
chức năng SEVAL_FUNCDEF
vàSEVAL_ONECMD
. Khi hàm được gọi với SEVAL_FUNCDEF
, nó có nhiệm vụ ngăn chặn việc giải thích các lệnh khác với định nghĩa hàm. Các SEVAL_ONECMD
lá cờ có nghĩa vụ phải ngăn chặn chức năng từ việc đánh giá hơn một lệnh duy nhất.
Biến môi trường được chế tạo đặc biệt của Tavis Ormandy làm một cái gì đó khác biệt tinh tế. Nó được thiết kế để gây nhầm lẫn cho trình phân tích cú pháp và làm hỏng bộ đệm được sử dụng để lưu trữ các lệnh được ước tính. Phần còn lại của biến môi trường trong bộ đệm thay đổi cách hiểu của lệnh tiếp theo . Vấn đề liên quan này đã nhận được mã định danh CVE CVE-2014-7169 .
Các thành phần của định nghĩa biến môi trường X='() { (a)=>\'
là:
() {
được trình phân tích cú pháp giải thích là khởi đầu của một định nghĩa hàm
(a)=
được dự định để gây nhầm lẫn cho trình phân tích cú pháp và khiến nó để lại tàn dư của biến môi trường trong bộ đệm
>\
là tải trọng thực tế còn lại trong bộ đệm
Mục đích của tải trọng là thay đổi cách hiểu của lệnh được thực thi trong lớp con được gọi bởi sh -c "echo date";
. Điều này tất nhiên giả định rằng đó /bin/sh
là một liên kết tượng trưng đến bash
. Khi chuỗi lệnh được chỉ định làm toán hạng -c
được đặt trong bộ đệm, nội dung của bộ đệm là:
>\[0xA]echo date
Đây [0xA]
là một ký tự dòng mới ASCII, thường hoạt động như một dấu phân cách lệnh, nhưng hiện được thoát khỏi \
tải trọng. Kết quả là, nội dung của bộ đệm được hiểu là
>echo date
Vì Bash cho phép các toán tử chuyển hướng đi trước các lệnh , nên điều này tương đương với
date > echo
Điều này chỉ đơn giản là làm cho date
lệnh được thực thi với đầu ra tiêu chuẩn của nó được chuyển hướng đến một tệp được gọi echo
. Phần còn lại cat echo
không phải là một phần của khai thác, nó chỉ chứng minh rằng bây giờ một tệp echo
có tên là chứa đầu ra của date
tồn tại.
Về lý do tại sao chuỗi (a)=
nhầm lẫn trình phân tích cú pháp trong trường hợp này, dường như nó có liên quan đến nó xuất hiện dưới dạng một định nghĩa hàm lồng nhau (không đúng định dạng). Các biến thể đơn giản hóa của khai thác thể hiện rõ điều này hơn:
$ X='() { function a a>\' bash -c echo
$ ls echo
echo