แนวทางปฏิบัติที่ดีที่สุดสำหรับการเรียกใช้โค้ดที่ไม่น่าเชื่อถือ


31

ฉันมีโครงการที่ฉันต้องการอนุญาตให้ผู้ใช้เรียกใช้รหัสหลามที่ไม่น่าเชื่อถือ ( เช่นนี้ ) กับเซิร์ฟเวอร์ของฉัน ฉันค่อนข้างใหม่สำหรับงูใหญ่และฉันต้องการหลีกเลี่ยงการทำผิดพลาดใด ๆ ที่แนะนำช่องโหว่ด้านความปลอดภัยหรือช่องโหว่อื่น ๆ เข้าสู่ระบบ มีแนวทางปฏิบัติที่ดีที่สุดให้อ่านแนะนำหรือตัวชี้อื่น ๆ ที่คุณสามารถให้บริการของฉันใช้งานได้ แต่ไม่สามารถใช้งานได้?

นี่คือสิ่งที่ฉันพิจารณาแล้ว:

  • ลบออก__builtins__จากบริบทที่จะห้ามการใช้งานของแพคเกจที่อาจเป็นอันตรายเช่นexec osผู้ใช้จะสามารถใช้แพ็คเกจที่ฉันให้ไว้ได้เท่านั้น
  • ใช้เธรดเพื่อบังคับใช้การหมดเวลาที่เหมาะสม
  • ฉันต้องการ จำกัด จำนวนหน่วยความจำทั้งหมดที่สามารถจัดสรรได้ภายในexecบริบท แต่ฉันไม่แน่ใจว่าเป็นไปได้หรือไม่

มีทางเลือกตรงไปตรงมาexecแต่ฉันไม่แน่ใจว่าสิ่งเหล่านี้จะเป็นประโยชน์ที่นี่:

  • การใช้ast.NodeVisitorเพื่อตรวจจับการพยายามเข้าถึงวัตถุที่ไม่ปลอดภัย แต่ฉันควรห้ามวัตถุอะไร
  • ค้นหาเครื่องหมายขีดล่างคู่ใด ๆ ในอินพุต (สง่างามน้อยกว่าตัวเลือกด้านบน)
  • การใช้PyPyหรือสิ่งที่คล้ายกับรหัส sandbox

หมายเหตุ:ฉันทราบว่ามีล่ามที่ใช้ JavaScript อย่างน้อยหนึ่งตัว ที่จะไม่ทำงานในสถานการณ์ของฉัน


8
บางจุดเริ่มต้นสำหรับการศึกษา: blog.delroth.net/2013/03/… , nedbatchelder.com/blog/201206/eval_really_is_dangerous.html , nedbatchelder.com/blog/201302/…และnedbatchelder.com/blog/201302/finding_python_3_builtins htmlเกี่ยวกับการแยกออกจาก sandbox
Martijn Pieters

3
@MartijnPieters: ยอดเยี่ยม น่าจะเป็นคำตอบที่ดีถ้าคุณสรุปแต่ละข้อ
Robert Harvey

พิจารณาด้วย: ทิ้งขยะไว้บนดิสก์, เครือข่าย (อย่าปล่อยให้พวกเขาส่งสแปมหรืออะไรก็ตาม), การอนุญาตไปยังไฟล์อื่น (อ่านไฟล์ของคุณ) แม้จะดีดออกมาในขณะที่วงสามารถทำลายกลไกซีดี ... ฉันจะไป virtualization (คุกหรือ kvm บางชื่อคุณ) หรืออย่างน้อยผู้ใช้ที่ไม่มีสิทธิ์เกือบ ตั้งค่าจำนวนหน่วยความจำที่ดีและเหมาะสมเพื่อใช้ประโยชน์จากโปรแกรมของคุณเอง
kyticka


1
ลองใช้PyPy :> Sandboxing: PyPy ให้ความสามารถในการเรียกใช้รหัสที่ไม่น่าเชื่อถือในวิธีที่ปลอดภัยอย่างเต็มที่
Vorac

คำตอบ:


28

