Đọc và xác nhận tập lệnh shell trước khi chuyển từ curl sang sh (curl -s [url] | sh)


11

Bất cứ khi nào tôi phải thực thi tập lệnh shell từ web curl -s [url] | sh, trước tiên tôi mở urltrong trình duyệt web của mình để đảm bảo tập lệnh không độc hại và an toàn để chạy.

Tôi nhớ đã nhìn thấy một thủ thuật dòng lệnh khiến cho có thể đọc tập lệnh từ dòng lệnh và sau đó xác nhận thực thi sau khi đọc tập lệnh. Nếu tôi nhớ lại một cách chính xác, nó trông giống như curl -s [url] | something...here | shvà không yêu cầu cài đặt phần mềm.

Có ai biết thủ thuật này không?

Câu trả lời:


5

Có một tiện ích moreutilsđược gọi là vipehiển thị stdin trong trình chỉnh sửa, nơi bạn có thể revew và sửa đổi tệp trước khi nó được chuyển sang thiết bị xuất chuẩn.

Nếu bạn không muốn cài đặt moreutils, bạn có thể thực hiện một cái gì đó tương tự như vậy:

file=$(mktemp); curl -s "$url" > $file; $EDITOR $file; sh $file; rm $file

mktempđang ở coreutilsvà rất có thể đã được cài đặt trên hệ thống của bạn.


2

Tôi không thể nghĩ ra một tiện ích duy nhất có thể làm những gì bạn mô tả, nhưng nó đủ dễ để biến nó thành một đoạn vỏ.

script=$(curl -s "$url")
printf "%s\nDo you want to run this script? [yN]" "$script"
read line
case $line in
  [Yy]|[Yy][Ee][Ss]) sh -c "$script";;
esac

Điều này giả sử tập lệnh là một tập tin văn bản. Null byte không được hỗ trợ: tùy thuộc vào shell, chúng có thể bị xóa hoặc chúng có thể khiến một dòng hoặc toàn bộ tệp bị cắt ngắn. Ngoài ra, tất cả các dòng mới ở cuối tập tin sẽ bị xóa (cấu trúc heredoc thêm một trở lại). Đây thường không phải là một vấn đề đối với một tập lệnh, nhưng nó có thể là, ví dụ, nếu tập lệnh kết thúc với một kho lưu trữ ở định dạng nhị phân mà nó trích xuất. Đây không phải là một cách phân phối tệp rất đáng tin cậy vì có nguy cơ đáng kể kịch bản nhị phân như vậy bị mã hóa sai tại một số điểm. Tuy nhiên, bạn có thể xử lý nó bằng cách viết tập lệnh vào một tệp tạm thời.

script_file=$(mktemp)
curl -s "$url" | tee "$script_file"
printf "Do you want to run this script? [yN]"
read line
case $line in
  [Yy]|[Yy][Ee][Ss]) sh "$script_file";;
esac
rm "$script_file"

$()nên được trích dẫn trên dòng đầu tiên. Ngoài ra, điều này sẽ loại bỏ các ký tự NUL trong đầu vào, có thể hiểu là có thể gây tử vong (ví dụ trong trường hợp tập lệnh tự giải nén).
l0b0

1
@ l0b0 Bạn không cần trích dẫn trong một bài tập, mặc dù nó được cho là phong cách tốt . Null byte thực sự bị mất, như là dòng mới cuối cùng; nếu bạn sẽ bao gồm một kho lưu trữ trong tập lệnh shell, tôi khuyên bạn nên sử dụng mã hóa văn bản, chẳng hạn như base64.
Gilles 'SO- ngừng trở nên xấu xa'

Tất cả các điểm hợp lệ, như thường lệ. +1
l0b0

@ l0b0 Về ý nghĩ thứ hai, trong khi nó hơi dễ bị rủi ro, đây là trường hợp sử dụng hợp lệ. Tôi đã cập nhật câu trả lời của mình. Tôi cũng đã sửa một lỗi trong câu trả lời ban đầu của mình, điều đó không cho phép tập lệnh sử dụng stdin của nó (vì tập lệnh được truyền vào stdin, không có lý do chính đáng).
Gilles 'SO- ngừng trở nên xấu xa'

1

Thật khó để tưởng tượng lý do tại sao bạn thậm chí muốn làm điều này, chứ đừng nói đến việc bạn sẽ tìm một nguồn (hoặc nguồn) tập lệnh để tải xuống và chạy như thế này thường xuyên đến mức nó cần một công cụ có mục đích đặc biệt.

Tại sao không tải xuống tập lệnh với curl(hoặc wgethoặc snarfbất cứ điều gì), kiểm tra và chỉnh sửa tập lệnh (đó là tập lệnh hiếm hoi không cần một số tùy chỉnh cho hệ thống cụ thể của bạn) và sau đó chạy nó - bằng cách làm cho nó có thể thực thi được bằng chmodhoặc bằng sh scriptname?


Tôi không muốn một công cụ đặc biệt. Tôi nhớ có một cách dễ dàng để làm điều này với các công cụ tiêu chuẩn.
Olivier Lalonde

2
Sẽ không khó để viết một tập lệnh shell nhỏ (có thể chỉ có 5 dòng hoặc hơn) để tải xuống một tập lệnh, trình bày nó để xem với lesshoặc một cái gì đó, sau đó hỏi bạn nếu bạn muốn chạy nó. Tôi không thể thấy rằng điều đó sẽ tốt hơn là chỉ tải xuống tập lệnh, xem tập lệnh và sau đó chạy nó nếu nó có vẻ ổn. IMO sẽ tệ hơn, nó sẽ không cung cấp bất kỳ lợi thế nào nhưng sẽ loại bỏ tính linh hoạt mà bạn có được khi chỉ làm việc trong vỏ của mình.
cas

0

Sử dụng dòng lệnh này:

curl URL | ( cat > /tmp/file; read REPLY; [[ ! $REPLY =~ ^[Yy]$ ]] && cat /tmp/file ) | sh

Bạn có thể sử dụng một hàm nhỏ cho điều đó:

curlsh()
{
    curl "$1" \
    | ( cat > /tmp/file;read REPLY; [[ ! $REPLY =~ ^[Yy]$ ]] && cat /tmp/file ) \
    | sh
}

Và hơn là sử dụng nó theo cách này:

curlsh http://site.in.net/path/to/script

0

Giả sử bạn đã biết -p (dấu nhắc) và tập lệnh không cần được thực thi với trình thông dịch, được chỉ định bởi shebang:

curl URL | tee /tmp/x && read -p "execute?" key ; test $key = y && sh /tmp/x
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.