ฉันสามารถป้องกันการฉีด SQL ด้วยการหลีกเลี่ยงการอ้างคำพูดเดียวและป้อนข้อมูลผู้ใช้โดยรอบด้วยคำพูดเดียว?


139

ฉันรู้ว่าการสืบค้น SQL แบบแปรผันเป็นวิธีที่ดีที่สุดในการฆ่าเชื้ออินพุตของผู้ใช้เมื่อสร้างเคียวรีที่มีการป้อนข้อมูลของผู้ใช้ แต่ฉันสงสัยว่าเกิดอะไรขึ้นกับการป้อนข้อมูลผู้ใช้และหลีกเลี่ยงคำพูดเดี่ยว ๆ นี่คือรหัส:

sSanitizedInput = "'" & Replace(sInput, "'", "''") & "'"

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

เรากำลังใช้ Microsoft SQL Server 2000 ซึ่งฉันเชื่อว่า single-quote เป็นตัวคั่นสตริงเท่านั้นและวิธีเดียวที่จะหลีกเลี่ยงตัวคั่นสตริงดังนั้นจึงไม่มีวิธีดำเนินการใด ๆ กับผู้ใช้ประเภทใด ๆ

ฉันไม่เห็นวิธีใดที่จะเปิดการโจมตีด้วยการฉีด SQL เพื่อต่อต้านสิ่งนี้ แต่ฉันรู้ว่าถ้านี่เป็นกระสุนที่ดูเหมือนกับฉันคนอื่นจะคิดว่ามันแล้วและมันจะเป็นเรื่องธรรมดา

เกิดอะไรขึ้นกับรหัสนี้ มีวิธีการโจมตี SQL injection ผ่านเทคนิคการฆ่าเชื้อนี้หรือไม่ ตัวอย่างอินพุตของผู้ใช้ที่ใช้ประโยชน์จากเทคนิคนี้จะเป็นประโยชน์


UPDATE:

ฉันยังไม่รู้วิธีการเปิดใช้การโจมตี SQL injection กับรหัสนี้อย่างมีประสิทธิภาพ มีบางคนแนะนำว่าแบ็กสแลชจะหนีจากเครื่องหมายคำพูดเดียวและปล่อยให้คำสั่งหยุดสตริงเพื่อให้ส่วนที่เหลือของสตริงจะถูกดำเนินการโดยเป็นส่วนหนึ่งของคำสั่ง SQL และฉันรู้ว่าวิธีนี้จะทำงานเพื่อฉีด SQL ลงใน ฐานข้อมูล MySQL แต่ใน SQL Server 2000 วิธีเดียว (ที่ฉันสามารถค้นหา) เพื่อหลีกเลี่ยงการอ้างคำพูดเดียวคือการอ้างอีกครั้งเดียว; แบ็กสแลชจะไม่ทำ

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

ฉันเข้าใจว่ามีวิธีที่ดีกว่าในการฆ่าเชื้ออินพุต แต่ฉันสนใจการเรียนรู้มากขึ้นว่าทำไมวิธีการที่ฉันให้ไว้ข้างต้นจะไม่ทำงาน หากใครรู้วิธีเฉพาะใด ๆ เพื่อติดตั้งการโจมตีการฉีด SQL กับวิธีการฆ่าเชื้อนี้ฉันชอบที่จะเห็นมัน


17
@BryanH ยอมรับว่าไม่เข้าใจว่าภูมิปัญญาที่ยอมรับกันทั่วไปนำไปใช้กับกรณีเฉพาะได้อย่างไรและการขอตัวอย่างเกี่ยวกับกรณีดังกล่าวไม่ใช่ความโอหังมันเป็นความอ่อนน้อมถ่อมตน เริ่มรำคาญเมื่อมีคนถามตัวอย่างว่าทำไมภูมิปัญญาที่ยอมรับกันโดยทั่วไปนั้นถูกต้องในทางกลับกัน การใช้เหตุผลโดยตัวอย่างเฉพาะมักเป็นวิธีที่ดีในการตรวจสอบและเรียนรู้ วิธีที่ OP ดำเนินการเกี่ยวกับข้อสงสัยนี้มีประโยชน์มากสำหรับความเข้าใจในเรื่องของฉันโดยเฉพาะเมื่อเขาอธิบายคำตอบที่เขาพบ
SantiBailors