งูหลาม sandboxing เป็นเรื่องยาก Python เป็นวิปัสสนาโดยเนื้อแท้ในหลายระดับ

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

นี่คือตัวอย่างของการค้นหาวิธีที่สร้างสรรค์ในการทำลายกล่องทราย Python:

แนวคิดพื้นฐานอยู่เสมอเพื่อหาวิธีในการสร้างประเภทหลามฐาน; ฟังก์ชั่นและคลาสและแยกออกจากเชลล์โดยการขอรับ Python interpreter เพื่อรัน bytecode (ไม่ จำกัด !)

เหมือนกันและอื่น ๆ ที่ใช้กับexecคำสั่ง ( exec()ฟังก์ชันใน Python 3)

ดังนั้นคุณต้องการ:

  • ควบคุมการคอมไพล์ไบต์ของรหัสไพ ธ อนอย่างน้อยที่สุดหรืออย่างน้อยโพสต์โปรเซส bytecode เพื่อลบการเข้าถึงชื่อที่ขึ้นต้นด้วยขีดล่าง

    สิ่งนี้ต้องการความรู้ที่ลึกซึ้งว่า Python interpreter ทำงานอย่างไรและโครงสร้างของ Python bytecode เป็นอย่างไร รหัสวัตถุซ้อนกัน; bytecode ของโมดูลครอบคลุมเฉพาะข้อความระดับบนสุดเท่านั้นแต่ละฟังก์ชันและคลาสประกอบด้วยลำดับ bytecode ของตัวเองรวมทั้งข้อมูลเมตาที่มีออบเจ็กต์ bytecode อื่น ๆสำหรับฟังก์ชั่นและคลาสที่ซ้อนกัน

  • คุณจำเป็นต้องมีรายการที่อนุญาตพิเศษที่สามารถใช้ได้ รอบคอบ

    โมดูลหลามมีการอ้างอิงถึงโมดูลอื่น หากคุณนำเข้าosมีชื่อท้องถิ่นosในโมดูลเนมสเปซของคุณที่อ้างถึงosโมดูล สิ่งนี้สามารถนำผู้โจมตีที่มุ่งมั่นไปยังโมดูลที่สามารถช่วยให้พวกเขาหลุดพ้นจากกล่องทราย pickleโมดูลเช่นช่วยให้คุณโหลดวัตถุโค้ดตัวอย่างดังนั้นหากใด ๆเส้นทางผ่านโมดูลอนุญาตพิเศษนำไปสู่pickleโมดูลคุณมีปัญหายังคง

  • คุณต้อง จำกัด โควต้าเวลาอย่างเคร่งครัด แม้แต่โค้ดที่ neutered ที่สุดก็ยังสามารถพยายามที่จะทำงานได้ตลอดไปโดยมัดทรัพยากรของคุณ

ลองดูที่RestrictedPythonซึ่งพยายามที่จะให้การควบคุม bytecode ที่เข้มงวดแก่คุณ RestrictedPythonแปลงรหัส Python เป็นสิ่งที่ช่วยให้คุณสามารถควบคุมชื่อโมดูลและวัตถุที่อนุญาตใน Python 2.3 ถึง 2.7

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

ในความคิดของฉันตัวเลือกที่แข็งแกร่งอย่างแท้จริงเท่านั้นคือการใช้ Virtual Machine แยกต่างหากอันที่ไม่มีการเข้าถึงเครือข่ายไปยังโลกภายนอกที่คุณทำลายหลังจากการวิ่งแต่ละครั้ง สคริปต์ใหม่แต่ละตัวจะได้รับ VM ใหม่แทน ด้วยวิธีนี้แม้ว่าโค้ดจะจัดการกับ Python sandbox ของคุณ (ซึ่งไม่น่าจะเป็นไปได้) ผู้โจมตีทุกคนที่ได้รับการเข้าถึงจะมีอายุสั้นและไม่มีค่า


10

TL; DRใช้ chroot / jail และเรียกใช้ในฐานะผู้ใช้ที่กำหนดเองโดยไม่มีสิทธิ์ใด ๆ

