Có luôn an toàn khi sử dụng `eval echo` không?


20

Việc sử dụng evalthường không được khuyến khích vì nó cho phép thực thi mã tùy ý. Tuy nhiên, nếu chúng ta sử dụng eval echo, thì có vẻ như phần còn lại của chuỗi sẽ trở thành đối số echonên sẽ an toàn. Tôi có đúng về điều này?


1
phải lúc nào cũng an toàn, bạn có thể quấn một quả bom ngã ba hoặc rm khó chịu -fR *
μολὼν.λαβέ

Có thể đây chỉ là một thử nghiệm suy nghĩ, nhưng nếu bạn thực sự nghĩ đến việc thực hiện điều này để vượt qua nó nhiều đối số như thế -n, bạn có thể thực hiện nó với một biến không được trích dẫn như echo $argumentshoặc nếu $argumentslà một mảng echo "${arguments[@]}". Sử dụng eval echolà vô nghĩa ngay cả khi nó an toàn.
JoL

Câu trả lời:


40

Ví dụ:

DANGEROUS=">foo"
eval echo $DANGEROUS

Các đối số tùy ý echocó thể đã làm một cái gì đó bất chính hơn là tạo một tệp có tên là "foo".


6
Ngoài ra : DANGEROUS="hello;ls", cho các lệnh tùy ý thay cho ls.
Kusalananda

2
Ngoài ra: DANGEROUS='$(ls)'(có thể cần thoát nhiều hơn).
wizzwizz4

Sẽ eval echo '"'"$DANGEROUS"'"'làm việc? Có vẻ như trên goo.gl/L2pPQP
Ismael Miguel

@IsmaelMiguel Điều đó không hoạt động đối với các ví dụ của wizzwizz, Cyker hoặc sorontar hoặc cho bất cứ điều gì có dấu ngoặc kép trong chuỗi (ví dụ DANGEROUS='">foo"').
Gordon Davisson

Chết tiệt. Tôi mặc dù tôi đã tìm thấy một cái gì đó giúp một chút
Ismael Miguel

26

@Celada đã cung cấp một câu trả lời tuyệt vời. Để chứng minh evallà thực sự xấu xa, đây là một cái gì đó bất chính hơn là tạo một tệp có tên là "foo" :

DANGEROUS='$(rm foo)'
eval echo "$DANGEROUS"

Và tất nhiên có thể có thứ gì đó bất chính hơn thứ gì đó bất chính hơn là tạo một tệp có tên là "foo" .


8
+1 để chứng minh rằng trích dẫn biến như "$THIS"thay vì chỉ có nó như $THISkhông thậm chí không giúp ích!
Celada

Gửi một cặp trích dẫn có vẻ giúp đỡ. Một cái gì đó như eval echo '"'"$DANGEROUS"'"'. Dùng thử trên goo.gl/L2pPQP
Ismael Miguel

Trên thực tế, ví dụ của bạn không bất kỳ điều gì bất chính hơn >foo, bởi vì "tạo một tệp có tên 'foo'" không nhất thiết phải như >foovậy. Sự khác biệt thực sự duy nhất mà ví dụ của bạn có là nó không để lại một tập tin trống phía sau. Các nội dung vẫn còn.
flarn2006

12

Không, nó không phải lúc nào cũng an toàn. Một eval có thể thực hiện bất kỳ lệnh nào.

Một lệnh an toàn, như thế này (ngày không được thực thi vì nó nằm trong dấu ngoặc đơn):

$ echo '$(date)'
$(date)

Trở nên nguy hiểm nếu được sử dụng với eval:

$ eval echo '$(date)'
Sat Dec 24 22:55:55 UTC 2016

Tất nhiên, ngày có thể là bất kỳ lệnh nào .

Một cách để cải thiện điều này là trích dẫn thêm các đối số để đánh giá:

$ eval echo '\$(date)'
$(date)

Nhưng thường rất khó để trích dẫn chính xác hai lần một biểu thức.

Và không thể kiểm soát trích dẫn chính xác nếu biểu thức có thể được đặt bởi kẻ tấn công bên ngoài, như:

$ var='$(date);echo Hello!'
$ eval echo "$var"
Sat Dec 24 23:01:48 UTC 2016
Hello!

1

Mặc dù đúng là evalluôn cần phải được tiếp cận một cách thận trọng, việc eval echoxây dựng không phải lúc nào cũng vô nghĩa và có thể được sử dụng một cách an toàn. Gần đây tôi cần nó để có được nhiều lần mở rộng niềng răng được đánh giá theo thứ tự tôi cần chúng thực hiện.

bash không mở rộng nhiều cú đúp từ trái sang phải, vì vậy

xargs -I_ cat _/{11..15}/{8..5}.jpg

mở rộng đến

xargs -I_ cat _/11/8.jpg _/11/7.jpg _/11/6.jpg _/11/5.jpg _/12/8.jpg _/12/7.jpg _/12/6.jpg _/12/5.jpg _/13/8.jpg _/13/7.jpg _/13/6.jpg _/13/5.jpg _/14/8.jpg _/14/7.jpg _/14/6.jpg _/14/5.jpg _/15/8.jpg _/15/7.jpg _/15/6.jpg _/15/5.jpg

nhưng tôi cần mở rộng cú đúp thứ hai được thực hiện trước, mang lại

xargs -I_ cat _/11/8.jpg _/12/8.jpg _/13/8.jpg _/14/8.jpg _/15/8.jpg _/11/7.jpg _/12/7.jpg _/13/7.jpg _/14/7.jpg _/15/7.jpg _/11/6.jpg _/12/6.jpg _/13/6.jpg _/14/6.jpg _/15/6.jpg _/11/5.jpg _/12/5.jpg _/13/5.jpg _/14/5.jpg _/15/5.jpg

Điều tốt nhất tôi có thể nghĩ ra để làm điều đó là

xargs -I_ cat $(eval echo _/'{11..15}'/{8..5}.jpg)

Điều này hoạt động vì các dấu ngoặc đơn bảo vệ bộ dấu ngoặc đầu tiên khỏi sự mở rộng trong quá trình phân tích cú pháp của evaldòng lệnh, khiến chúng được mở rộng bởi lớp con được gọi bởi eval.

Có thể có một số kế hoạch xảo quyệt liên quan đến việc mở rộng niềng răng lồng nhau cho phép điều này xảy ra trong một bước, nhưng nếu có thì tôi quá già và ngu ngốc khi nhìn thấy nó. Ngoài ra còn có các loại vỏ khác bashcho phép các cách thức gọn gàng hơn để đạt được loại điều này. Nhưng trong mọi trường hợp, việc sử dụng evalnày là an toàn vì các đối số của nó là tất cả các chuỗi cố định không chứa mở rộng tham số.


Bạn không cần echo và thay thế lệnh ở đây (cũng có sự phụ thuộc vào $ IFS). Bạn có thể làmeval xargs -I_ cat _/'{11..15}'/{8..5}.jpg
Stéphane Chazelas

Điều đó cũng hoạt động, nhưng nó làm cho quá trình subshell được sinh ra bởi eval stick xung quanh cho đến khi quá trình xargs kết thúc; phiên bản echo eval làm cho subshell biến mất trước khi xargs thậm chí được bắt đầu. Điều này có lẽ chỉ quan trọng đối với những người khác cũng như tôi về những gì hiển thị trong chế độ xem trên cây htop và thiết lập nhật ký -x :-)
flabdablet
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.