@patrik เพิ่งเจอสิ่งนี้เนื่องจากฉันกำลังทำงานกับโค้ดชิ้นเดียวกัน แต่พยายามที่จะหลีกเลี่ยงสตริงและซ้อนเคียวรี คุณเคยคิดออกไหม
3therk1ll

1
@ 3therk1ll เป็นการดีที่สุดที่จะไม่ลองใช้คุณควรใช้ SQL แบบแปรผัน
Patrick

@ แพทริคฉันกำลังใกล้เข้ามาจากมุมมองของผู้โจมตี!
3therk1ll

คำตอบ:


87

ก่อนอื่นมันเป็นแค่การปฏิบัติที่ไม่ดี การตรวจสอบอินพุตเป็นสิ่งจำเป็นเสมอ แต่ก็ยังไม่แน่นอนเสมอ
ยิ่งกว่านั้นการตรวจสอบบัญชีดำนั้นเป็นปัญหาเสมอดีกว่ามากในการกำหนดค่า / รูปแบบที่คุณยอมรับอย่างชัดเจนและเคร่งครัด เป็นที่ยอมรับว่าเป็นไปไม่ได้เสมอไป - แต่จะต้องทำในระดับหนึ่งเสมอ
งานวิจัยบางเรื่องในหัวข้อ:

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

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

วิธีที่เหมาะสมในการทำ:

  • การตรวจสอบรายการที่อนุญาต: ประเภทความยาวรูปแบบหรือค่าที่ยอมรับได้
  • หากคุณต้องการขึ้นบัญชีดำ การหลีกเลี่ยงการอ้างเป็นสิ่งที่ดี แต่ภายในบริบทของการบรรเทาอื่น ๆ
  • ใช้วัตถุ Command และ Parameter เพื่อเตรียมและตรวจสอบความถูกต้อง
  • โทรสอบถามพารามิเตอร์
  • ดีกว่าใช้ขั้นตอนการจัดเก็บโดยเฉพาะ
  • หลีกเลี่ยงการใช้ไดนามิก SQL และอย่าใช้การต่อสตริงเพื่อสร้างคิวรี
  • หากใช้ SP คุณสามารถ จำกัด สิทธิ์ในฐานข้อมูลเพื่อดำเนินการ SP ที่จำเป็นเท่านั้นและไม่สามารถเข้าถึงตารางได้โดยตรง
  • คุณสามารถตรวจสอบได้อย่างง่ายดายว่า codebase ทั้งหมดเข้าถึงฐานข้อมูลผ่าน SP เท่านั้น ...

2
เมื่อใช้อย่างถูกต้องการเชื่อมต่อ SQL แบบไดนามิกและสตริงสามารถใช้งานได้อย่างปลอดภัยกับแบบสอบถามแบบใช้พารามิเตอร์ (เช่นsp_executesqlแทนที่จะเป็นEXEC) นั่นคือคุณสามารถสร้างคำสั่ง SQL แบบไดนามิกตราบใดที่ไม่มีข้อความที่ต่อกันมาจากผู้ใช้ สิ่งนี้ยังมีประโยชน์ด้านประสิทธิภาพ; sp_executesqlรองรับการแคช
Brian

2
@Brian, duh :) แต่ในความเป็นจริงคุณเห็นโปรแกรมเมอร์ทำบ่อยแค่ไหน? ยิ่งไปกว่านั้นสถานการณ์ทั่วไปที่ SQL แบบไดนามิกเป็น "ต้องการ" ต้องการอินพุตผู้ใช้เป็นส่วนหนึ่งของแบบสอบถาม (ตามที่คาดคะเน) หากคุณสามารถทำ sp_executesql คุณจะไม่ต้องการ sql แบบไดนามิกในตอนแรก
AviD

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

1
@ElRonnoco แน่ใจ แต่ผมทำไม่ได้ส่วนลดที่ตั้งแต่ผมเคยเห็นมันในป่าอีกครั้งกว่าที่คุณคิดว่า ...
Avid

1
@AviD ฉันได้อัปเดตลิงก์ไปยัง SQL Smuggling PDF ที่คุณเขียนเป็นเวอร์ชันเดียวที่ฉันสามารถหาได้ทางออนไลน์ ... โปรดแจ้งให้เราทราบหากมีตำแหน่งอื่นสำหรับกระดาษของคุณ
Michael Fredrickson

