.class
ไฟล์Java สามารถถอดรหัสได้ค่อนข้างง่าย ฉันจะป้องกันฐานข้อมูลของฉันได้อย่างไรหากต้องใช้ข้อมูลล็อกอินในรหัส
.class
ไฟล์Java สามารถถอดรหัสได้ค่อนข้างง่าย ฉันจะป้องกันฐานข้อมูลของฉันได้อย่างไรหากต้องใช้ข้อมูลล็อกอินในรหัส
คำตอบ:
อย่าใส่รหัสผ่านแบบฮาร์ดโค้ดลงในรหัสของคุณ สิ่งนี้ถูกนำมาใช้เมื่อไม่นานมานี้ในข้อผิดพลาดในการเขียนโปรแกรมที่อันตรายที่สุด 25 อันดับแรก :
การเข้ารหัสบัญชีลับและรหัสผ่านลงในซอฟต์แวร์ของคุณอย่างหนักนั้นสะดวกมากสำหรับวิศวกรย้อนกลับที่มีทักษะ หากรหัสผ่านเหมือนกันในซอฟต์แวร์ทั้งหมดของคุณลูกค้าทุกคนจะมีช่องโหว่เมื่อรู้รหัสผ่านนั้นอย่างหลีกเลี่ยงไม่ได้ และเนื่องจากเป็นฮาร์ดโค้ดจึงเป็นความเจ็บปวดอย่างมากในการแก้ไข
คุณควรจัดเก็บข้อมูลการกำหนดค่ารวมถึงรหัสผ่านไว้ในไฟล์แยกต่างหากที่แอปพลิเคชันอ่านเมื่อเริ่มทำงาน นั่นเป็นวิธีเดียวที่แท้จริงในการป้องกันไม่ให้รหัสผ่านรั่วไหลอันเป็นผลมาจากการแยกคอมไพล์ (ห้ามคอมไพล์ลงในไบนารีเพื่อเริ่มต้นด้วย)
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับความผิดพลาดที่พบบ่อยนี้คุณสามารถอ่านบทความ CWE-259 บทความนี้มีคำจำกัดความตัวอย่างและข้อมูลอื่น ๆ เกี่ยวกับปัญหาอย่างละเอียดมากขึ้น
ใน Java วิธีที่ง่ายที่สุดวิธีหนึ่งคือการใช้คลาส Preferences ออกแบบมาเพื่อจัดเก็บการตั้งค่าโปรแกรมทุกประเภทซึ่งบางส่วนอาจรวมถึงชื่อผู้ใช้และรหัสผ่าน
import java.util.prefs.Preferences;
public class DemoApplication {
Preferences preferences =
Preferences.userNodeForPackage(DemoApplication.class);
public void setCredentials(String username, String password) {
preferences.put("db_username", username);
preferences.put("db_password", password);
}
public String getUsername() {
return preferences.get("db_username", null);
}
public String getPassword() {
return preferences.get("db_password", null);
}
// your code here
}
ในรหัสด้านบนคุณสามารถเรียกใช้setCredentials
เมธอดได้หลังจากแสดงกล่องโต้ตอบถามหาชื่อผู้ใช้และรหัสผ่าน เมื่อคุณต้องการเชื่อมต่อกับฐานข้อมูลคุณสามารถใช้getUsername
และgetPassword
วิธีการเพื่อดึงค่าที่เก็บไว้ ข้อมูลรับรองการเข้าสู่ระบบจะไม่ถูกฮาร์ดโค้ดลงในไบนารีของคุณดังนั้นการแยกคอมไพล์จะไม่ก่อให้เกิดความเสี่ยงด้านความปลอดภัย
หมายเหตุสำคัญ:ไฟล์การกำหนดลักษณะเป็นเพียงไฟล์ XML ข้อความธรรมดา ตรวจสอบให้แน่ใจว่าคุณดำเนินการตามขั้นตอนที่เหมาะสมเพื่อป้องกันไม่ให้ผู้ใช้ที่ไม่ได้รับอนุญาตดูไฟล์ดิบ (สิทธิ์ UNIX, สิทธิ์ของ Windows, และอื่น ๆ ) ใน Linux อย่างน้อยก็ไม่ใช่ปัญหาเพราะการโทรPreferences.userNodeForPackage
จะสร้างไฟล์ XML ในโฮมไดเร็กทอรีของผู้ใช้ปัจจุบันซึ่งผู้ใช้รายอื่นไม่สามารถอ่านได้ ใน Windows สถานการณ์อาจแตกต่างออกไป
หมายเหตุสำคัญเพิ่มเติม:มีการอภิปรายมากมายในความคิดเห็นของคำตอบนี้และอื่น ๆ เกี่ยวกับสถาปัตยกรรมที่ถูกต้องสำหรับสถานการณ์นี้ คำถามเดิมไม่ได้กล่าวถึงบริบทที่ใช้แอปพลิเคชันจริงๆดังนั้นฉันจะพูดถึงสองสถานการณ์ที่ฉันคิดได้ ประการแรกคือกรณีที่บุคคลที่ใช้โปรแกรมรู้อยู่แล้ว (และได้รับอนุญาตให้รู้) ข้อมูลรับรองฐานข้อมูล ประการที่สองคือกรณีที่คุณซึ่งเป็นผู้พัฒนาพยายามเก็บข้อมูลรับรองฐานข้อมูลเป็นความลับจากบุคคลที่ใช้โปรแกรม
กรณีแรก: ผู้ใช้ได้รับอนุญาตให้ทราบข้อมูลรับรองการเข้าสู่ระบบฐานข้อมูล
ในกรณีนี้วิธีแก้ปัญหาที่ฉันกล่าวถึงข้างต้นจะได้ผล Preference
คลาสJava จะจัดเก็บชื่อผู้ใช้และรหัสผ่านเป็นข้อความธรรมดา แต่ไฟล์การกำหนดค่าตามความชอบจะสามารถอ่านได้โดยผู้ใช้ที่ได้รับอนุญาตเท่านั้น ผู้ใช้สามารถเปิดไฟล์ XML การกำหนดค่าตามความชอบและอ่านข้อมูลรับรองการเข้าสู่ระบบได้ แต่นั่นไม่ใช่ความเสี่ยงด้านความปลอดภัยเนื่องจากผู้ใช้ทราบข้อมูลรับรองที่จะเริ่มต้นด้วย
กรณีที่สอง: พยายามซ่อนข้อมูลรับรองการเข้าสู่ระบบจากผู้ใช้
นี่เป็นกรณีที่ซับซ้อนมากขึ้น: ผู้ใช้ไม่ควรทราบข้อมูลรับรองการเข้าสู่ระบบ แต่ยังคงต้องการเข้าถึงฐานข้อมูล ในกรณีนี้ผู้ใช้ที่เรียกใช้แอปพลิเคชันจะมีสิทธิ์เข้าถึงฐานข้อมูลโดยตรงซึ่งหมายความว่าโปรแกรมจำเป็นต้องทราบข้อมูลรับรองการเข้าสู่ระบบล่วงหน้า วิธีแก้ปัญหาที่ฉันกล่าวถึงข้างต้นไม่เหมาะสมสำหรับกรณีนี้ คุณสามารถจัดเก็บข้อมูลรับรองการเข้าสู่ระบบฐานข้อมูลในไฟล์การตั้งค่า แต่ผู้ใช้จะสามารถอ่านไฟล์นั้นได้เนื่องจากพวกเขาจะเป็นเจ้าของ ในความเป็นจริงไม่มีวิธีใดที่ดีในการใช้กรณีนี้อย่างปลอดภัย
กรณีที่ถูกต้อง: การใช้สถาปัตยกรรมหลายชั้น
วิธีที่ถูกต้องในการดำเนินการคือต้องมีชั้นกลางระหว่างเซิร์ฟเวอร์ฐานข้อมูลและแอปพลิเคชันไคลเอนต์ของคุณซึ่งจะตรวจสอบผู้ใช้แต่ละรายและอนุญาตให้ดำเนินการเฉพาะบางกลุ่ม ผู้ใช้แต่ละคนจะมีข้อมูลรับรองการเข้าสู่ระบบของตนเอง แต่ไม่ใช่สำหรับเซิร์ฟเวอร์ฐานข้อมูล ข้อมูลรับรองจะอนุญาตให้เข้าถึงเลเยอร์กลาง (ระดับตรรกะทางธุรกิจ) และจะแตกต่างกันสำหรับผู้ใช้แต่ละราย
ผู้ใช้ทุกคนจะมีชื่อผู้ใช้และรหัสผ่านของตนเองซึ่งสามารถเก็บไว้ในไฟล์ค่ากำหนดโดยไม่มีความเสี่ยงด้านความปลอดภัย สิ่งนี้เรียกว่าสถาปัตยกรรมสามชั้น (ระดับที่เป็นเซิร์ฟเวอร์ฐานข้อมูลเซิร์ฟเวอร์ตรรกะทางธุรกิจและแอปพลิเคชันไคลเอนต์) มันซับซ้อนกว่า แต่จริงๆแล้วเป็นวิธีที่ปลอดภัยที่สุดในการทำสิ่งนี้
ลำดับพื้นฐานของการดำเนินการคือ:
getInventoryList
.ทราบว่าในกระบวนการทั้งหมดโปรแกรมไคลเอนต์ไม่เคยเชื่อมต่อโดยตรงกับฐานข้อมูล ระดับตรรกะทางธุรกิจได้รับคำร้องขอจากผู้ใช้ที่ได้รับการพิสูจน์ตัวตนประมวลผลคำขอของไคลเอ็นต์สำหรับรายการสินค้าคงคลังจากนั้นจึงดำเนินการสืบค้น SQL เท่านั้น
ใส่รหัสผ่านลงในไฟล์ที่แอปพลิเคชันจะอ่าน อย่าฝังรหัสผ่านในไฟล์ต้นฉบับ ระยะเวลา
Ruby มีโมดูลที่ไม่ค่อยมีใครรู้จักชื่อDBI :: DBRCสำหรับการใช้งานดังกล่าว ฉันไม่สงสัยเลยว่า Java มีคุณสมบัติเทียบเท่า อย่างไรก็ตามมันไม่ใช่เรื่องยากที่จะเขียนอย่างใดอย่างหนึ่ง
คุณกำลังเขียนเว็บแอปพลิเคชันหรือไม่? ในกรณีนี้ให้ใช้ JNDI เพื่อกำหนดค่าภายนอกให้กับแอปพลิเคชัน ดูภาพรวมได้ที่นี่ :
JNDI ให้วิธีการที่สม่ำเสมอสำหรับแอปพลิเคชันในการค้นหาและเข้าถึงบริการระยะไกลผ่านเครือข่าย บริการระยะไกลอาจเป็นบริการขององค์กรใด ๆ รวมถึงบริการส่งข้อความหรือบริการเฉพาะแอปพลิเคชัน แต่แน่นอนว่าแอปพลิเคชัน JDBC สนใจบริการฐานข้อมูลเป็นหลัก เมื่อออบเจ็กต์ DataSource ถูกสร้างและลงทะเบียนด้วยบริการการตั้งชื่อ JNDI แอปพลิเคชันสามารถใช้ JNDI API เพื่อเข้าถึงออบเจ็กต์ DataSource นั้นซึ่งสามารถใช้เพื่อเชื่อมต่อกับแหล่งข้อมูลที่เป็นตัวแทนได้
ไม่ว่าคุณจะทำอะไรข้อมูลที่ละเอียดอ่อนจะถูกเก็บไว้ในบางไฟล์ เป้าหมายของคุณคือทำให้ยากที่สุดเท่าที่จะทำได้ คุณจะประสบความสำเร็จได้มากน้อยเพียงใดขึ้นอยู่กับโครงการความต้องการและความหนาของกระเป๋าเงินของ บริษัท ของคุณ
วิธีที่ดีที่สุดคืออย่าเก็บรหัสผ่านไว้ที่ใดก็ได้ สิ่งนี้ทำได้โดยใช้ฟังก์ชันแฮชเพื่อสร้างและจัดเก็บแฮชรหัสผ่าน:
hash("hello") = 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
hash("hbllo") = 58756879c05c68dfac9866712fad6a93f8146f337a69afe7dd238f3364946366
อัลกอริทึมแฮชเป็นฟังก์ชันทางเดียว พวกเขาเปลี่ยนข้อมูลจำนวนเท่าใดก็ได้ให้เป็น "ลายนิ้วมือ" ที่มีความยาวคงที่ซึ่งไม่สามารถย้อนกลับได้ นอกจากนี้ยังมีคุณสมบัติที่หากอินพุตเปลี่ยนแปลงไปแม้แต่นิดเดียวแฮชที่ได้จะแตกต่างกันอย่างสิ้นเชิง (ดูตัวอย่างด้านบน) วิธีนี้เหมาะสำหรับการป้องกันรหัสผ่านเนื่องจากเราต้องการจัดเก็บรหัสผ่านในรูปแบบที่ป้องกันแม้ว่าไฟล์รหัสผ่านจะถูกบุกรุก แต่ในขณะเดียวกันเราต้องสามารถตรวจสอบได้ว่ารหัสผ่านของผู้ใช้นั้นถูกต้อง
หมายเหตุที่ไม่เกี่ยวข้อง:ในสมัยก่อนอินเทอร์เน็ตเมื่อคุณคลิกลิงก์ "ลืมรหัสผ่าน" เว็บไซต์ต่างๆจะส่งรหัสผ่านข้อความธรรมดาของคุณให้คุณทางอีเมล พวกเขาอาจเก็บข้อมูลเหล่านั้นไว้ในฐานข้อมูลที่ไหนสักแห่ง เมื่อแฮกเกอร์เข้าถึงฐานข้อมูลได้พวกเขาจะสามารถเข้าถึงรหัสผ่านทั้งหมดได้ เนื่องจากผู้ใช้จำนวนมากจะใช้รหัสผ่านเดียวกันในหลาย ๆ เว็บไซต์จึงเป็นปัญหาด้านความปลอดภัยอย่างมาก โชคดีที่ปัจจุบันนี้ไม่ใช่วิธีปฏิบัติทั่วไป
มาถึงคำถาม: วิธีที่ดีที่สุดในการจัดเก็บรหัสผ่านคืออะไร? ฉันจะพิจารณาว่าโซลูชันนี้ (การตรวจสอบความถูกต้องและบริการจัดการผู้ใช้ของสตอร์มพา ธ )เป็นวิธีที่ดีมาก:
เห็นได้ชัดว่าคุณไม่ใช่ Google หรือธนาคารดังนั้นนี่จึงเป็นวิธีแก้ปัญหาที่มากเกินไปสำหรับคุณ แต่แล้วคำถามก็มาถึง: โครงการของคุณต้องการความปลอดภัยเท่าไรคุณมีเวลาและเงินเท่าไหร่?
สำหรับแอปพลิเคชันจำนวนมากแม้ว่าจะไม่แนะนำให้เก็บรหัสผ่านแบบฮาร์ดโค้ดไว้ในโค้ดอาจเป็นวิธีแก้ปัญหาที่ดีพอ อย่างไรก็ตามด้วยการเพิ่มขั้นตอนการรักษาความปลอดภัยเพิ่มเติมจากรายการด้านบนสองสามขั้นตอนอย่างง่ายดายคุณสามารถทำให้แอปพลิเคชันของคุณปลอดภัยมากขึ้น
ตัวอย่างเช่นสมมติว่าขั้นตอนที่ 1 ไม่ใช่โซลูชันที่ยอมรับได้สำหรับโครงการของคุณ คุณไม่ต้องการให้ผู้ใช้ป้อนรหัสผ่านทุกครั้งหรือคุณไม่ต้องการ / ต้องการให้ผู้ใช้ทราบรหัสผ่าน คุณยังคงมีข้อมูลที่ละเอียดอ่อนอยู่ที่ไหนสักแห่งและคุณต้องการปกป้องสิ่งนี้ คุณมีแอปพลิเคชั่นที่เรียบง่ายไม่มีเซิร์ฟเวอร์ที่จะจัดเก็บไฟล์ของคุณหรือเป็นการสร้างความยุ่งยากให้กับโครงการของคุณมากเกินไป แอปพลิเคชันของคุณทำงานบนสภาพแวดล้อมที่ไม่สามารถจัดเก็บไฟล์ได้อย่างปลอดภัย นี่เป็นหนึ่งในกรณีที่แย่ที่สุด แต่ยังคงมีมาตรการรักษาความปลอดภัยเพิ่มเติมคุณสามารถมีโซลูชันที่ปลอดภัยกว่านี้ ตัวอย่างเช่นคุณสามารถเก็บข้อมูลที่ละเอียดอ่อนไว้ในไฟล์และคุณสามารถเข้ารหัสไฟล์ได้ คุณสามารถเข้ารหัสคีย์ส่วนตัวแบบฮาร์ดโค้ดในรหัสได้ คุณสามารถทำให้โค้ดสับสนได้ดังนั้นคุณจึงทำให้บางคนแตกรหัสได้ยากขึ้นเล็กน้อยลิงค์นี้ . (ฉันอยากจะเตือนคุณอีกครั้งว่านี่ไม่ปลอดภัย 100% แฮ็กเกอร์อัจฉริยะที่มีความรู้และเครื่องมือที่ถูกต้องสามารถแฮ็กสิ่งนี้ได้ แต่ตามความต้องการและความต้องการของคุณนี่อาจเป็นทางออกที่ดีพอสำหรับคุณ)
คำถามนี้แสดงวิธีการจัดเก็บรหัสผ่านและข้อมูลอื่น ๆ ในไฟล์ที่เข้ารหัส: Java 256-bit AES Password-Based Encryption
MD5 เป็นอัลกอริธึมแฮชไม่ใช่อัลกอริทึมการเข้ารหัสในระยะสั้นคุณไม่สามารถย้อนกลับการแฮชคุณสามารถเปรียบเทียบ ควรใช้เมื่อจัดเก็บข้อมูลการรับรองความถูกต้องของผู้ใช้ไม่ใช่ db ชื่อผู้ใช้และรหัสผ่าน ชื่อผู้ใช้ db และ pwd ควรเข้ารหัสและเก็บไว้ในไฟล์ config เพื่อให้น้อยที่สุด