การเขียนโปรแกรม back-end
| English | ไทย |
|---|---|
| route/ruːt/ | เส้นทาง |
| validate input/ˈvælɪdeɪt ˈɪnpʊt/ | ตรวจสอบอินพุต |
| status/ˈsteɪtəs/ | สถานะ |
| SQL injection/ˌes kjuː ˈel ɪnˈdʒekʃn/ | SQL injection |
| parameterised query/ˌpærəˈmetəraɪzd ˈkwɪərɪ/ | query แบบพารามิเตอร์ |
ตัวอักษรค้นหามีผลต่อการเปลี่ยนแปลง Query
- การค้นหาชื่อจะรับ
' OR 1=1 --หากโค้ดนำมันไปวางใน SQL ข้อความอาจเปลี่ยนเงื่อนไขแทนที่จะคงเป็นชื่อไว้ - Route เชื่อมโยงวิธีการและเส้นทางของคำขอเข้ากับตัวจัดการ (handler) รักษาสัญญาของ Route ให้ชัดเจนก่อนดำเนินการค้นหา
ตรวจสอบรูปแบบและสิทธิ์
- Validation ข้อมูล หมายถึงการตรวจสอบค่าที่จำเป็น ประเภท ความยาวที่อนุญาตและช่วงที่รองรับ ตรวจสอบสิทธิ์ของผู้เรียกแยกต่างหาก
- สถานะ อธิบายผลลัพธ์: 200 สำหรับการค้นหาสำเร็จ, 400 สำหรับอินพุตที่ไม่ถูกต้อง และ 404 สำหรับทรัพยากรที่หายขาด ความล้มเหลวด้านสิทธิ์ต้องใช้นโยบายที่แอปพลิเคชันตกลงกัน; ไม่ใช่แค่อินพุตที่ผิดโดยอัตโนมัติ
จับคู่ผลลัพธ์เหล่านี้ภายใต้สัญญาเส้นทางของบทเรียน
ความหมายเหล่านี้ไม่ได้กำหนดเองว่าความล้มเหลวในการอนุญาตที่เป็นส่วนตัวควรแสดงอย่างไร
เก็บค่าภายนอกข้อความ SQL
- SQL injection เกิดขึ้นเมื่อข้อความที่ไม่ไว้วางใจกลายเป็นส่วนหนึ่งของไวยากรณ์ SQL Parameterised query จะผูกค่าแยกต่างหากกับคำสั่ง
- Placeholders ผูกค่าเท่านั้น ไม่ผูกชื่อตารางหรือทิศทางเรียงลำดับแบบสุ่ม เลือกตัวระบุเช่นนี้จากรายชื่อ_allowlist_ ของเซิร์ฟเวอร์ที่กำหนดไว้ล่วงหน้าเมื่อ Route ต้องการใช้มัน
การค้นหาค่าแบบใดที่ช่วยแยกชื่อที่ถูกส่งมาจากไวยากรณ์ SQL?
การผูกค่าช่วยให้แยกออกจากคำสั่งที่ตายตัว
อธิบายว่าการผูกชื่อเข้ากับช่องว่างใน SQL เปลี่ยนแปลงอะไรไป
คำสั่งยังคงตายตัวในขณะที่ค่าที่ถูกผูกแยกต่างหากยังคงเป็นข้อมูล
ตัวแทนค่าสามารถใช้แทนชื่อตารางหรือลำดับการเรียงลำดับได้อย่างปลอดภัย
ตัวแทนผูกกับค่า เลือกชื่อตัวแปรพลวัตจากรายการอนุญาตด้านเซิร์ฟเวอร์ที่กำหนดไว้ล่วงหน้าเท่านั้น
รันตัวอย่างในพื้นที่อย่างสมบูรณ์
- บันทึกและรันตัวอย่าง Python นี้โดยใช้ SQLite ค่าข้อความที่แปลกประหลาดจะถูกจัดเก็บเป็นชื่อ จากนั้นถูกค้นหาในฐานะค่าที่ถูกผูก
- ผลลัพธ์จะมีเพียงแถวที่มีชื่อนั้นเท่านั้น การผูกป้องกันไม่ให้ค่านีกลายเป็นไวยากรณ์ SQL ไม่ได้หมายความว่ามีการกำหนดสิทธิ์หรือไม่ทำให้แอปพลิเคชันปลอดภัยทุกประการ
import sqlite3
con = sqlite3.connect(":memory:")
con.execute("CREATE TABLE students (id INTEGER PRIMARY KEY, name TEXT)")
name = "' OR 1=1 --"
con.executemany("INSERT INTO students VALUES (?, ?)", [(1, "Mei"), (2, name)])
rows = con.execute("SELECT id FROM students WHERE name = ?", (name,)).fetchall()
print(rows) # [(2,)]
con.close()
ตัวอย่าง SQLite แบบสมบูรณ์จะพิมพ์อะไร?
สตริงที่ไม่寻常ถูกจัดเก็บและจากนั้นจับคู่ในฐานะชื่อตามตัวอักษร
ทำให้ความล้มเหลวมีประโยชน์และเป็นส่วนตัว
- ให้ข้อความที่ชัดเจนแก่เบราว์เซอร์เพื่อให้สามารถดำเนินการได้ เช่น-fields- ที่ไม่ถูกต้องหรือความล้มเหลวชั่วคราว อย่าส่งข้อผิดพลาด SQL/raw-, ข้อมูลประจำตัวส่วนตัวหรือ stack traces
- บันทึกข้อมูลการวินิจฉัยเฉพาะในบันทึกที่ปลอดภัยโดยลบค่าที่เป็นความลับออกแล้ว บันทึกบริบทให้เพียงพอต่อการตรวจสอบโดยไม่คัดลอกทุกส่วนขอรับที่มีข้อมูลส่วนตัว
ส่งข้อผิดพลาดฐานข้อมูลดิบให้ผู้ใช้ทั่วไปเพื่อให้ họสามารถแก้ไข SQL ได้
ส่งข้อความที่ปลอดภัยและมีประโยชน์; ปกป้องบันทึกการวินิจฉัยและลบค่าที่อ่อนไหวออก
ตรวจสอบมากกว่าเพียงกรณีปกติที่สำเร็จ
- ตรวจสอบอินพุตที่ถูกต้อง หายไป มีประเภทไม่ตรง และมีขนาดใหญ่เกิน การเข้าถึงที่ถูกปฏิเสธ ผลลัพธ์จับคู่ว่าง และความล้มเหลวของฐานข้อมูลที่จำลองไว้ กำหนดผลลัพธ์ที่คาดหวังสำหรับแต่ละกรณี
- รักษาทุกค่าไดนามิกที่ผูกไว้ รวมถึงค่าจากเมนูแบบเลื่อนลง รายการในเบราว์เซอร์ไม่สามารถป้องกันผู้ส่งส่งค่าอื่นโดยตรงได้
ตรวจสอบคำขอ อนุญาตให้ผู้เรียกใช้ และผูกค่าข้อมูล สิ่งเหล่านี้แก้ปัญหาที่แตกต่างกัน ไม่มีสิ่งใดแทนอีกสิ่งหนึ่ง
อินพุตภายนอกใดที่ต้องการตรวจสอบจากเซิร์ฟเวอร์? เลือกทุกข้อที่เกี่ยวข้อง
ค่าภายนอกที่ดูปกติก็ยังคงมีประเภท ความยาว หรือสิทธิ์ที่ผิดได้
คำขอข้อมูลมีการกำหนดพารามิเตอร์ แต่ผู้เรียกใช้งานรายใดก็อ่านแถวข้อมูลนักเรียนที่เป็นความลับได้ สิ่งที่ขาดหายไปคืออะไร?
การผูกที่อยู่เพื่อฉีดค่า ไม่ได้อนุญาตให้ผู้เรียกใช้งานเข้าถึงข้อมูล