หมวดหมู่ OWASP: MASVS-CRYPTO: วิทยาการเข้ารหัสลับ
ภาพรวม
ตัวสร้างเลขสุ่มเทียม (Pseudorandom Number Generator หรือ PRNG) คืออัลกอริทึมที่สร้างลำดับตัวเลขที่คาดการณ์ได้โดยอิงตามค่าเริ่มต้นที่เรียกว่า Seed ลำดับตัวเลขที่สร้างโดย PRNG มีคุณสมบัติโดยประมาณ เหมือนกับลำดับตัวเลขสุ่มจริง แต่สร้างได้เร็วกว่าและใช้ทรัพยากรการคำนวณน้อยกว่า
กล่าวอีกนัยหนึ่งคือ PRNG มีการรับประกันสูงกว่า RNG ที่ไม่ปลอดภัย (เช่น java.math.Random) ในแง่ของความสม่ำเสมอของการกระจายเอนโทรปี ซึ่งจำลองลำดับตัวเลขสุ่มจริง การสร้างตัวเลขสุ่มจริงต้องใช้อุปกรณ์เฉพาะทางและมักจะอยู่นอกขอบเขตของการพัฒนาปกติ เอกสารนี้ไม่ได้กล่าวถึงการสร้างตัวเลขสุ่มจริง และมุ่งเน้นเฉพาะ PRNG เนื่องจากเป็นวิธีการมาตรฐานที่ใช้
ช่องโหว่ของ PRNG ที่ไม่ปลอดภัยเกิดขึ้นเมื่อนักพัฒนาแอปใช้ PRNG ทั่วไปเพื่อวัตถุประสงค์ด้านวิทยาการเข้ารหัสลับ แทนที่จะใช้ PRNG ที่ปลอดภัยด้านวิทยาการเข้ารหัสลับ (Cryptographically-Secure PRNG หรือ CSPRNG) CSPRNG มีข้อกำหนดที่เข้มงวดกว่า และเมื่อไม่ทราบ Seed แล้ว CSPRNG จะต้องให้ข้อได้เปรียบแก่ผู้โจมตีเพียงเล็กน้อยในการแยกความแตกต่างของลำดับเอาต์พุตจากลำดับสุ่มจริง
ผู้โจมตีอาจสามารถคาดเดาลำดับตัวเลขที่สร้างขึ้นได้เมื่อใช้ Seed ที่คาดการณ์ได้ เช่น Seed ที่นักพัฒนาแอปฮาร์ดโค้ดไว้ เพื่อเริ่มต้น PRNG หรือ CSPRNG เนื่องจากผู้โจมตีสามารถคาดเดา Seed และคาดการณ์เอาต์พุตที่สร้างโดย PRNG ได้
ผลกระทบ
หากใช้ PRNG ที่ไม่ปลอดภัยด้านวิทยาการเข้ารหัสลับในบริบทด้านความปลอดภัย เช่น การตรวจสอบสิทธิ์ ผู้โจมตีอาจสามารถคาดเดาตัวเลขที่สร้างขึ้นแบบสุ่มและเข้าถึงข้อมูลหรือฟีเจอร์ที่มีสิทธิ์ได้
การบรรเทา
ทั่วไป
- ใช้
java.security.SecureRandomเมื่อมี ผลกระทบด้านความปลอดภัย - ใช้
java.util.Randomในกรณีอื่นๆ - ห้าม ใช้
Math.random!
java.security.SecureRandom
แนะนำ ให้ใช้เพื่อความปลอดภัย ใน Android, SecureRandom.getInstanceStrong() เทียบเท่ากับการรับ SHA1PRNG จาก AndroidOpenSSL ซึ่งไม่ได้แมปกับการใช้งาน /dev/random ที่บล็อก หากต้องการใช้ ให้เรียก getInstanceStrong() ดังนี้
Kotlin
val rand = SecureRandom.getInstanceStrong()
Java
SecureRandom rand = SecureRandom.getInstanceStrong();
มิฉะนั้น ใน Linux Kernel เวอร์ชันก่อน 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 จะรับ Seed เริ่มต้นจาก /dev/urandom และจะใช้โดยอัตโนมัติเมื่อสร้างหรือรับออบเจ็กต์ จึงไม่จำเป็นต้อง Seed PRNG อย่างชัดเจน โดยทั่วไป เราไม่แนะนำให้ใช้ SecureRandom ในลักษณะที่กำหนดได้ (โดยเฉพาะอย่างยิ่งหากการใช้ดังกล่าวทำให้เกิดการฮาร์ดโค้ดค่า Seed ซึ่งทุกคนที่คอมไพล์แอปกลับสามารถดูได้) นักพัฒนาแอปที่ต้องการสร้างเอาต์พุตแบบสุ่มเทียมที่ทำซ้ำได้ควรใช้ 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 ของ Seed ที่คาดการณ์ได้
- CWE ของ PRNG ที่ไม่ปลอดภัยด้านวิทยาการเข้ารหัสลับ
- Java Secure Random
- Java Random เทียบกับ SecureRandom
- วิธีใช้ SecureRandom
- คำแนะนำด้านความปลอดภัยของ Python PRNG
- ข้อมูลสรุปเกี่ยวกับพื้นที่เก็บข้อมูลที่เข้ารหัสลับของ OWASP
- CVE-2013-6386: ช่องโหว่ของ PRNG ที่ไม่ปลอดภัยใน Drupal
- CVE-2006-3419: ช่องโหว่ของ PRNG ที่ไม่ปลอดภัยใน Tor
- CVE-2008-4102: Seed ที่คาดการณ์ได้ใน Joomla
- แพตช์สุ่มของ Linux Kernel