41

ตกลงการตอบสนองนี้จะเกี่ยวข้องกับการอัปเดตคำถาม:

"หากใครรู้วิธีใดวิธีหนึ่งในการเมาท์การโจมตีฉีด SQL กับวิธีฆ่าเชื้อนี้ฉันชอบที่จะดู"

ตอนนี้นอกเหนือจากแบ็กสแลชของ MySQL แล้ว - และเมื่อพิจารณาว่าเรากำลังพูดถึง MSSQL จริง ๆ แล้วก็มีวิธีที่เป็นไปได้ 3 วิธีในการที่ SQL ฉีดโค้ดของคุณ

sSanitizedInput = "'" และแทนที่ (sInput, "'", "'" ") &"' "

พิจารณาว่าสิ่งเหล่านี้จะไม่ถูกต้องตลอดเวลาและขึ้นอยู่กับรหัสจริงของคุณ:

  1. การฉีด SQL ลำดับที่สอง - หากแบบสอบถาม SQL ถูกสร้างขึ้นใหม่ตามข้อมูลที่ดึงมาจากฐานข้อมูลหลังจากการหลบหนีข้อมูลจะถูกรวมเข้าด้วยกันโดยไม่ใช้ค่า Escape และอาจถูกฉีด SQL ทางอ้อม ดู
  2. การตัดสตริง - (ซับซ้อนกว่านี้นิดหน่อย) - สถานการณ์คือคุณมีสองฟิลด์พูดชื่อผู้ใช้และรหัสผ่านและ SQL เชื่อมทั้งสองฟิลด์เข้าด้วยกัน และทั้งสองฟิลด์ (หรือเพียงอันแรก) มีขีดจำกัดความยาวที่ จำกัด ตัวอย่างเช่นชื่อผู้ใช้จะถูก จำกัด ที่ 20 ตัวอักษร สมมติว่าคุณมีรหัสนี้:
username = left(Replace(sInput, "'", "''"), 20)

สิ่งที่คุณจะได้รับคือชื่อผู้ใช้หลบหนีจากนั้นตัดเหลือ 20 ตัวอักษร ปัญหาที่นี่ - ฉันจะติดคำพูดของฉันในตัวละครที่ 20 (เช่นหลังจาก 19 ของ) และคำพูดที่หลบหนีของคุณจะถูกตัดแต่ง (ในตัวละครที่ 21) จากนั้น SQL

sSQL = "select * from USERS where username = '" + username + "'  and password = '" + password + "'"

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


28

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


2
ถ้าคุณต้องจัดการกับบางสิ่งบางอย่างเช่น "ตาราง Google Fusion" ที่ไหน, ที่นั่น, ไม่มีห้องสมุดนามธรรมที่รองรับภาษาถิ่นของมัน? คุณจะแนะนำอะไร
systempuntoout

20

ฉันรู้ว่านี่เป็นเวลานานหลังจากคำถามถูกถาม แต่ ..

วิธีหนึ่งในการเริ่มต้นการโจมตีในขั้นตอน 'อ้างถึงการโต้แย้ง' คือการตัดสตริง ตาม MSDN ใน SQL Server 2000 SP4 (และ SQL Server 2005 SP1) สตริงที่ยาวเกินไปจะถูกตัดทอนอย่างเงียบ ๆ

เมื่อคุณอ้างอิงสตริงสตริงจะเพิ่มขนาด เครื่องหมายวรรคตอนทุกครั้งจะถูกทำซ้ำ สิ่งนี้สามารถใช้เพื่อผลักดันส่วนต่าง ๆ ของ SQL นอกบัฟเฟอร์ ดังนั้นคุณสามารถตัดส่วนต่าง ๆ ของข้อที่ได้อย่างมีประสิทธิภาพ

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

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

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


1
หลังจากโพสต์แล้วฉันตัดสินใจว่าโพสต์ของ AviD ครอบคลุมเนื้อหานี้และมีรายละเอียดเพิ่มเติม หวังว่าโพสต์ของฉันจะยังคงเป็นประโยชน์กับใครบางคน
Jørn Jensen

10

ฉันใช้เทคนิคนี้เมื่อจัดการกับฟังก์ชั่น 'การค้นหาขั้นสูง' ซึ่งการสร้างแบบสอบถามตั้งแต่ต้นเป็นคำตอบเดียว (ตัวอย่าง: อนุญาตให้ผู้ใช้ค้นหาผลิตภัณฑ์ตามข้อ จำกัด ที่ไม่ จำกัด เกี่ยวกับคุณลักษณะของผลิตภัณฑ์การแสดงคอลัมน์และค่าที่อนุญาตของพวกเขาเป็นตัวควบคุม GUI เพื่อลดเกณฑ์การเรียนรู้สำหรับผู้ใช้)

ในตัวมันเองปลอดภัย AFAIK อย่างไรก็ตามผู้ตอบอีกคนหนึ่งชี้ให้เห็นว่าคุณอาจต้องจัดการกับ backspace escaping (แม้ว่าจะไม่ใช่เมื่อผ่านการสืบค้นไปยัง SQL Server โดยใช้ ADO หรือ ADO.NET อย่างน้อยก็ไม่สามารถรับรองฐานข้อมูลหรือเทคโนโลยีทั้งหมดได้)

อุปสรรค์คือคุณต้องแน่ใจว่าสตริงใดที่มีอินพุตผู้ใช้ (อาจเป็นอันตรายเสมอ) และสตริงใดเป็นเคียวรี SQL ที่ถูกต้อง หนึ่งในกับดักคือถ้าคุณใช้ค่าจากฐานข้อมูล - ค่าเหล่านั้นมาจากผู้ใช้หรือไม่? ถ้าเป็นเช่นนั้นพวกเขาจะต้องหลบหนี คำตอบของฉันคือพยายามทำให้ช้าที่สุดเท่าที่จะเป็นไปได้ (แต่ไม่มีในภายหลัง!) เมื่อสร้างแบบสอบถาม SQL

อย่างไรก็ตามในกรณีส่วนใหญ่การผูกพารามิเตอร์เป็นวิธีที่จะทำได้ง่ายกว่า


2
คุณยังสามารถใช้การทดแทนพารามิเตอร์แม้ว่าคุณจะสร้างคิวรีของคุณเอง
Nick Johnson

1
คุณควรสร้างสตริงคำสั่ง SQL ตั้งแต่เริ่มต้น แต่ยังคงใช้การทดแทนพารามิเตอร์
JeeBee

ไม่ไม่ต้องสร้างคำสั่ง SQL ของคุณตั้งแต่ต้น
AviD

8

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


4
และเมื่อคุณพลาดONEกรณีหนึ่งการป้อนข้อมูลที่คุณกำลัง PWND
BryanH

4
"บางคนเมื่อต้องเผชิญกับปัญหาคิดว่า" ฉันรู้ว่าฉันจะใช้การแสดงออกปกติ "ตอนนี้พวกเขามีปัญหาสองประการ"
MickeyfAgain_BeforeExitOfSO

1
@ Mickeyf ฉันรู้ว่านี่เป็นความรู้สึกร่วมกัน แต่การแสดงออกปกติโดยสุจริตนั้นยอดเยี่ยมมากเมื่อคุณ grep พวกเขา
tom.dietrich

@ tom.dietrich มันขึ้นอยู่กับสถานการณ์ในชีวิตจริงเสมอ F.ex. ไวยากรณ์ regexpr ไม่ได้มาตรฐานดังนั้นโดยทั่วไปฉันจะแนะนำให้ใช้ regexpr ในบริบทที่ระบบต่าง ๆ ถูกรวมเข้าด้วยกันเพื่อทำงานร่วมกัน นี่เป็นเพราะเอ็นจิ้น regexpr ที่แตกต่างกันประเมิน regexprs แตกต่างกันและที่สำคัญกว่านั้นความจริงที่ยากนี้มักจะวัดผลหรือเพิกเฉยซึ่งอาจทำให้นักพัฒนาไม่สนใจความไม่เข้ากันเหล่านี้จนกว่าพวกเขาจะถูกกัด มีความไม่ลงรอยกันมากมายเช่น; ดู f.ex regular-expressions.info/shorthand.html (ค้นหาflavorsในหน้านั้น)
SantiBailors

6

มันเป็นความคิดที่ไม่ดีอยู่แล้วอย่างที่คุณรู้

มีบางอย่างเกี่ยวกับการหลบหนีคำพูดในสตริงเช่นนี้: \ '

การแทนที่ของคุณจะส่งผลให้: \ ''

หากเครื่องหมายแบ็กสแลชหนีจากเครื่องหมายคำพูดแรกคำพูดที่สองจะสิ้นสุดสตริง


3
ขอบคุณสำหรับคำตอบ! ฉันรู้ว่าการโจมตีจะทำงานกับฐานข้อมูล mySQL แต่ฉันค่อนข้างแน่ใจว่า MS SQL Server จะไม่ยอมรับเครื่องหมายแบ็กสแลชเป็นอักขระเลี่ยง (ฉันลองใช้) การค้นหา google หลายครั้งไม่ได้เปิดเผยตัวละครหลบหนีอื่น ๆ ซึ่งทำให้ฉันสงสัยว่าทำไมสิ่งนี้ถึงใช้งานไม่ได้
Patrick

6

คำตอบง่ายๆ: มันจะทำงานบางครั้ง แต่ไม่ตลอดเวลา คุณต้องการใช้การตรวจสอบความถูกต้องของรายการสีขาวกับทุกสิ่งที่คุณทำ แต่ฉันรู้ว่านั่นเป็นไปไม่ได้เสมอไปดังนั้นคุณจึงถูกบังคับให้ต้องทำบัญชีดำที่ดีที่สุด ในทำนองเดียวกันคุณต้องการใช้ procs ที่จัดเก็บแบบ Parametrized ในทุกสิ่งแต่ไม่สามารถทำได้อีกครั้งดังนั้นคุณจึงถูกบังคับให้ใช้ sp_execute กับพารามิเตอร์

มีหลายวิธีในการขึ้นบัญชีดำที่คุณสามารถใช้กับ (และบัญชีขาวบางรายการ)

การเขียนที่ดีอยู่ที่นี่: http://www.owasp.org/index.php/Top_10_2007-A2

หากคุณต้องการทำเช่นนี้เป็นการแก้ไขด่วนเพื่อให้คุณมีเวลาในการรับของจริงให้ทำ แต่อย่าคิดว่าคุณปลอดภัย


6

มีสองวิธีที่จะทำได้โดยไม่มีข้อยกเว้นเพื่อให้ปลอดภัยจากการฉีด SQL คำสั่งที่เตรียมไว้หรือขั้นตอนการจัดเก็บ prameterized


4

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


4

ใช่นั่นควรจะทำงานได้ดีจนกระทั่งมีคนรันSET QUOTED_IDENTIFIER OFFและใช้เครื่องหมายคำพูดคู่กับคุณ

แก้ไข: ไม่ง่ายเหมือนการไม่อนุญาตให้ผู้ใช้ที่เป็นอันตรายปิดตัวระบุที่เสนอราคา:

โปรแกรมควบคุม ODBC Native Client SQL Server และ SQL Server Native Client OLE DB Provider OLE สำหรับ SQL Server จะตั้งค่า QUOTED_IDENTIFIER เป็น ON โดยอัตโนมัติเมื่อเชื่อมต่อ สามารถกำหนดค่านี้ในแหล่งข้อมูล ODBC ในคุณสมบัติการเชื่อมต่อ ODBC หรือคุณสมบัติการเชื่อมต่อ OLE DB ค่าเริ่มต้นสำหรับ SET QUOTED_IDENTIFIER นั้นเป็น OFF สำหรับการเชื่อมต่อจากแอปพลิเคชัน DB-Library

เมื่อสร้างโพรซีเดอร์ที่เก็บไว้การตั้งค่าSET QUOTED_IDENTIFIER และ SET ANSI_NULLS จะถูกบันทึกและใช้สำหรับการเรียกใช้ครั้งต่อไปของโพรซีเดอร์ที่เก็บนั้น

SET QUOTED_IDENTIFIER ยังสอดคล้องกับการตั้งค่า QUOTED_IDENTIFER ของ ALTER DATABASE

SET QUOTED_IDENTIFIER มีการกำหนดเวลาในการแยก การตั้งเวลาแยกวิเคราะห์หมายความว่าหากมีคำสั่ง SET อยู่ในแบทช์หรือกระบวนงานที่เก็บไว้จะมีผลโดยไม่คำนึงว่าการใช้รหัสถึงจุดนั้นจริงหรือไม่ และคำสั่ง SET จะมีผลบังคับใช้ก่อนที่จะดำเนินการคำสั่งใด ๆ

มีหลายวิธีที่ QUOTED_IDENTIFIER สามารถปิดได้โดยที่คุณไม่จำเป็นต้องรู้ เป็นที่ยอมรับ - นี่ไม่ใช่ปืนสูบบุหรี่ใช้ประโยชน์ที่คุณกำลังมองหา แต่มันเป็นพื้นผิวการโจมตีที่ค่อนข้างใหญ่ แน่นอนถ้าคุณหลีกเลี่ยงการเสนอราคาซ้ำสองครั้งเราก็กลับมาที่จุดเริ่มต้น ;)


