目录
0x00 简介
0x01 随机数
概述
分类
特性
伪随机数的生成
应用场景
0x02 随机数的安全性
随机数的安全风险
漏洞实例
1.应该使用随机数而未使用随机数
2.使用弱伪随机数
1) 密码取回
2) 其他随机数验证场景
安全建议
首页 后端开发 php教程 聊一聊随机数安全

聊一聊随机数安全

Jun 20, 2016 pm 12:27 PM


0x00 简介

和朋友聊到一个比较有意思的现象,在最近两年的校招面试中,大部分同学连一点基础的密码学知识都没有, 即便是有一些渗透功底的同学。

所以这里想和大家聊一些简单的密码学基础知识,不涉及算法实现,更多的是和常见的漏洞场景联系起来,让问题更容易理解,有点抛砖引玉的意思。

本文主要聊一下随机数,随机数其实是非常广泛的,可以说也是密码技术的基础。

对随机数的使用不当很可能会导致一些比较严重的安全问题, 并且这些安全问题通常会比较隐蔽。

0x01 随机数

概述

随机数在计算机应用中使用的比较广泛,最为熟知的便是在密码学中的应用。本文主要是讲解随机数使用导致的一些Web安全风。

我们先简单了解一下随机数



分类

随机数分为真随机数和伪随机数,我们程序使用的基本都是伪随机数,其中伪随机又分为强伪随机数和弱伪随机数。

  1. 真随机数 ,通过物理实验得出,比如掷钱币、骰子、转轮、使用电子元件的噪音、核裂变等

  2. 伪随机数 ,通过一定算法和种子得出。软件实现的是伪随机数

    1. 强伪随机数 ,难以预测的随机数

    2. 弱伪随机数 ,易于预测的随机数

特性

随机数有3个特性,具体如下:

  1. 随机性 :不存在统计学偏差,是完全杂乱的数列

  2. 不可预测性 :不能从过去的数列推测出下一个出现的数

  3. 不可重现性 :除非将数列本身保存下来,否则不能重现相同的数列

随机数的特性和随机数的分类有一定的关系,比如,弱伪随机数只需要满足随机性即可,而强位随机数需要满足随机性和不可预测性,真随机数则需要同时满足3个特性。

引发安全问题的关键点在于不可预测性。

伪随机数的生成

我们平常软件和应用实现的都是伪随机数,所以本文的重点也就是伪随机数。

伪随机数的生成实现一般是 算法+种子

具体的伪随机数生成器PRNG一般有:

  1. 线性同余法

  2. 单向散列函数法

  3. 密码法

  4. ANSI X9.17

比较常用的一般是线性同余法,比如我们熟知的C语言的rand库和Java的java.util.Random类,都采用了线性同余法生成随机数。

应用场景

随机数的应用场景比较广泛,以下是随机数常见的应用场景:

  • 验证码生成

  • 抽奖活动

  • UUID生成

  • SessionID生成

  • Token生成

    • CSRF Token

    • 找回密码Token

  • 游戏(随机元素的生成)

    • 洗牌

    • 俄罗斯方块出现特定形状的序列

    • 游戏爆装备

  • 密码应用场景

    • 生成密钥:对称密码,消息认证

    • 生成密钥对:公钥密码,数字签名

    • 生成IV: 用于分组密码的CBC,CFB和OFB模式

    • 生成nonce: 用于防御重放攻击; 分组密码的CTR模式

    • 生成盐:用于基于口令的密码PBE等

0x02 随机数的安全性

相比其他密码技术,随机数很少受到关注,但随机数在密码技术和计算机应用中是非常重要的,不正确的使用随机数会导致一系列的安全问题。

随机数的安全风险

随机数导致的安全问题一般有两种

  1. 应该使用随机数,开发者并 没有使用随机数

  2. 应该使用强伪随机数,开发者 使用了弱伪随机数

第一种情况,简单来讲,就是我们需要一个随机数,但是开发者没有使用随机数,而是指定了一个常量。当然,很多人会义愤填膺的说,sb才会不用随机数。但是,请不要忽略我朝还是有很多的。主要有两个场景:

开发者缺乏基础常识不知道要用随机数;

一些应用场景和框架,接口文档不完善或者开发者没有仔细阅读等原因。

比如找回密码的token,需要一个伪随机数,很多业务直接根据用户名生成token;

比如OAuth2.0中需要第三方传递一个state参数作为CSRF Token防止CSRF攻击,很多开发者根本不使用这个参数,或者是传入一个固定的值。由于认证方无法对这个值进行业务层面有效性的校验,导致了OAuth的CSRF攻击。