แนวทางปฏิบัติที่ดีที่สุดสำหรับการเรียกใช้โค้ดที่ไม่น่าเชื่อถือคือการแยกรหัสผ่านแซนด์บ็อกซ์ระบบ เพื่อความปลอดภัยสูงสุด:

  • สร้างคอนเทนเนอร์ด้วย Python เท่านั้นและเป็นการอ้างอิงและการขึ้นต่อกันของคอนเทนเนอร์
  • สร้างคอนเทนเนอร์โดยไม่มีอุปกรณ์ทั้งหมดที่ไม่จำเป็นอย่างแน่นอน(เช่นเครือข่ายและที่เก็บข้อมูล)
  • สร้างคอนเทนเนอร์ที่มีข้อ จำกัด ในการใช้หน่วยความจำและกระบวนการ
  • สร้างคอนเทนเนอร์ใหม่ด้วยการวิ่งทุกครั้ง(หรืออย่างน้อยที่สุดกับผู้ใช้แต่ละคนและช่วงเวลาสูงสุด)
  • เรียกใช้ในฐานะผู้ใช้ที่ต้องการสิทธิ์น้อยที่สุด
  • เรียกใช้ในฐานะผู้ใช้ที่ไม่มีสิทธิ์ในการเขียนไฟล์

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


นี่เป็นสิ่งเดียวที่คุณจะทำได้แม้จากระยะไกลคุณมั่นใจว่าถูกต้อง - ให้มันเป็นกระบวนการของตัวเอง
Michael Kohne

3

ไม่มีวิธีที่คุณสามารถทำได้อย่างปลอดภัย

หากคุณต้องการทำสิ่งนี้อย่างปลอดภัยคุณจะต้องเริ่มต้นด้วยการใช้งานไพ ธ อนของคุณเองซึ่งทำงานในสภาพแวดล้อมที่มีการควบคุมอย่างสมบูรณ์โดยเฉพาะอย่างยิ่งควรรันในเบราว์เซอร์ของผู้ใช้แทนที่จะเป็นบนระบบของคุณ คุณอาจเริ่มต้นด้วย Jython (python สำหรับ java) และทำแพ็กเกจเป็นแอปเพล็ต java เนื่องจากมันจะทำงานใน java sandbox บนเครื่องของผู้ใช้ระบบของคุณจะปลอดภัยพอสมควร


4
คำถามด้านความปลอดภัยสำหรับเซิร์ฟเวอร์ของเขาไม่ใช่สำหรับเครื่องของลูกค้า อันตรายด้านความปลอดภัยที่อาจเกิดขึ้นของ Java เช่นเดียวกับเทคโนโลยีเว็บอื่น ๆ คือเซิร์ฟเวอร์สามารถใช้เพื่อปรับใช้โปรแกรมที่เป็นอันตรายต่อลูกค้า
ddyer

1
@grasGendarme เหมือนเรื่องราวใหม่เกี่ยวกับเครื่องบินตกจริง ๆ บอกคุณมากเกี่ยวกับวิธีที่หายากเหล่านั้น เรื่องราวเกี่ยวกับรูความปลอดภัยของจาวาบอกคุณว่าจาวามีความปลอดภัย คุณจะไม่ได้รับเรื่องราวดังกล่าวเกี่ยวกับ C เพราะคำตอบที่คุณจะได้รับคือ "well duh; ถ้าคุณเรียกใช้มันจะทำทุกอย่างที่ต้องการ"
Richard Tingle

2

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

ฉันจะดูPyPyแทน CPython มาตรฐาน กล่าวโดยสรุปคือการใช้งาน Python ที่เป็นทางเลือก มันมีข้อดีและคุณสมบัติที่แตกต่างหลายประการและหนึ่งในนั้นคือการทดลองแบบแซนด์บ็อกซ์ผ่านการแทนที่การเรียกระบบแทนการ จำกัด คุณสมบัติทางภาษา


0

ตราบใดที่ประสิทธิภาพไม่ได้มีความสำคัญอย่างยิ่งสำหรับคุณคุณสามารถเรียกใช้งานได้ใน Brython ซึ่งวางไว้ในกล่องทดลอง JavaScript อย่างมีประสิทธิภาพ

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