1
ที่สามารถใช้งานได้ แต่อีกครั้งพวกเขาจะได้รับรหัสเพื่อดำเนินการอย่างไรเมื่ออินพุตของผู้ใช้ทั้งหมดถูกล้อมรอบด้วยเครื่องหมายคำพูดเดี่ยว? บรรทัดรหัสเฉพาะที่สามารถฉีด SQL ลงในโค้ดด้านบนจะมีประโยชน์มาก ขอบคุณ!
Patrick

4

การป้องกันของคุณจะล้มเหลวถ้า:

  • แบบสอบถามคาดหวังว่าจะเป็นตัวเลขแทนที่จะเป็นสตริง
  • มีวิธีอื่นที่จะเป็นตัวแทนของเครื่องหมายคำพูดเดียวรวมไปถึง:
    • ลำดับ escape เช่น \ 039
    • อักขระ Unicode

(ในกรณีหลังมันจะต้องเป็นสิ่งที่ขยายออกไปหลังจากที่คุณแทนที่เสร็จแล้ว)


4

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


1

สิ่งที่รหัสน่าเกลียดทั้งหมด sanitisation ของผู้ใช้จะเป็นอะไร! จากนั้น StringBuilder clunky สำหรับคำสั่ง SQL วิธีการเตรียมการให้ผลลัพธ์เป็นโค้ดที่สะอาดกว่ามากและประโยชน์ของการฉีด SQL เป็นส่วนเสริมที่ดีมาก

