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

以是这里想和大家聊一些大略的密码学根本知识,不涉及算法实现,更多的是和常见的漏洞场景联系起来,让问题更随意马虎理解,有点抛砖引玉的意思。

本文紧张聊一下随机数,随机数实在是非常广泛的,可以说也是密码技能的根本。

phpmtrand漏洞WEB 平安之随机数平安 Node.js

对随机数的利用不当很可能会导致一些比较严重的安全问题, 并且这些安全问题常日会比较暗藏。

0x01 随机数

概述

随机数在打算机运用中利用的比较广泛,最为熟知的便是在密码学中的运用。
本文紧张是讲解随机数利用导致的一些Web安全风。

我们先大略理解一下随机数

分类

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

真随机数,通过物理实验得出,比如掷泉币、骰子、转轮、利用电子元件的噪音、核裂变等伪随机数,通过一定算法和种子得出。
软件实现的是伪随机数 强伪随机数,难以预测的随机数弱伪随机数,易于预测的随机数特性

随机数有3个特性,详细如下:

随机性:不存在统计学偏差,是完备凌乱的数列不可预测性:不能从过去的数列推测出下一个涌现的数不可重现性:除非将数列本身保存下来,否则不能重现相同的数列

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

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

伪随机数的天生

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

伪随机数的天生实现一样平常是算法+种子。

详细的伪随机数天生器PRNG一样平常有:

线性同余法单向散列函数法密码法ANSI X9.17

比较常用的一样平常是线性同余法,比如我们熟知的C措辞的rand库和Java的java.util.Random类,都采取了线性同余法天生随机数。

运用处景

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

验证码天生抽奖活动UUID天生SessionID天生Token天生 CSRF Token找回密码Token游戏(随机元素的天生) 洗牌俄罗斯方块涌现特定形状的序列游戏爆装备密码运用处景 天生密钥:对称密码,认证天生密钥对:公钥密码,数字署名天生IV: 用于分组密码的CBC,CFB和OFB模式天生nonce: 用于防御重放攻击; 分组密码的CTR模式天生盐:用于基于口令的密码PBE等。

0x02 随机数的安全性

比较其他密码技能,随机数很少受到关注,但随机数在密码技能和打算机运用中是非常主要的,禁绝确的利用随机数会导致一系列的安全问题。

随机数的安全风险

随机数导致的安全问题一样平常有两种

该当利用随机数,开拓者并没有利用随机数;该当利用强伪随机数,开拓者利用了弱伪随机数。

第一种情形,大略来讲,便是我们须要一个随机数,但是开拓者没有利用随机数,而是指定了一个常量。
当然,很多人会义愤填膺的说,sb才会不用随机数。
但是,请不要忽略我朝还是有很多的。
紧张有两个场景:

开拓者缺少根本知识不知道要用随机数;

一些运用处景和框架,接口文档不完善或者开拓者没有仔细阅读等缘故原由。

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

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

第二种情形,紧张差异就在于伪随机数的强弱了,大部分(所有?)措辞的API文档中的根本库(常用库)中的random库都是弱伪随机,很多开拓自然就直策应用。
但是,最主要也最致命的是,弱伪随机数是不能用于密码技能的。

还是第一种情形中的找回密码场景,关于token的天生, 很多开拓利用了韶光戳作为随机数(md5(韶光戳),md5(韶光戳+用户名)),但是由于韶光戳是可以预测的,很随意马虎就被猜解。
不可预测性是区分弱伪随机数和强伪随机数的关键指标。

当然,除了以上两种情形,还有一些比较特殊的情形,常日情形下比较少见,但是也不用除:

种子的透露,算法很多时候是公开的,如果种子透露了,相称于随机数已经透露了;随机数池不敷。
这个严格来说也属于弱伪随机数,由于随机数池不敷实在也导致了随机数是可预测的,攻击者可以直接暴力破解。
漏洞实例

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

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

1.该当利用随机数而未利用随机数

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

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

唯品会账号干系漏洞可通过csrf登录任意账号大家网-百度OAuth 2.0 redirect_uir CSRF 漏洞

2.利用弱伪随机数

1) 密码取回

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

1.Shopex4.8.5密码取回处新天生密码可预测漏洞

直策应用了韶光函数microtime作为随机数,然后获取MD5的前6位。

?

1

#!phpsubstr(md5(print_r(microtime,true)),0,6);

PHP 中microtime的值除了当前做事器的秒数外,还有微秒数,奇妙数的变革范围在0.000000 -- 0.999999 之间,一样平常来说,做事器的韶光可以通过HTTP返转头的DATE字段来获取,因此我们只须要遍历这1000000可能值即可。
但我们要利用暴力破解的办法发起1000000次网络要求的话,网络要求数也会非常之大。
可是shopex非常知心的在天生密码前再次将microtime 输出了一次:

2

#!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 B2B2014-05-21最新版绕过全局防御暴力注入(官方Demo可重现)

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

Android4.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漏洞详解安全建议

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

业务场景须要利用随机数,一定要利用随机数,比如Token的天生;随机数要足够长,避免暴力破解;担保不同用途的随机数利用不同的种子对安全性哀求高的随机数(如密码技能干系)禁止利用的弱伪随机数: 不要利用韶光函数作为随机数(很多程序员喜好用韶光戳) Java:system.currenttimemillis php:microtime不要利用弱伪随机数天生器 Java: java.util.Random PHP: rand 范围很小,32767 PHP: mt_rand 存在毛病强伪随机数CSPRNG(安全可靠的伪随机数天生器(Cryptographically SecurePseudo-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 Pythonos.urandom Perl Math::Random::Secure C/C++ (Windows API) CryptGenRandom Any language on GNU/Linuxor Unix Read from /dev/random or /dev/urandom

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

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

强伪随机数的天生思路:网络打算机的各种信息,键盘输入韶光,内存利用状态,硬盘空闲空间,IO延时,进程数量,线程数量等信息,CPU时钟,来得到一个近似随机的种子,紧张是达到不可预测性。