ฉันจะบังคับให้ใช้คำสั่งในตัวอย่างชัดเจนและปลอดภัยได้อย่างไร


19

มีเป็นคำถามที่คล้ายกันที่เกี่ยวข้องกับ 'ตัด' สถานการณ์ที่คุณต้องการแทนที่เช่นcdมีคำสั่งที่เรียกใช้ cdbuiltin

อย่างไรก็ตามในแง่ของ shellshock et al และเมื่อรู้ว่าทุบตีนำเข้าฟังก์ชั่นจากสภาพแวดล้อมฉันได้ทำการทดสอบสองสามครั้งและฉันไม่สามารถหาวิธีโทรหา builtin ได้อย่างปลอดภัยcdจากสคริปต์ของฉัน

พิจารณาสิ่งนี้

cd() { echo "muahaha"; }
export -f cd

สคริปต์ใด ๆ ที่ถูกเรียกใช้ในสภาพแวดล้อมนี้cdจะใช้งานไม่ได้(พิจารณาถึงผลกระทบของสิ่งที่ชอบcd dir && rm -rf .)

มีคำสั่งให้ตรวจสอบประเภทของคำสั่ง (เรียกว่าสะดวกtype) และคำสั่งสำหรับการดำเนินการรุ่น builtin แทนที่จะเป็นฟังก์ชั่น ( builtinและcommand) แต่แท้จริงและดูเถิดสิ่งเหล่านี้สามารถถูกแทนที่ด้วยการใช้ฟังก์ชั่นเช่นกัน

builtin() { "$@"; }
command() { "$@"; }
type() { echo "$1 is a shell builtin"; }

จะให้ผลดังนี้:

$ type cd
cd is a shell builtin
$ cd x
muahaha
$ builtin cd x
muahaha
$ command cd x
muahaha

มีวิธีใดที่จะบังคับให้ทุบตีอย่างปลอดภัยเพื่อใช้คำสั่ง builtin หรืออย่างน้อยตรวจพบว่าคำสั่งไม่ใช่ builtin โดยไม่ต้องล้างสภาพแวดล้อมทั้งหมดหรือไม่

ฉันรู้ว่ามีใครบางคนควบคุมสภาพแวดล้อมของคุณคุณอาจเมาอยู่ดี แต่อย่างน้อยสำหรับนามแฝงที่คุณมีตัวเลือกที่จะไม่เรียกนามแฝงด้วยการแทรก a \ก่อนหน้านี้


คุณสามารถเรียกใช้สคริปต์ของคุณโดยใช้envคำสั่งมาก่อนเช่นนี้:env -i <SCRIPT.sh>
Arkadiusz Drabczyk

เฉพาะในกรณีที่envไม่ได้นิยามใหม่เป็นฟังก์ชันด้วย มันน่ากลัวมาก ฉันคิดว่าตัวละครพิเศษจะช่วยได้ - การโทรด้วยเส้นทางแบบเต็มซึ่งรวมถึงการ/ใช้.กับแหล่งที่มาและอื่น ๆ แต่ยังสามารถใช้สำหรับชื่อฟังก์ชั่น! คุณสามารถกำหนดฟังก์ชันที่คุณต้องการได้ใหม่ แต่ก็ยากที่จะกลับไปเรียกคำสั่งเดิม
orion

1
จริง แต่ถ้าคุณจะเรียกใช้สคริปต์ใด ๆ บนเครื่องที่ถูกบุกรุกคุณก็จะเมาอยู่ดี อีกทางหนึ่งเขียนสคริปต์ของคุณ#/bin/shหากนี่ไม่ใช่เชลล์เชิงโต้ตอบเริ่มต้น
Arkadiusz Drabczyk

คำตอบ:


16