ทำไมต้องบูรณาการล้อ?


1

แทนที่จะเปลี่ยนอัญประกาศเดี่ยวให้เป็น (ดูเหมือนอะไร) สองเครื่องหมายคำพูดเดียวทำไมไม่เพียงเปลี่ยนเครื่องหมายอัญประกาศเป็นอัญประกาศหรือลบออกทั้งหมด

ไม่ว่าจะด้วยวิธีใดมันเป็นเรื่องเล็กน้อย ... โดยเฉพาะอย่างยิ่งเมื่อคุณมีสิ่งต่าง ๆ (เช่นชื่อ) ซึ่งอาจใช้เครื่องหมายคำพูดเดียว ...

หมายเหตุ: วิธีการของคุณจะถือว่าทุกคนที่ทำงานในแอพของคุณจำการทำให้สะอาดอินพุตได้เสมอก่อนที่จะเข้าสู่ฐานข้อมูลซึ่งอาจไม่เหมือนจริงเกือบตลอดเวลา


ลงคะแนนเนื่องจากคำตอบไม่ได้ตอบคำถาม คำถามเกี่ยวกับการหลีกเลี่ยงสตริงใน SQL เมื่อคุณหลีกเลี่ยงสตริงที่กำหนดเอง (ในขณะที่ผู้ถามพยายามทำเพื่อจัดการกับข้อมูลที่ไม่ถูกแก้ไข) คุณจะไม่สามารถแทนที่อักขระที่มีปัญหาด้วยตัวอื่นที่เป็นปัญหาได้ ที่ทำให้ข้อมูลเสียหาย (เช่นเดียวกับอัญประกาศเดี่ยวคือเครื่องหมายอัญประกาศเดี่ยว (อย่างน้อยเป็น ASCII))
andrewf

