หมวดหมู่ OWASP: MASVS-CRYPTO: วิทยาการเข้ารหัส
ภาพรวม
ตัวสร้างตัวเลขสุ่มเทียม (PRNG) คืออัลกอริทึมที่สร้างลำดับตัวเลขที่คาดการณ์ได้โดยอิงตามค่าเริ่มต้นที่เรียกว่าค่าเริ่มต้น ลำดับตัวเลขที่สร้างโดย PRNG มีคุณสมบัติโดยประมาณเหมือนกับลำดับตัวเลขสุ่มจริง แต่สร้างได้เร็วกว่าและใช้การคำนวณน้อยกว่า
กล่าวอีกนัยหนึ่งคือ PRNG มีการรับประกันสูงกว่า RNG ที่อ่อนแอ (เช่น
java.math.Random) ในแง่ของความสม่ำเสมอของการกระจายเอนโทรปี ซึ่งจำลอง
ลำดับตัวเลขสุ่มอย่างแท้จริง การสร้างตัวเลขสุ่มอย่างแท้จริงต้องใช้อุปกรณ์เฉพาะทางและมักอยู่นอกขอบเขตของการพัฒนาปกติ เอกสารนี้ไม่ครอบคลุมการสร้างตัวเลขสุ่มอย่างแท้จริง และมุ่งเน้นเฉพาะ PRNG เนื่องจากเป็นวิธีการมาตรฐานที่ใช้กัน
ช่องโหว่ PRNG ที่ไม่รัดกุมจะเกิดขึ้นเมื่อนักพัฒนาแอปใช้ PRNG ปกติเพื่อ วัตถุประสงค์ในการเข้ารหัสลับ แทนที่จะใช้ PRNG ที่มีความปลอดภัยแบบเข้ารหัสลับ (CSPRNG) CSPRNG มีข้อกำหนดที่เข้มงวดกว่า และเมื่อไม่ทราบค่าเริ่มต้น จะต้องให้ ผู้โจมตีได้เปรียบเพียงเล็กน้อยในการแยกความแตกต่างของลำดับเอาต์พุต จากลำดับแบบสุ่มจริง
ผู้โจมตียังอาจคาดเดาลำดับตัวเลขที่สร้างขึ้นได้เมื่อใช้ Seed ที่คาดเดาได้ เช่น Seed ที่นักพัฒนาซอฟต์แวร์ฮาร์ดโค้ดไว้ เพื่อเริ่มต้น PRNG หรือ CSPRNG เนื่องจากผู้โจมตีสามารถคาดเดา Seed และคาดเดาเอาต์พุตที่สร้างโดย PRNG ได้
ผลกระทบ
หากใช้ PRNG ที่ไม่ปลอดภัยทางคริปโตกราฟีในบริบทด้านความปลอดภัย เช่น การตรวจสอบสิทธิ์ ผู้โจมตีอาจคาดเดาตัวเลขที่สร้างขึ้นแบบสุ่ม และเข้าถึงข้อมูลหรือฟีเจอร์ที่มีสิทธิ์ได้
การลดปัญหา
ทั่วไป
- ใช้
java.security.SecureRandomเมื่อมีผลกระทบด้านความปลอดภัย - ใช้
java.util.Randomสำหรับกรณีอื่นๆ - อย่าใช้
Math.random!
java.security.SecureRandom
แนะนำสำหรับการใช้งานด้านความปลอดภัย หากเวอร์ชันเคอร์เนล Linux เป็น 5.17 ขึ้นไปหรือ ยอมรับการบล็อกเธรดได้ ให้รอจนกว่าจะมีการสะสมเอนโทรปีมากพอ ก่อนที่จะสร้างเลขสุ่ม (เช่น ใช้ /dev/random) โดยเรียกใช้ getInstanceStrong()
Kotlin
val rand = SecureRandom.getInstanceStrong()
Java
SecureRandom rand = SecureRandom.getInstanceStrong();
มิฉะนั้น ในเคอร์เนล Linux เวอร์ชันก่อน 5.17 เมื่อการบล็อกเทรดเป็นยอมรับไม่ได้เมื่อสร้างเลขสุ่ม ให้เรียกใช้เครื่องมือสร้าง SecureRandom โดยตรง
Kotlin
import java.security.SecureRandom
object generateRandom {
@JvmStatic
fun main(args: Array<String>) {
// Create instance of SecureRandom class
val rand = SecureRandom()
// Generate random integers in range 0 to 999
val rand_int = rand.nextInt(1000)
// Use rand_int for security & authentication
}
}
Java
import java.security.SecureRandom;
public class generateRandom {
public static void main(String args[])
{
// Create instance of SecureRandom class
SecureRandom rand = new SecureRandom();
// Generate random integers in range 0 to 999
int rand_int = rand.nextInt(1000);
// Use rand_int for security & authentication
}
}
SecureRandom จะรับค่าเริ่มต้นจาก /dev/urandom และจะใช้โดยอัตโนมัติ
เมื่อสร้างหรือรับออบเจ็กต์ จึงไม่จำเป็นต้อง
ระบุค่าเริ่มต้นสำหรับ PRNG อย่างชัดเจน โดยทั่วไป เราไม่แนะนำให้ใช้ SecureRandom
แบบดีเทอร์มินิสติก (โดยเฉพาะหากการดำเนินการนี้ทำให้ต้องฮาร์ดโค้ดค่าเริ่มต้น ซึ่ง
ทุกคนที่คอมไพล์แอปจะเห็น) นักพัฒนาแอปที่ต้องการสร้างเอาต์พุตแบบสุ่มเทียมที่ทำซ้ำได้ควรใช้ Primitive ที่เหมาะสมกว่า เช่น HMAC, HKDF และ SHAKE
java.util.Random
หลีกเลี่ยงเพื่อวัตถุประสงค์ด้านความปลอดภัย / การตรวจสอบสิทธิ์ ใช้เพื่อวัตถุประสงค์อื่นๆ ได้
Kotlin
import java.util.Random
object generateRandom {
@JvmStatic
fun main(args: Array<String>) {
// Create instance of SecureRandom class
val rand = Random()
// Generate random integers in range 0 to 999
val rand_int = rand.nextInt(1000)
}
}
Java
import java.util.Random;
public class generateRandom {
public static void main(String args[])
{
// Create instance of Random class
Random rand = new Random();
// Generate random integers in range 0 to 999
int rand_int = rand.nextInt(1000);
}
}
แหล่งข้อมูล
- java.security.SecureRandom
- java.util.Random
- Math.random
- CWE ที่คาดการณ์ได้
- CWE ของ PRNG ที่มีความแข็งแรงทางวิทยาการเข้ารหัสต่ำ
- Java Secure Random
- Java Random เทียบกับ SecureRandom
- วิธีใช้ SecureRandom
- คำแนะนำด้านความปลอดภัยสำหรับ PRNG ของ Python
- ข้อมูลสรุปการจัดเก็บข้อมูลที่เข้ารหัสของ OWASP
- CVE-2013-6386: ช่องโหว่ PRNG ที่อ่อนแอใน Drupal
- CVE-2006-3419: ช่องโหว่ PRNG ที่ไม่ปลอดภัยใน Tor
- CVE-2008-4102: Predictable Seed ใน Joomla
- แพตช์แบบสุ่มของเคอร์เนล Linux