第二种情况,主要区别就在于伪随机数的强弱了,大部分(所有?)语言的API文档中的基础库(常用库)中的random库都是弱伪随机,很多开发自然就直接使用。但是,最重要也最致命的是, 弱伪随机数是不能用于密码技术的

还是第一种情况中的找回密码场景,关于token的生成, 很多开发使用了时间戳作为随机数(md5(时间戳),md5(时间戳+用户名)),但是由于时间戳是可以预测的,很容易就被猜解。 不可预测性是区分弱伪随机数和强伪随机数的关键指标

当然,除了以上两种情况,还有一些比较特别的情况,通常情况下比较少见,但是也不排除:

  1. 种子的泄露,算法很多时候是公开的,如果种子泄露了,相当于随机数已经泄露了;

  2. 随机数池不足。这个严格来说也属于弱伪随机数,因为随机数池不足其实也导致了随机数是可预测的,攻击者可以直接暴力破解。

漏洞实例

wooyun上有很多漏洞,还蛮有意思的,都是和随机数有关的。

PS:个人实力有限,以下实例基本都来自wooyun漏洞实例,在这里谢谢各位大牛,如有侵权,请联系删除。

1.应该使用随机数而未使用随机数

Oauth2.0的这个问题特别经典,除了wooyun实例列出来的,其实很多厂商都有这个问题。

Oauth2.0中state参数要求第三方应用的开发者传入一个CSRF Token(随机数),如果没有传入或者传入的不是随机数,会导致CSRF登陆任意帐号:

  1. 唯品会账号相关漏洞可通过csrf登录任意账号

  2. 人人网-百度OAuth 2.0 redirect_uir CSRF 漏洞

2.使用弱伪随机数

1) 密码取回

很多密码找回的场景,会发送给用户邮件一个url,中间包含一个token,这个token如果猜测,那么就可以找回其他用户的密码。

1.Shopex 4.8.5密码取回处新生成密码可预测漏洞

直接使用了时间函数microtime()作为随机数,然后获取MD5的前6位。

#!phpsubstr(md5(print_r(microtime(),true)),0,6);
登录后复制

PHP 中microtime()的值除了当前服务器的秒数外,还有微秒数,微妙数的变化范围在0.000000 -- 0.999999 之间,一般来说,服务器的时间可以通过HTTP返回头的DATE字段来获取,因此我们只需要遍历这1000000可能值即可。但我们要使用暴力破解的方式发起1000000次网络请求的话,网络请求数也会非常之大。可是shopex非常贴心的在生成密码前再次将microtime() 输出了一次:

#!php$messenger = &$this->system->loadModel('system/messenger');echo microtime()."
";
登录后复制

   

2. 奇虎360任意用户密码修改

直接是MD5(unix时间戳)

3. 涂鸦王国弱随机数导致任意用户劫持漏洞,附测试POC

关于找回密码随机数的问题强烈建议大家参考拓哥的11年的文章 《利用系统时间可预测破解java随机数| 空虚浪子心的灵魂》

2) 其他随机数验证场景

  • CmsEasy最新版暴力注入(加解密缺陷/绕过防注入)

弱伪随机数被绕过

  • Espcms v5.6 暴力注入

Espcms中一处SQL注入漏洞的利用,利用时发现espcms对传值有加密并且随机key,但是这是一个随机数池固定的弱伪随机数,可以被攻击者遍历绕过

  • Destoon B2B 2014-05-21最新版绕过全局防御暴力注入(官方Demo可重现)

使用了microtime()作为随机数,可以被预测暴力破解

Android 4.4之前版本的Java加密架构(JCA)中使用的Apache Harmony 6.0M3及其之前版本的SecureRandom实现存在安全漏洞,具体位于 classlib/modules/security/src/main/java/common/org/apache/harmony/security/provider/crypto/SHA1PRNG_SecureRandomImpl.java

类的engineNextBytes函数里,当用户没有提供用于产生随机数的种子时,程序不能正确调整偏移量,导致PRNG生成随机序列的过程可被预测。

  • Android SecureRandom漏洞详解

安全建议