-1

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

มันเป็นงานพิเศษมากมาย


-2

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


-3

ใช่คุณสามารถถ้า ...

หลังจากศึกษาหัวข้อฉันคิดว่าอินพุตที่ถูกสุขลักษณะตามที่คุณแนะนำนั้นปลอดภัย แต่ภายใต้กฎเหล่านี้เท่านั้น:

  1. คุณไม่อนุญาตให้ค่าสตริงที่มาจากผู้ใช้กลายเป็นอย่างอื่นนอกเหนือจากตัวอักษรสตริง (เช่นหลีกเลี่ยงการให้ตัวเลือกการกำหนดค่า: "ป้อนชื่อคอลัมน์ / นิพจน์ SQL เพิ่มเติมที่นี่:") ชนิดของค่าอื่นที่ไม่ใช่สตริง (ตัวเลข, วันที่, ... ): แปลงเป็นชนิดข้อมูลเนทิฟและจัดเตรียมรูทีนสำหรับ SQL ตัวอักษรจากแต่ละชนิดข้อมูล

    • คำสั่ง SQL เป็นปัญหาในการตรวจสอบ
  2. คุณใช้nvarchar/ ncharcolumn (และตัวอักษรสตริงนำหน้าด้วยN) หรือค่า จำกัด ที่จะใส่varchar/ charคอลัมน์เป็นอักขระ ASCII เท่านั้น (เช่นการยกเว้นข้อยกเว้นเมื่อสร้างคำสั่ง SQL)

    • วิธีนี้คุณจะหลีกเลี่ยงการแปลงเครื่องหมายอะโพสโทรฟีอัตโนมัติจาก CHAR (700) ถึง CHAR (39) (และอาจจะเป็น Unicode Hacks อื่น ๆ ที่คล้ายกัน)
  3. คุณตรวจสอบความยาวของค่าเพื่อให้พอดีกับความยาวคอลัมน์จริงเสมอ (ยกเว้นหากมีอีกต่อไป)

    • มีข้อบกพร่องที่ทราบใน SQL Server ที่อนุญาตให้เลี่ยงข้อผิดพลาด SQL ที่เกิดจากการตัด (นำไปสู่การตัดเสียงเงียบ)
  4. คุณรับรองว่าSET QUOTED_IDENTIFIERเป็นเสมอON

    • ระวังมันจะมีผลบังคับใช้ในการแยกวิเคราะห์เวลาคือแม้ในส่วนที่ไม่สามารถเข้าถึงได้ของรหัส

