มีปัญหาอะไร
-
ก่อนเช่นค่าสาธารณูปโภคจำนวนมากที่คุณจะมีปัญหากับชื่อไฟล์ที่เริ่มต้นด้วย ขณะที่อยู่ใน:
sh -c 'inline sh script here' other args
args อื่น ๆ ถูกส่งผ่านไปยังinline sh script
; ด้วยความperl
เสมอภาค
perl -e 'inline perl script here' other args
args อื่น ๆ จะถูกสแกนเพื่อหาตัวเลือกเพิ่มเติมเพื่อperlก่อนไม่ใช่สคริปต์แบบอินไลน์ ตัวอย่างเช่นหากมีไฟล์ที่เรียกว่า-eBEGIN{do something evil}
ในไดเรกทอรีปัจจุบัน
perl -ne 'inline perl script here;' *
(มีหรือไม่มี-n
) จะทำสิ่งที่ชั่วร้าย
เช่นเดียวกับยูทิลิตี้อื่น ๆ การทำงานเพื่อใช้ตัวทำเครื่องหมายจุดสิ้นสุด ( --
):
perl -ne 'inline perl script here;' -- *
แต่ถึงอย่างนั้นก็ยังคงเป็นอันตรายและที่ว่าลงไปที่<>
ผู้ประกอบการใช้โดย/-n
-p
ปัญหาอธิบายไว้ในperldoc perlop
เอกสารประกอบ
ตัวดำเนินการพิเศษนั้นจะใช้ในการอ่านหนึ่งบรรทัด (หนึ่งเรคคอร์ดบันทึกเป็นบรรทัดโดยค่าเริ่มต้น) ของอินพุตซึ่งอินพุตนั้นมาจากแต่ละอาร์กิวเมนต์ที่ส่งผ่าน@ARGV
มา
ใน:
perl -pe '' a b
-p
หมายถึงwhile (<>)
วนรอบรหัส (ที่นี่ว่างเปล่า)
<>
จะเปิดขึ้นก่อนa
อ่านระเบียนทีละบรรทัดจนกว่าไฟล์จะหมดแล้วเปิดb
...
ปัญหาคือการเปิดไฟล์มันใช้รูปแบบแรกที่ไม่ปลอดภัยของopen
:
open ARGV, "the file as provided"
ด้วยรูปแบบนั้นถ้าอาร์กิวเมนต์เป็น
"> afile"
มันจะเปิดขึ้นafile
ในโหมดการเขียน
"cmd|"
มันทำงานcmd
และอ่านผลลัพธ์
"|cmd"
cmd
คุณได้เปิดสตรีมสำหรับการเขียนการป้อนข้อมูลของ
ตัวอย่างเช่น:
perl -pe '' 'uname|'
ไม่ส่งออกเนื้อหาของไฟล์ที่เรียกว่าuname|
(ชื่อไฟล์ที่ถูกต้องสมบูรณ์ btw) แต่เป็นเอาต์พุตของuname
คำสั่ง
หากคุณกำลังทำงาน:
perl -ne 'something' -- *
และบางคนได้สร้างไฟล์ชื่อrm -rf "$HOME"|
(อีกครั้งชื่อไฟล์ที่ถูกต้องสมบูรณ์) ในไดเรกทอรีปัจจุบัน (เช่นเนื่องจากไดเรกทอรีนั้นครั้งหนึ่งเคยเขียนโดยผู้อื่นหรือคุณแยกไฟล์เก็บถาวรหลบหรือคุณเรียกใช้คำสั่งหลบหรือ ช่องโหว่อื่นในซอฟต์แวร์อื่นถูกโจมตี) จากนั้นคุณประสบปัญหาใหญ่ พื้นที่ที่สิ่งสำคัญที่ต้องระวังคือเครื่องมือประมวลผลไฟล์โดยอัตโนมัติในพื้นที่สาธารณะเช่น/tmp
(หรือเครื่องมือที่อาจถูกเรียกใช้โดยเครื่องมือดังกล่าว)
ไฟล์ที่เรียกว่า> foo
, foo|
, |foo
มีปัญหา แต่ในระดับที่น้อยกว่า< foo
และfoo
ด้วยอักขระระยะห่าง ASCII ชั้นนำหรือต่อท้าย (รวมถึงช่องว่าง, แท็บ, การขึ้นบรรทัดใหม่, CR ... ) รวมถึงนั่นหมายความว่าไฟล์เหล่านั้นจะไม่ได้รับการประมวลผล
นอกจากนี้ระวังว่าอักขระบางตัวในบางชุดตัวอักษรหลายไบต์ (เช่นǖ
ใน BIG5-HKSCS) สิ้นสุดใน 0x7c |
ไบต์การเข้ารหัสของ
$ printf ǖ | iconv -t BIG5-HKSCS | od -tx1 -tc
0000000 88 7c
210 |
0000002
ดังนั้นในโลแคลที่ใช้ชุดอักขระนั้น
perl -pe '' ./nǖ
จะพยายามเรียกใช้./n\x88
คำสั่งเนื่องจากperl
จะไม่พยายามตีความชื่อไฟล์นั้นในภาษาของผู้ใช้!
วิธีแก้ไข / หลีกเลี่ยง
AFAIK ไม่มีอะไรที่คุณสามารถทำได้เพื่อเปลี่ยนพฤติกรรมการเริ่มต้นที่ไม่ปลอดภัยของperl
ครั้งเดียวและสำหรับทั้งระบบ
ครั้งแรกปัญหาเกิดขึ้นเฉพาะกับตัวอักษรที่จุดเริ่มต้นและจุดสิ้นสุดของชื่อไฟล์ ดังนั้นในขณะที่perl -ne '' *
หรือperl -ne '' *.txt
มีปัญหา
perl -ne 'some code' ./*.txt
ไม่ได้เพราะข้อโต้แย้งทั้งหมดนี้เริ่มต้นด้วย./
และสิ้นสุดใน.txt
(เพื่อไม่-
, <
, >
, |
พื้นที่ ... ) โดยทั่วไปมันเป็นความคิดที่ดีที่จะคำนำหน้าglobs./
กับ นอกจากนี้ยังช่วยหลีกเลี่ยงปัญหาเกี่ยวกับไฟล์ที่เรียก-
หรือเริ่มต้นด้วย-
ยูทิลิตี้อื่น ๆ (และที่นี่หมายความว่าคุณไม่จำเป็นต้องทำเครื่องหมายสิ้นสุดตัวเลือก ( --
) อีกต่อไป)
การใช้-T
เพื่อเปิดtaint
โหมดช่วยในระดับหนึ่ง มันจะยกเลิกคำสั่งหากพบไฟล์ที่เป็นอันตรายดังกล่าว (สำหรับ>
และใน|
บางกรณีเท่านั้นไม่ใช่<
หรือเว้นวรรค)
มีประโยชน์เมื่อใช้คำสั่งแบบโต้ตอบตามที่แจ้งเตือนคุณว่ามีบางอย่างที่เกิดขึ้น ซึ่งอาจไม่เป็นที่น่าพอใจเมื่อทำการประมวลผลอัตโนมัติเนื่องจากนั่นหมายความว่าบางคนสามารถทำให้การประมวลผลนั้นล้มเหลวเพียงแค่สร้างไฟล์
หากคุณไม่ต้องการที่จะดำเนินการทุกไฟล์โดยไม่คำนึงถึงชื่อของพวกเขาคุณสามารถใช้โมดูลใน CPAN (น่าเสียดายที่มักจะไม่ได้ติดตั้งโดยค่าเริ่มต้น) นั่นเป็นโมดูลสั้น ๆ ที่ทำ:ARGV::readonly
perl
sub import{
# Tom Christiansen in Message-ID: <24692.1217339882@chthon>
# reccomends essentially the following:
for (@ARGV){
s/^(\s+)/.\/$1/; # leading whitespace preserved
s/^/< /; # force open for input
$_.=qq/\0/; # trailing whitespace preserved & pipes forbidden
};
};
โดยทั่วไปจะ sanitises @ ARGV โดยการเปิดตัวอย่างลงใน" foo|"
"< ./ foo|\0"
คุณสามารถทำเช่นเดียวกันในBEGIN
คำสั่งในperl -n/-p
คำสั่งของคุณ:
perl -pe 'BEGIN{$_.="\0" for @ARGV} your code here' ./*
ที่นี่เราลดความซับซ้อนของมันบนสมมติฐานที่./
ใช้
ผลข้างเคียงของ (และARGV::readonly
) ถึงแม้ว่า$ARGV
ในyour code here
นั้นแสดงให้เห็นว่าตัวละคร NUL ต่อท้าย
อัพเดท 2015-06-03
perl
v5.21.5 ขึ้นไปมี<<>>
โอเปอเรเตอร์ใหม่ที่ทำงานคล้ายกัน<>
ยกเว้นว่ามันจะไม่ทำการประมวลผลพิเศษนั้น อาร์กิวเมนต์จะถูกพิจารณาว่าเป็นชื่อไฟล์เท่านั้น ดังนั้นด้วยเวอร์ชันเหล่านี้คุณสามารถเขียน:
perl -e 'while(<<>>){ ...;}' -- *
(อย่าลืม--
หรือใช้งาน./*
) โดยไม่ต้องกลัวว่าจะเขียนทับไฟล์หรือรันคำสั่งที่ไม่คาดคิด
-n
/ -p
ยังคงใช้<>
รูปแบบอันตรายแม้ว่า และระวัง symlink ยังคงมีอยู่ดังนั้นจึงไม่ได้หมายความว่าปลอดภัยที่จะใช้ในไดเรกทอรีที่ไม่น่าเชื่อถือ