다음 값을 추측하는 기능 rand
은 무엇 srand
을 호출 했는지 결정할 수있는 것과 관련 이 있습니다. 특히, 미리 결정된 수의 시딩 (seeding) srand
은 예측 가능한 출력을 초래한다 ! PHP 대화식 프롬프트에서 :
[charles@charles-workstation ~]$ php -a
Interactive shell
php > srand(1024);
php > echo rand(1, 100);
97
php > echo rand(1, 100);
97
php > echo rand(1, 100);
39
php > echo rand(1, 100);
77
php > echo rand(1, 100);
93
php > srand(1024);
php > echo rand(1, 100);
97
php > echo rand(1, 100);
97
php > echo rand(1, 100);
39
php > echo rand(1, 100);
77
php > echo rand(1, 100);
93
php >
이것은 단지 약간의 우연이 아닙니다. 대부분의 PHP 버전 * 대부분의 플랫폼에서 ** 순서 97, 97, 39, 77, 93이 생성됩니다srand
'D 1024를.
분명히, 이것은 PHP의 문제가 아니며, 이것은 구현의 문제입니다. rand
자체 . Perl을 포함하여 동일한 (또는 유사한) 구현을 사용하는 다른 언어에서도 동일한 문제가 나타납니다.
비결은 PHP의 제정신 버전에 srand
"알 수없는"값 이 미리 설정되어 있다는 것 입니다. 아, 그러나 그것은 실제로 알려지지 않았습니다. 보낸 사람 ext/standard/php_rand.h
:
#define GENERATE_SEED() (((long) (time(0) * getpid())) ^ ((long) (1000000.0 * php_combined_lcg(TSRMLS_C))))
따라서, time()
PID 및의 결과 php_combined_lcg
는에 정의 된 수학입니다 ext/standard/lcg.c
. 나는 여기에 c & p를하지 않을 것입니다. 또한, 내 눈이 번쩍이고 사냥을 중단하기로 결정했습니다.
인터넷 검색의 것을 쇼의 비트 PHP의 다른 지역 최고의 랜덤 생성 특성이없는 , 그리고 호출하는 php_combined_lcg
, 여기 분석, 특히이 비트를 밖으로 서 :
이 함수 gettimeofday
는은 플래터에 정확한 서버 타임 스탬프를 되돌려 줄뿐만 아니라 "더 많은 엔트로피"(PHP에서 uniqid
)를 요청하면 LCG 출력을 추가합니다 .
그래, 그uniqid
. 두 번째 인수를 true로 설정하여 php_combined_lcg
호출 한 후 결과 16 진수를 볼 때 볼 수있는 값 인 것 같습니다 uniqid
.
자, 우리는 어디에 있었습니까?
아, 네. srand
.
따라서 임의의 값을 예측하려는 코드 가 호출 하지 않으면srand
에 의해 제공되는 값을 결정해야합니다.이 값은에 php_combined_lcg
대한 호출을 통해 (간접적으로?) 얻을 수 있습니다 uniqid
. 그 가치를 손 에 넣으면 나머지 값 , PID 및 수학 을 무차별 대입하는 것이 가능 합니다 time()
. 연결된 보안 문제는 세션을 중단하는 것과 관련이 있지만 동일한 기술이 여기에서 작동합니다. 다시 기사에서 :
위에서 설명한 공격 단계를 요약하면 다음과 같습니다.
- 서버가 재부팅 될 때까지 기다리십시오
- uniqid 값을 가져옵니다
- 이로부터 RNG 종자를 무차별 대입
- 대상이 나타날 때까지 온라인 상태를 폴링
- 현재 서버 시간 및 RNG 값을 추적하기 위해 uniqid 폴링으로 상태 폴링을 인터리브
- 폴링에서 설정된 시간 및 RNG 값 간격을 사용하여 서버에 대한 무차별 강제 세션 ID
필요에 따라 마지막 단계를 교체하십시오.
(이 보안 문제는 현재 (5.3.6)보다 이전 PHP 버전 (5.3.2)에서보고되었으므로 동작 uniqid
및 / 또는 php_combined_lcg
변경 되었을 수 있으므로이 특정 기술은 더 이상 작동하지 않을 수 있습니다. YMMV.)
반면, 제품을 만들려고하는 코드 가 srand
수동으로 호출 하는 경우 결과보다 몇 배 더 나은 것을 사용하지 않는 한 값을 추측하고 지역을 파종하는 것이php_combined_lcg
훨씬 쉬울 것입니다. 올바른 번호의 발전기. 수동으로 전화하는 대부분의 사람들srand
이것이 얼마나 끔찍한 아이디어인지 알지 못하므로 더 나은 가치를 사용하지 않을 것입니다.
mt_rand
동일한 문제로 인해 어려움을 겪고 있음을 주목할 가치가 있습니다. mt_srand
알려진 값으로 시드 하면 예측 가능한 결과가 생성됩니다. 엔트로피를 기반으로하는 openssl_random_pseudo_bytes
것이 아마도 더 안전한 내기 일 것입니다.
tl; dr : 최상의 결과를 얻으려면 PHP 난수 생성기를 시드하지 말고 좋은 결과를 얻으 uniqid
려면 사용자에게 노출하지 마십시오 . 이들 중 하나 또는 둘 다를 수행하면 난수가 더 추측 가능할 수 있습니다.
PHP 7 업데이트 :
PHP 7.0 출시 random_bytes
및 random_int
핵심 기능으로. 기본 시스템의 CSPRNG 구현을 사용하여 시드 난수 생성기의 문제점을 제거합니다. openssl_random_pseudo_bytes
확장 기능을 설치하지 않고도 효과적으로와 유사합니다 . 폴리 필은 PHP5에 사용할 수 있습니다 .
* : Suhosin 보안 패치 는 rand
및mt_rand
모든 호출과 같은 그들은 항상 것을 다시 씨앗을. Suhosin은 타사에서 제공합니다. 일부 Linux 배포판은 기본적으로 공식 PHP 패키지에 포함하지만 다른 배포판은 옵션으로 만들고 나머지는 완전히 무시합니다.
** : 사용중인 플랫폼 및 기본 라이브러리 호출에 따라 여기에 설명 된 것과 다른 시퀀스가 생성되지만 Suhosin 패치를 사용하지 않으면 결과를 계속 반복 할 수 있습니다.