สัปดาห์ที่แล้วฉันสร้างเว็บไซต์ให้คนอื่น และฉันบังเอิญค้นพบว่ามีช่องโหว่มากมายในงานของฉัน ในเวลาเพียง 20 วินาที ฉันใช้การแทรก SQL เพื่อแก้ไข ดังนั้นฉันจึงตรวจสอบข้อมูลบางอย่างเกี่ยวกับการฉีด sql และได้รับข้อมูลเชิงลึกบางอย่าง ฉันหวังว่าจะสามารถแบ่งปันกับมือใหม่ได้ ผู้เชี่ยวชาญหัวเราะ!
แนวคิดทั่วไปของการโจมตีด้วยการฉีด SQL:
ค้นหาตำแหน่งการฉีด SQL
กำหนดประเภทเซิร์ฟเวอร์และประเภทฐานข้อมูลพื้นหลัง
เพื่อตรวจสอบความสามารถในการปฏิบัติการ
โดยทั่วไปผู้โจมตีบางรายจะใช้การแทรก SQL ต่อไป ฉันจะพูดถึงข้อมูลเชิงลึกของตัวเองเกี่ยวกับวิธีการฉีด sql
วิธีการฉีด:
ตามทฤษฎีแล้ว หน้าเว็บการรับรองความถูกต้องจะมีลักษณะดังนี้:
เลือก * จากผู้ดูแลระบบโดยที่คำสั่งชื่อผู้ใช้='XXX' และรหัสผ่าน='ปปปป' หากไม่ได้ทำการกรองอักขระที่จำเป็นก่อนที่จะรันคำสั่งนี้อย่างเป็นทางการ ก็ง่ายต่อการใช้งานการฉีด SQL
ตัวอย่างเช่น ป้อนในกล่องข้อความชื่อผู้ใช้: abc' หรือ 1=1-- ป้อนในกล่องรหัสผ่าน: 123 จากนั้นคำสั่ง SQL จะกลายเป็น:
เลือก * จากผู้ดูแลระบบโดยที่ชื่อผู้ใช้='abc' หรือ 1=1 และรหัสผ่าน='123' ไม่ว่าผู้ใช้จะป้อนชื่อผู้ใช้และรหัสผ่านใดคำสั่งนี้จะถูกดำเนินการอย่างถูกต้องเสมอและผู้ใช้สามารถหลอกลวงระบบได้อย่างง่ายดายและได้รับกฎหมาย ตัวตน.
เดาวิธีแก้ปัญหา:
แนวคิดพื้นฐานคือ เดาชื่อฐานข้อมูลทั้งหมด เดาชื่อตารางทุกชื่อในฐานข้อมูล วิเคราะห์ชื่อตารางที่อาจเก็บชื่อผู้ใช้และรหัสผ่าน เดาชื่อทุกฟิลด์ในตาราง เดาทุกบันทึกในเนื้อหาตาราง
นอกจากนี้ยังมีวิธีรับชื่อฐานข้อมูลและชื่อของแต่ละตารางด้วย
เพียงรับชื่อฐานข้อมูลและชื่อตารางของคุณโดยรายงานข้อผิดพลาดในรูปแบบ: http://www .cn/news?id=10'!
สำหรับ jsp โดยทั่วไปเราใช้กลยุทธ์ต่อไปนี้เพื่อจัดการกับมัน:
1.คำชี้แจงที่เตรียมไว้
หากคุณเป็นนักพัฒนาที่มีความก้าวหน้าในระดับปานกลางอยู่แล้ว คุณควรใช้ PreparationStatement แทน Statement เสมอ
นี่คือเหตุผลบางประการ
1. ความสามารถในการอ่านและบำรุงรักษาโค้ด
2. ReadyStatement ปรับปรุงประสิทธิภาพการทำงานให้มากที่สุด
3. จุดที่สำคัญที่สุดคือความปลอดภัยได้รับการปรับปรุงอย่างมาก
จนถึงตอนนี้ บางคน (รวมถึงตัวฉันเองด้วย) ยังไม่รู้ไวยากรณ์ SQL พื้นฐานที่ชั่วร้ายด้วยซ้ำ
สตริง sql = "select * จาก tb_name โดยที่ name= '"+varname+"' และ passwd='"+varpasswd+"'";
1
] เป็นชื่อ รหัสผ่านจะเป็นอย่างไร มาดูกันว่าจะเป็นอย่างไร?
passwd = 'สบาย ๆ' ;
เนื่องจาก '1'='1' เป็นจริงอย่างแน่นอน จึงสามารถผ่านการตรวจสอบได้ มีอะไรเพิ่มเติม:
ส่งผ่าน ['; วางตาราง tb_name; ] เป็น varpasswd จากนั้น:
เลือก * จาก tb_name = 'any' และ passwd = ''; drop table tb_name; บางฐานข้อมูลจะไม่ยอมให้คุณประสบความสำเร็จ แต่ก็มีฐานข้อมูลจำนวนมากที่สามารถดำเนินการคำสั่งเหล่านี้ได้
และถ้าคุณใช้คำสั่งที่คอมไพล์แล้ว เนื้อหาใด ๆ ที่คุณส่งเข้ามาจะไม่มีความสัมพันธ์ที่ตรงกับคำสั่งดั้งเดิม (สมมติฐานคือฐานข้อมูลนั้นรองรับการคอมไพล์ล่วงหน้า แต่อาจไม่มีฐานข้อมูลฝั่งเซิร์ฟเวอร์ที่ไม่รองรับการคอมไพล์ นั่น เป็นเพียงฐานข้อมูลเดสก์ท็อปบางส่วนเท่านั้น นั่นคือฐานข้อมูลที่สามารถเข้าถึงไฟล์ได้โดยตรง ตราบใดที่ฐานข้อมูลเหล่านั้นใช้คำสั่งที่คอมไพล์แล้ว คุณไม่จำเป็นต้องทำการกรองข้อมูลที่เข้ามา หากคุณใช้คำสั่งธรรมดา คุณอาจต้องใช้จ่าย มีเวลาหล่นมาก;, ฯลฯ การวางแผนการตัดสินและการคิดมาก
2. นิพจน์ทั่วไป
2.1. นิพจน์ทั่วไปเพื่อตรวจจับอักขระเมตา SQL/(%27)|(')|(--)|(%23)|(#)/ix
2.2. แก้ไขนิพจน์ทั่วไปสำหรับการตรวจหาอักขระเมตา SQL /((%3D)|(=))[^n]*((%27)|(')|(--) 54ne com
|(%3B)|(:))/i
2.3. การโจมตีด้วยการฉีด SQL ทั่วไป/w*((%27)|('))((%6F)|o|(%4F))((%72)|r |( China Network Management Alliance www.bitscn.com
%52))/ix
2.4 ตรวจหาการแทรก SQL นิพจน์ทั่วไปของคำค้นหา UNION /((%27)|('))union/ix(%27)|(') - single
เครื่องหมายคำพูดและสหภาพที่เทียบเท่าฐานสิบหก - คำหลักของสหภาพ
2.5. นิพจน์ทั่วไป/exec(s|+)+(s|x)pw+/ix เพื่อตรวจจับการโจมตีแบบฉีด SQL Server ของ MS
SQL
เนื้อหาตัวกรองสตริงคงที่สาธารณะ (เนื้อหาสตริง) {
สตริง flt="'|และ|exec|insert|select|delete|update|count|*|%
|chr|กลาง|ต้นแบบ|ตัด|ถ่าน|ประกาศ|;
Stringfilter[] = flt.split("|");
สำหรับ (int i = 0; ฉัน {
content.replace(ตัวกรอง[i], "");
-
ส่งคืนเนื้อหา
-
4. การปกปิดอักขระที่ไม่ปลอดภัย
ส่วนนี้ใช้ js เพื่อบล็อกซึ่งมีบทบาทน้อยมาก แม้ว่าวิธีการบล็อกคำหลักจะมีผลบางอย่าง แต่ในการใช้งานจริงคำหลัก SQL เหล่านี้อาจกลายเป็นคำหลักที่ใช้ค้นหาจริงและจากนั้นคุณจะถูกบล็อก ผู้ใช้จะไม่สามารถใช้งานได้ตามปกติ เพียงแค่ใช้ความพยายามบางอย่างกับมาตรฐานการเข้ารหัส
เมื่อมีตัวแปรใน SQL ที่ดำเนินการ เพียงใช้ PreparationStatement ที่จัดทำโดย JDBC (หรือเลเยอร์การคงอยู่ของข้อมูลอื่นๆ) จำไว้ว่าอย่าใช้วิธีการประกบสตริง
การแนะนำฟังก์ชัน: ตรวจสอบว่ามี "'"," \","/ " หรือไม่
คำอธิบายพารามิเตอร์: สตริงที่จะตรวจสอบ ค่าส่งคืน: 0: ใช่ 1: ไม่ใช่ ชื่อฟังก์ชัน ใช่
ตรวจสอบฟังก์ชัน(ก)
-
กลับ 1;
fibdn = อาร์เรย์ใหม่ ("'" ," \","/ ");
i=fibdn.ความยาว;
j=a.ความยาว;
สำหรับ (ii=0; ii { สำหรับ (jj=0; jj
{ temp1=a.charAt(jj);
temp2=fibdn[ii];
ถ้า (tem'; p1==temp2)
{ กลับ 0;
-
-
กลับ 1;
}