โอลิเวีย D เป็นเกือบถูกต้อง แต่คุณต้องตั้งค่าก่อนที่จะใช้POSIXLY_CORRECT=1 unsetPOSIX มีความคิดของพิเศษ Built-inและทุบตีสนับสนุนนี้ unsetเป็นหนึ่งในตัว ค้นหาSPECIAL_BUILTINในbuiltins/*.cแหล่งทุบตีสำหรับรายการนี้ยังรวมถึงset, unset, export, และevalsource

$ unset() { echo muahaha-unset; }
$ unset unset
muahaha-unset
$ POSIXLY_CORRECT=1
$ unset unset

โกงunsetได้รับตอนนี้ลบออกจากสภาพแวดล้อมที่ถ้าคุณล้างค่าcommand, type, builtinแล้วคุณควรจะสามารถที่จะดำเนินการต่อไป แต่unset POSIXLY_CORRECTถ้าคุณจะอาศัยอยู่กับพฤติกรรมที่ไม่ POSIX หรือคุณลักษณะขั้นสูงทุบตี

นี้ไม่ได้นามแฝงอยู่แม้ว่าดังนั้นคุณต้องใช้\unsetเพื่อให้แน่ใจว่าการทำงานในเปลือกโต้ตอบ (หรือเสมอในกรณีที่expand_aliasesมีผล)

สำหรับความหวาดระแวงนี้ควรแก้ไขทุกอย่างฉันคิดว่า:

POSIXLY_CORRECT=1
\unset -f help read unset
\unset POSIXLY_CORRECT
re='^([a-z:.\[]+):' # =~ is troublesome to escape
while \read cmd; do 
    [[ "$cmd" =~ $re ]] && \unset -f ${BASH_REMATCH[1]}; 
done < <( \help -s "*" )

( while, do, doneและ[[จะถูกสงวนคำพูดและไม่จำเป็นต้องมีข้อควรระวัง.) หมายเหตุ: เราจะใช้unset -fเพื่อให้แน่ใจว่าฟังก์ชั่นล้างแม้ว่าตัวแปรและฟังก์ชั่นแสดงความ namespace เดียวกันก็เป็นไปได้ที่ทั้งสองจะมีชีวิตอยู่ไปพร้อม ๆ กัน (ขอบคุณ Etan Reisner) ซึ่งในกรณีนี้ การตั้งค่าไอเอ็นจีสองครั้งก็จะทำเคล็ดลับเช่นกัน คุณสามารถทำเครื่องหมายฟังก์ชั่นอ่านได้อย่างเดียวทุบตีไม่ได้ป้องกันไม่ให้คุณ unsetting ฟังก์ชั่นอ่านได้อย่างเดียวและรวมถึงการทุบตี-4.2 ทุบตี-4.3 จะป้องกันไม่ให้คุณ แต่ก็ยังได้รับเกียรตินิยม builtins พิเศษเมื่อPOSIXLY_CORRECTเป็นชุด

การอ่านอย่างเดียวPOSIXLY_CORRECTไม่ใช่ปัญหาจริงนี่ไม่ใช่บูลีนหรือตั้งค่าสถานะว่าเปิดใช้งานโหมด POSIX ดังนั้นถ้ามันมีอยู่ในรูปแบบอ่านได้อย่างเดียวคุณสามารถพึ่งพาฟีเจอร์ POSIX แม้ว่าค่าจะว่างเปล่าหรือ 0 คุณจะต้อง ฟังก์ชั่นที่ไม่มีปัญหาตั้งค่าวิธีที่แตกต่างจากด้านบนอาจจะมีการตัดและวาง:

\help -s "*" | while IFS=": " read cmd junk; do echo \\unset -f $cmd; done

(และไม่สนใจข้อผิดพลาดใด ๆ ) หรือมีส่วนร่วมในการอื่น ๆ บางscriptobatics


หมายเหตุอื่น ๆ :

  • functionเป็นคำที่สงวนไว้สามารถใช้นามแฝง แต่ไม่สามารถแทนที่ด้วยฟังก์ชันได้ (นามแฝงfunctionเป็นปัญหาอย่างอ่อนโยนเนื่องจาก\function ไม่เป็นที่ยอมรับว่าเป็นวิธีการเลี่ยงผ่าน)
  • [[, ]]เป็นคำสงวนพวกเขาสามารถ aliased (ซึ่งจะถูกละเว้น) แต่ไม่แทนที่ด้วยฟังก์ชั่น ( แต่ฟังก์ชั่นสามารถตั้งชื่อให้)
  • (( ไม่ใช่ชื่อที่ถูกต้องสำหรับฟังก์ชั่นหรือนามแฝง

น่าสนใจขอบคุณ! ฉันดูเหมือนแปลกสำหรับฉันที่ทุบตีจะเริ่มต้นที่จะไม่ปกป้องunsetและอัลจากการถูกเขียนทับ
falstro

สิ่งนี้ต้องการการ-fโต้แย้งunsetหรือไม่? มิฉะนั้นถ้าทั้งสองตัวแปรและฟังก์ชั่นที่มีชื่อเดียวกันกับ builtin จะถูกกำหนดแล้วunsetจะเลือกตัวแปรที่จะยกเลิกการตั้งค่าก่อน นอกจากนี้ล้มเหลวถ้ามีฟังก์ชั่นการปิดบังการตั้งค่าreadonlyไม่ได้หรือไม่ (แม้ว่าจะตรวจจับได้และอาจทำให้เกิดข้อผิดพลาดร้ายแรงได้) นอกจากนี้ยังมีข้อผิดพลาดใน[ตัว
Etan Reisner

1
ฉันไม่คิดว่า\unset -f unsetสมเหตุสมผลเพราะมันจะทำในวงอ่าน ถ้าunsetเป็นฟังก์ชั่น\unsetปกติแล้วคุณจะแก้ไขมันแทนที่จะเป็นบิวอิน แต่คุณสามารถใช้งาน\unsetได้อย่างปลอดภัยตราบใดที่โหมด POSIX มีผล อย่างชัดเจนเรียก\unset -fบน[, .และ:อาจจะมีความคิดที่ดี แต่เป็นไม่รวม regex ของพวกเขา ฉันจะเพิ่ม-fไปยัง\unsetในวงและจะ\unset POSIXLY_CORRECTหลังจากวงแทนก่อน \unalias -a(หลัง\unset -f unalias) อนุญาตให้ผู้อื่นนำการหลบหนีอย่างปลอดภัยตามคำสั่งที่ตามมา
Adrian Günter

1
@ AdrianGünterลอง: [[ ${POSIXLY_CORRECT?non-POSIX mode shell is untrusted}x ]]นี่จะทำให้สคริปต์ไม่โต้ตอบเพื่อออกพร้อมกับข้อผิดพลาดที่ระบุหากตัวแปรไม่ได้ตั้งค่าหรือดำเนินการต่อหากมีการตั้งค่า (ว่างเปล่าหรือค่าใด ๆ )
mr.spuratic

1
"คุณต้องใช้\unset" ... ควรสังเกตว่าการอ้างถึงอักขระใด ๆ จะทำงานเพื่อหลีกเลี่ยงการขยายนามแฝงไม่ใช่เพียงแค่ชื่อแรก un"se"tจะทำงานได้ดีเช่นกันอ่านน้อยลง "คำแรกของแต่ละคำสั่งง่าย ๆ ถ้าไม่ได้ใส่คำพูดจะถูกตรวจสอบเพื่อดูว่ามันมีนามแฝงอยู่หรือไม่" - Bash Ref
Robin A. Meade

6

ฉันรู้ว่ามีคนควบคุมสภาพแวดล้อมของคุณคุณอาจเมาอยู่ดี

ใช่แล้ว หากคุณเรียกใช้สคริปต์ในสภาพแวดล้อมที่ไม่รู้จักสิ่งต่าง ๆ ทุกอย่างอาจผิดพลาดได้เริ่มต้นด้วยการLD_PRELOADทำให้กระบวนการเชลล์รันโค้ดโดยพลการก่อนที่สคริปต์จะอ่านสคริปต์ของคุณ การพยายามป้องกันสภาพแวดล้อมที่เป็นมิตรจากภายในสคริปต์นั้นไร้ประโยชน์

Sudo ทำให้สภาพแวดล้อมถูกทำลายโดยการลบสิ่งที่ดูเหมือนว่านิยามฟังก์ชันทุบตีมานานกว่าทศวรรษ ตั้งแต่Shellshockสภาพแวดล้อมอื่น ๆ ที่ใช้เชลล์สคริปต์ในสภาพแวดล้อมที่ไม่น่าเชื่อถือได้ตามหลังชุดสูท

คุณไม่สามารถเรียกใช้สคริปต์อย่างปลอดภัยในสภาพแวดล้อมที่ได้รับการตั้งค่าโดยเอนทิตีที่ไม่น่าเชื่อถือ ดังนั้นการกังวลเกี่ยวกับนิยามฟังก์ชั่นจึงไม่ได้ผล ฆ่าเชื้อสภาพแวดล้อมของคุณและในการทำเช่นนั้นตัวแปรที่ทุบตีจะตีความว่าเป็นคำจำกัดความของฟังก์ชั่น


1
ฉันไม่เห็นด้วยกับสิ่งนี้อย่างสิ้นเชิง ความปลอดภัยไม่ได้เป็นข้อเสนอไบนารีที่อยู่กึ่งกลางรอบ "sanitized" หรือ "unsanitized" มันเกี่ยวกับการขจัดโอกาสในการหาประโยชน์ และน่าเสียดายที่ความซับซ้อนของระบบที่ทันสมัยหมายถึงมีโอกาสในการหาประโยชน์จำนวนมากที่จำเป็นต้องล็อคไว้อย่างถูกต้อง โอกาสการแสวงหาผลประโยชน์จำนวนมากมุ่งเน้นไปที่การโจมตีต้นน้ำที่ไม่มีอันตรายเช่นการเปลี่ยนตัวแปร PATH การกำหนดฟังก์ชั่นที่มีอยู่ในเครื่อง ฯลฯ ให้โอกาสคนเดียวหรือโปรแกรมในการทำเช่นนั้นและทั้งระบบของคุณมีความเสี่ยง
Dejay Clayton

@DejayClayton ฉันเห็นด้วยอย่างยิ่งกับความคิดเห็นของคุณยกเว้นประโยคแรกเพราะฉันไม่เห็นว่ามันขัดแย้งกับคำตอบของฉันในทางใด การลบโอกาสในการหาประโยชน์ช่วย แต่ไม่สามารถลบได้เพียงครึ่งเดียวเท่านั้นที่มีการบิดเล็กน้อยในการโจมตีทำให้สามารถทำงานต่อไปได้
Gilles 'หยุดชั่วร้าย'

ประเด็นของฉันคือคุณไม่สามารถเพียงแค่ "ทำความสะอาดสภาพแวดล้อมของคุณ" แล้วหยุดกังวลเกี่ยวกับเวกเตอร์การโจมตีต่างๆ บางครั้งก็จ่ายเพื่อ "ป้องกันสภาพแวดล้อมที่เป็นมิตรจากภายในสคริปต์" แม้ว่าคุณจะแก้ปัญหา "นิยามฟังก์ชั่น" คุณยังต้องกังวลเกี่ยวกับสิ่งต่าง ๆ เช่นการมี PATH ที่ใครบางคนสามารถใส่สคริปต์ที่กำหนดเองชื่อ "cat" หรือ "ls" ลงในไดเรกทอรีและจากนั้นสคริปต์ใด ๆ ที่เรียก "cat "หรือ" ls "แทน" / bin / cat "และ" / bin / ls "กำลังเรียกใช้ช่องโหว่
Dejay Clayton

@DejayClayton เห็นได้ชัดว่าการฆ่าเชื้อในสภาพแวดล้อมนั้นไม่ได้ช่วยในเรื่องของเวคเตอร์การโจมตีที่ไม่เกี่ยวข้องกับสภาพแวดล้อม (ตัวอย่างเช่นสคริปต์ที่โทร/bin/catใน chroot อาจเรียกอะไรก็ได้) การฆ่าเชื้อโรคในสภาพแวดล้อมนั้นทำให้คุณมีสติPATH(สมมติว่าคุณทำถูกต้องแน่นอน) ฉันยังไม่เห็นจุดของคุณ
Gilles 'หยุดความชั่วร้าย'

พิจารณาว่า PATH เป็นหนึ่งในโอกาสที่ใหญ่ที่สุดสำหรับการหาประโยชน์และแนวทางปฏิบัติที่น่าสงสัยจำนวนมากได้รับการจัดทำเป็นเอกสารตามคำแนะนำที่แนะนำแม้ในบล็อกความปลอดภัยและเมื่อพิจารณาว่าบางครั้งแอปพลิเคชันที่ติดตั้ง การป้องกันโค้ดในสคริปต์จะเป็นความคิดที่ไม่ดี สิ่งที่คุณพิจารณาว่า PATH มีเหตุผลในความเป็นจริงอาจเสี่ยงต่อการหาประโยชน์ที่คุณไม่ได้พบ
Dejay Clayton

1

คุณสามารถใช้unset -fเพื่อลบฟังก์ชั่นภายในคำสั่งและประเภท


2
ขอโทษที่unset() { true; }ดูแล
falstro

1
ประณาม! และรายการฟังก์ชั่นที่กำหนดยังต้องอาศัย builtin ฉันยอมแพ้!
odc
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.