ปลอดภัยหรือไม่ที่จะใช้ `เสียงสะท้อน '


20

การใช้งานevalมักจะหมดกำลังใจเพราะจะทำให้สามารถเรียกใช้รหัสโดยอำเภอใจได้ อย่างไรก็ตามถ้าเราใช้eval echoดูเหมือนว่าส่วนที่เหลือของสตริงจะกลายเป็นข้อโต้แย้งechoดังนั้นมันควรจะปลอดภัย ฉันถูกต้องหรือไม่


1
ไม่ปลอดภัยเสมอไปที่คุณจะห่อระเบิดหรืออาร์เอ็ม -fR * ที่น่ารังเกียจ
μολὼν.λαβέ

อาจจะเป็นเพียงแค่การทดลองทางความคิด แต่ถ้าคุณเป็นจริงคิดว่าการทำเช่นนี้จะผ่านมันข้อโต้แย้งหลายเช่น-nคุณก็สามารถทำมันได้ด้วยตัวแปร unquoted เหมือนecho $argumentsหรือถ้าเป็นอาร์เรย์$arguments echo "${arguments[@]}"การใช้eval echoจะไม่มีจุดหมายแม้ว่าจะมีความปลอดภัย
JoL

คำตอบ:


40

counterexample:

DANGEROUS=">foo"
eval echo $DANGEROUS

อาร์กิวเมนต์โดยพลการechoสามารถทำสิ่งที่เลวร้ายยิ่งกว่าการสร้างไฟล์ชื่อ "foo"


6
นอกจากนี้: สำหรับคำสั่งโดยพลในสถานที่ของDANGEROUS="hello;ls" ls
Kusalananda

2
นอกจากนี้: DANGEROUS='$(ls)'(อาจต้องหลีกหนีมากขึ้น)
wizzwizz4

จะeval echo '"'"$DANGEROUS"'"'ทำงานอย่างไร ดูเหมือนว่าในgoo.gl/L2pPQP
Ismael Miguel

@IsmaelMiguel นั่นใช้ไม่ได้กับตัวอย่างของ wizzwizz, Cyker หรือ sorontar หรืออะไรก็ตามที่มีเครื่องหมายคำพูดคู่ในสตริง (เช่นDANGEROUS='">foo"')
Gordon Davisson

ยี้ ผมว่าผมพบว่าบางสิ่งบางอย่างที่ช่วยเล็ก ๆ น้อย ๆ
อิสมาเอลมิเกล

26

@ Celada ได้ให้คำตอบที่ยอดเยี่ยม เพื่อแสดงให้เห็นถึงevalความชั่วร้ายจริงๆนี่เป็นสิ่งที่เลวร้ายยิ่งกว่าการสร้างไฟล์ชื่อ "foo" :

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

และแน่นอนอาจมีบางสิ่งบางอย่างสามานย์มากกว่าสิ่งที่ชั่วร้ายมากขึ้นกว่าการสร้างไฟล์ที่เรียกว่า "ฟู"


8
+1 สำหรับการแสดงให้เห็นว่าการอ้างถึงตัวแปรเช่น"$THIS"แทนที่จะมีเพียงแค่มัน$THISไม่ได้ช่วยอะไรได้!
Celada

การส่งคำพูดคู่ aditional ดูเหมือนว่าจะช่วย eval echo '"'"$DANGEROUS"'"'สิ่งที่ชอบ ลองใช้กับgoo.gl/L2pPQP
Ismael Miguel

อันที่จริงตัวอย่างของคุณไม่ได้เลวร้ายไปกว่า>fooเพราะ "การสร้างไฟล์ชื่อ 'foo'" ไม่จำเป็นต้องทำทุก>fooอย่าง ความแตกต่างที่แท้จริงของคุณตัวอย่างเดียวคือมันไม่ทิ้งไฟล์เปล่าไว้ข้างหลัง เนื้อหายังคงหายไป
flarn2006

12

ไม่มันไม่ปลอดภัยเสมอไป Eval สามารถดำเนินการคำสั่งใด ๆ

คำสั่งที่ปลอดภัยเช่นนี้ (วันที่ไม่ได้ดำเนินการตามที่อยู่ในเครื่องหมายคำพูดเดียว):

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

กลายเป็นอันตรายหากใช้กับ eval:

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

แน่นอนวันที่อาจเป็นคำสั่งใด ๆ

วิธีหนึ่งในการปรับปรุงนี้คือการอ้างถึงข้อโต้แย้งเพิ่มเติมเพื่อประเมิน:

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

แต่มักจะยากที่จะพูดอย่างถูกต้องสองครั้ง

และมันก็เป็นไปไม่ได้ที่จะควบคุมการอ้างที่ถูกต้องหากผู้โจมตีภายนอกสามารถตั้งค่าได้เช่น:

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

1

ในขณะที่มันเป็นความจริงที่evalจะต้องเข้าหาด้วยความระมัดระวังeval echoอยู่เสมอการก่อสร้างนั้นไม่ไร้จุดหมายเสมอไปและสามารถใช้ได้อย่างปลอดภัย เมื่อเร็ว ๆ นี้ฉันต้องการให้มันได้รับการขยายการประเมินหลายครั้งตามที่ฉันต้องการ

bash ทำวงเล็บปีกกาหลายตัวจากซ้ายไปขวาดังนั้น

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

ขยายเป็น

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

แต่ฉันต้องการการขยายรั้งที่สองเสร็จก่อนยอมทำ

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

สิ่งที่ดีที่สุดที่ฉันสามารถทำได้คือ

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

งานนี้เพราะราคาเดียวปกป้องชุดแรกของการจัดฟันจากการขยายตัวระหว่างการแยกวิเคราะห์ของevalบรรทัดคำสั่งออกจากพวกเขาจะได้รับการขยายตัว subshell evalอุทธรณ์โดย

อาจมีรูปแบบที่น่าสนใจเกี่ยวกับการขยายรั้งแบบซ้อนที่อนุญาตให้สิ่งนี้เกิดขึ้นในขั้นตอนเดียว แต่ถ้ามีฉันแก่เกินไปและโง่เกินกว่าที่จะมองเห็น นอกจากนี้ยังมีกระสุนที่นอกเหนือจากbashที่อนุญาตให้ใช้วิธีที่เป็นระเบียบเพื่อบรรลุสิ่งนี้ แต่ในกรณีใด ๆ การใช้งานนี้evalมีความปลอดภัยเนื่องจากอาร์กิวเมนต์เป็นสตริงคงที่ทั้งหมดที่ไม่มีการขยายพารามิเตอร์


คุณไม่ต้องการ echo และการทดแทนคำสั่งที่นี่ (ซึ่งมีการพึ่งพา $ IFS) คุณสามารถทำได้eval xargs -I_ cat _/'{11..15}'/{8..5}.jpg
Stéphane Chazelas

ใช้งานได้ แต่มันทำให้กระบวนการ subshell เกิดจาก eval stick รอบ ๆ จนกว่ากระบวนการ xargs จะเสร็จสิ้น รุ่น eal echo ทำให้ subshell นั้นหายไปก่อนที่จะเริ่ม xargs นี่อาจจะเป็นสิ่งสำคัญเฉพาะกับคนอื่น ๆ ที่จะเป็นทางทวารหนักกับผมเกี่ยวกับสิ่งที่ปรากฏขึ้นในมุมมองต้นไม้ htop และตั้งบันทึก -x แม้ว่า :-)
flabdablet
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.