เมื่อปฏิบัติตาม 4 คะแนนเหล่านี้คุณควรจะปลอดภัย หากคุณละเมิดใด ๆ ของพวกเขาวิธีการฉีด SQL จะเปิดขึ้น


1
มันเหมือนกับว่าคุณไม่ได้อ่านคำตอบอื่น ๆ ทั้งหมดสำหรับคำถามอายุ 8 ปีนี้เนื่องจากคำตอบใด ๆ จำนวนมากชี้ให้เห็นว่าวิธีการของเขาล้มเหลวในการหยุดฉีดถ้าผู้โจมตีเพียงแค่ใช้อักขระ Unicode
โฮแกน

@ โฮแกน - ฉันทำ แต่ฉันคิดว่ามีค่าพิเศษในคำถามของฉัน ฉันมีประสบการณ์มากมายและทดสอบสิ่งที่ฉันเขียน ฉันรู้ว่าการใช้พารามิเตอร์ข้อความค้นหานั้นดีกว่า แต่ฉันก็เข้าใจสถานการณ์อย่างถ่องแท้เมื่อมีคนต้องหลีกเลี่ยงเนื่องจากสาเหตุต่าง ๆ (เช่นนายจ้างต้องการให้วิธีเก่า ๆ ) ในกรณีนี้ฉันคิดว่าคำตอบของฉันครอบคลุมมากและมีมูลค่าสูงกว่าคำตอบที่บอกว่า "อย่าทำอย่างนั้น" เพราะมันแสดงให้เห็นถึงวิธีการที่ผ่าน แสดงคำตอบอื่น ๆ ที่นี่ซึ่งแสดงในลักษณะเดียวกันและฉันจะลองลบของฉันออก
miroxlav

ตกลงเมื่อใดก็ตามที่ (ไม่ใช่ถ้า) ระบบของคุณถูกบุกรุกโปรดกลับมาและลบคำตอบนี้ .... หรือคุณอาจใช้แบบสอบถามแบบมีพารามิเตอร์
โฮแกน

@ โฮแกน - ฉันไม่มีปัญหาที่จะทำ :) แต่ตอนนี้ฉันอ้างว่าไม่มีวิธีที่จะหลีกเลี่ยงได้ถ้าคุณรักษากฎ 4 ข้อที่ฉันโพสต์ไว้ หากคุณคิดว่ามีวิธีการอยู่รอบ ๆ จริงๆให้ชี้ไปที่
miroxlav

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