เราควรใช้ QUOTENAME เพื่อป้องกันการโจมตีจากการฉีดหรือไม่


9

ฉันดูขั้นตอนการจัดเก็บแบบเก่าวันนี้และสังเกตว่ามันใช้quotenameกับพารามิเตอร์อินพุต หลังจากขุดลงไปเพื่อหาว่ามันทำอะไรฉันก็เจอเว็บไซต์นี้ ตอนนี้ฉันเข้าใจแล้วว่ามันทำอะไรและจะใช้อย่างไร แต่เว็บไซต์บอกว่ามันถูกใช้เพื่อลดการโจมตีจากการฉีด SQL เมื่อฉันใช้ในการพัฒนาแอพที่สอบถามฐานข้อมูลโดยตรงโดยใช้ asp.net ฉันจะใช้พารามิเตอร์ ADO.Net เพื่อส่งผ่านการป้อนข้อมูลของผู้ใช้เป็นค่าที่แท้จริงและไม่เคยกังวลเกี่ยวกับการปกป้องในขั้นตอนการจัดเก็บของฉัน

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

รหัสที่ทำให้ฉันในรูปแบบความคิดนี้ ( @parm1เป็นพารามิเตอร์ที่ผู้ใช้ป้อน):

'SELECT project [Project], project_desc [Description], 
        customer [Customer], cpnyid [Company]
FROM PJPROJ (nolock)
where project like ' + quotename(@parm1,'''') + '

คำตอบ:


17

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

ฟังก์ชันนี้เหมาะสมสำหรับชื่อวัตถุ (เช่นตาราง, คอลัมน์, ชื่อฐานข้อมูล) เท่านั้น

คุณควรลองและทำพารามิเตอร์ทุกอย่างอื่นและใช้sp_executesqlผ่านพารามิเตอร์แทนการเชื่อมโยงสิ่งเหล่านั้นลงในสตริงการสืบค้น

บทความที่ชัดเจนเกี่ยวกับหัวข้อนี้ยังคงเป็นThe Curse and Blessings ของ Dynamic SQL


แก้ไข ตอนนี้คุณได้ใส่รหัสที่ฉันเห็นว่ามันผ่านพารามิเตอร์ที่สองของ'การเพิ่มคำพูดนอกและหนีคำพูดใด ๆ โดยการเพิ่มพวกเขาก่อนที่จะฉีดเข้าไปในสตริง นี่ไม่ใช่การใช้ชื่อเล่นที่ดี มันจะล้มเหลว (return null) หากสตริงมากกว่า 128 ตัวอักษร

นอกจากนี้ก็ยังอาจจะออกจากความเป็นไปได้ฉีด SQL ถ้าสตริงมี U + 02BC แทนเครื่องหมายวรรคตอนมาตรฐานแล้วสตริงได้รับมอบหมายให้ varchar หลังจากสุขาภิบาล ( ซึ่งสามารถเงียบได้รับการดัดแปลงเป็นเครื่องหมายวรรคตอนปกติ )

วิธีที่ถูกต้องในการทำเช่นนี้คือปล่อยให้การสืบค้นพารามิเตอร์ จากนั้นส่ง@parm1ค่าไปที่sys.sp_executesql

DECLARE @Sql NVARCHAR(MAX);

SET @Sql = '
SELECT project      [Project],
       project_desc [Description],
       customer     [Customer],
       cpnyid       [Company]
FROM   PJPROJ (nolock)
WHERE  project LIKE @parm1 
';

EXEC sys.sp_executesql
  @Sql,
  N'@parm1 varchar(100)',
  @parm1 = 'foobar%'; 
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.