上面讲的随机数基础和漏洞实例更偏重是给攻击者一些思路,这里更多的是一些防御和预防的建议。

  1. 业务场景需要使用随机数,一定要使用随机数,比如Token的生成;

  2. 随机数要足够长,避免暴力破解;

  3. 保证不同用处的随机数使用不同的种子

  4. 对安全性要求高的随机数(如密码技术相关)禁止使用的弱伪随机数:

    1. 不要使用时间函数作为随机数(很多程序员喜欢用时间戳) Java:system.currenttimemillis() php:microtime()

    2. 不要使用弱伪随机数生成器 Java: java.util.Random PHP: rand() 范围很小,32767 PHP: mt_rand() 存在缺陷

  5. 强伪随机数CSPRNG(安全可靠的伪随机数生成器(Cryptographically Secure Pseudo-Random Number Generator)的各种参考

Platform CSPRNG
PHP mcrypt_create_iv, openssl_random_pseudo_bytes
Java java.security.SecureRandom
Dot NET (C#, VB) System.Security.Cryptography.RNGCryptoServiceProvider
Ruby SecureRandom
Python os.urandom
Perl Math::Random::Secure
C/C++ (Windows API) CryptGenRandom
Any language on GNU/Linux or Unix Read from /dev/random or /dev/urandom

6.强伪随机数生成(不建议开发自己实现)

产生高强度的随机数,有两个重要的因素:种子和算法。算法是可以有很多的,通常如何选择种子是非常关键的因素。 如Random,它的种子是System.currentTimeMillis(),所以它的随机数都是可预测的, 是弱伪随机数。

强伪随机数的生成思路:收集计算机的各种信息,键盘输入时间,内存使用状态,硬盘空闲空间,IO延时,进程数量,线程数量等信息,CPU时钟,来得到一个近似随机的种子,主要是达到不可预测性。

以上就是聊一聊随机数安全的内容,更多相关内容请关注PHP中文网(www.php.cn)!


本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

在PHP API中说明JSON Web令牌(JWT)及其用例。 在PHP API中说明JSON Web令牌(JWT)及其用例。 Apr 05, 2025 am 12:04 AM

JWT是一种基于JSON的开放标准,用于在各方之间安全地传输信息,主要用于身份验证和信息交换。1.JWT由Header、Payload和Signature三部分组成。2.JWT的工作原理包括生成JWT、验证JWT和解析Payload三个步骤。3.在PHP中使用JWT进行身份验证时,可以生成和验证JWT,并在高级用法中包含用户角色和权限信息。4.常见错误包括签名验证失败、令牌过期和Payload过大,调试技巧包括使用调试工具和日志记录。5.性能优化和最佳实践包括使用合适的签名算法、合理设置有效期、

会话如何劫持工作,如何在PHP中减轻它? 会话如何劫持工作,如何在PHP中减轻它? Apr 06, 2025 am 12:02 AM

会话劫持可以通过以下步骤实现:1.获取会话ID,2.使用会话ID,3.保持会话活跃。在PHP中防范会话劫持的方法包括:1.使用session_regenerate_id()函数重新生成会话ID,2.通过数据库存储会话数据,3.确保所有会话数据通过HTTPS传输。

描述扎实的原则及其如何应用于PHP的开发。 描述扎实的原则及其如何应用于PHP的开发。 Apr 03, 2025 am 12:04 AM

SOLID原则在PHP开发中的应用包括:1.单一职责原则(SRP):每个类只负责一个功能。2.开闭原则(OCP):通过扩展而非修改实现变化。3.里氏替换原则(LSP):子类可替换基类而不影响程序正确性。4.接口隔离原则(ISP):使用细粒度接口避免依赖不使用的方法。5.依赖倒置原则(DIP):高低层次模块都依赖于抽象,通过依赖注入实现。

在PHPStorm中如何进行CLI模式的调试? 在PHPStorm中如何进行CLI模式的调试? Apr 01, 2025 pm 02:57 PM

在PHPStorm中如何进行CLI模式的调试?在使用PHPStorm进行开发时,有时我们需要在命令行界面(CLI)模式下调试PHP�...

如何在系统重启后自动设置unixsocket的权限? 如何在系统重启后自动设置unixsocket的权限? Mar 31, 2025 pm 11:54 PM

如何在系统重启后自动设置unixsocket的权限每次系统重启后,我们都需要执行以下命令来修改unixsocket的权限:sudo...

解释PHP中的晚期静态绑定(静态::)。 解释PHP中的晚期静态绑定(静态::)。 Apr 03, 2025 am 12:04 AM

静态绑定(static::)在PHP中实现晚期静态绑定(LSB),允许在静态上下文中引用调用类而非定义类。1)解析过程在运行时进行,2)在继承关系中向上查找调用类,3)可能带来性能开销。

如何用PHP的cURL库发送包含JSON数据的POST请求? 如何用PHP的cURL库发送包含JSON数据的POST请求? Apr 01, 2025 pm 03:12 PM

使用PHP的cURL库发送JSON数据在PHP开发中,经常需要与外部API进行交互,其中一种常见的方式是使用cURL库发送POST�...

See all articles