찾다
백엔드 개발PHP 튜토리얼PHP에서 mt_rand() 난수의 안전한 예에 대한 자세한 설명

mt_rand()와 관련된 보안 취약점이 얼마 전에 많이 발견되었는데, 이는 기본적으로 난수 사용법에 대한 오해에서 비롯되었습니다. 여기에서는 PHP 공식 웹사이트 매뉴얼의 또 다른 함정에 대해 언급하고 싶습니다. mt_rand()의 소개를 살펴보세요: 중국어 버전 ^cn 영어 버전 ^en 영어 버전에는 추가로 노란색 주의 경고가 있는 것을 볼 수 있습니다. mt_rand()는 mersennetwister 알고리즘을 사용하여 임의의 정수를 반환합니다. 이는 누구나 알고 있지만 다음 기사에서는 주로 PHP의 mt_rand() 난수 보안에 대한 관련 정보를 소개합니다. 참고할 수 있도록 아래 에디터와 함께 배워보겠습니다.

많은 국내 개발자들이 아마도 중국어 버전의 소개를 읽고 프로그램에서 mt_rand()를 사용하여 보안 토큰, 핵심 암호화 및 복호화 키 등을 생성하여 심각한 보안 문제를 일으켰을 것입니다.

의사 난수

mt_rand()는 실제 난수 생성 함수가 아닙니다. 실제로 프로그래밍 언어의 대부분의 난수 함수는 의사 난수를 생성합니다. 실제 난수와 의사 난수의 차이점은 여기서 설명하지 않습니다. 의사 난수는 일반적으로 사용되는 시계를 통해 결정 가능한 함수(일반적으로 사용되는 선형 합동)에 의해 생성됩니다. ). 즉, 시드나 생성된 난수를 알면 다음 난수열에 대한 정보를 얻을 수 있다는 뜻이다(예측성).

mt_rand()에서 내부적으로 난수를 생성하는 함수가 다음과 같다고 간단히 가정해 보세요. rand = seed+(i*10) 여기서 Seed는 난수 시드이고 i는 이 난수 함수가 호출되는 횟수입니다. i와 rand의 두 값을 동시에 알면 시드의 값을 쉽게 계산할 수 있습니다. 예를 들어, rand=21 및 i=2는 21=seed+(2*10) 함수로 대체되어 seed=1을 얻습니다. 아주 간단하지 않나요? 시드를 얻은 후에 i가 임의의 값일 때 랜드 값을 계산할 수 있습니다.

PHP의 자동 시드


이전 섹션에서 우리는 mt_rand()가 호출될 때마다 시드와 현재 호출 수 i를 기반으로 의사 난수가 계산된다는 것을 이미 알고 있습니다. 그리고 시드는 자동으로 시드됩니다:

참고: PHP 4.2.0부터 난수 생성기를 시드하기 위해 srand() 또는 mt_srand()를 사용할 필요가 없습니다. 이제 시스템에서 자동으로 시드가 수행되기 때문입니다.

그러면 시스템은 언제 자동으로 시드를 완료합니까? mt_rand()가 매번 자동으로 시드되면 시드를 크래킹할 필요가 없습니다. 매뉴얼에서는 이 점에 대한 자세한 정보를 제공하지 않습니다. 인터넷을 여기저기 찾아보았지만 믿을만한 답변을 찾을 수 없어서 소스코드를 확인하게 되었습니다 ^mtrand:

PHPAPI void php_mt_srand(uint32_t seed)
{
 /* Seed the generator with a simple uint32 */
 php_mt_initialize(seed, BG(state));
 php_mt_reload();

 /* Seed only once */
 BG(mt_rand_is_seeded) = 1; 
}
/* }}} */

/* {{{ php_mt_rand
 */
PHPAPI uint32_t php_mt_rand(void)
{
 /* Pull a 32-bit integer from the generator state
 Every other access function simply transforms the numbers extracted here */

 register uint32_t s1;

 if (UNEXPECTED(!BG(mt_rand_is_seeded))) {
 php_mt_srand(GENERATE_SEED());
 }

 if (BG(left) == 0) {
 php_mt_reload();
 }
 --BG(left);

 s1 = *BG(next)++;
 s1 ^= (s1 >> 11);
 s1 ^= (s1 > 18) );
}

mt_rand()가 호출될 때마다 먼저 뿌렸는지부터 확인하는 걸 볼 수 있습니다 . 파종된 경우에는 난수를 직접 생성하고, 그렇지 않으면 php_mt_srand를 호출하여 파종합니다. 즉, 각 php cgi 프로세스 중에 mt_rand()에 대한 첫 번째 호출만 자동으로 시드됩니다. 다음으로, 처음 뿌려진 시드를 기반으로 난수가 생성됩니다. CGI를 제외한 php의 여러 작동 모드 중(각 요청은 cgi 프로세스를 시작하고 요청이 완료된 후 닫힙니다. php.ini 환경 변수는 매번 다시 읽어야 하므로 효율성이 낮으며, 그렇게 해서는 안 됩니다. 현재 많이 사용됨) 기본적으로 하나의 프로세스가 요청을 처리한 후 대기 프로세스는 다음 프로세스를 기다리며 여러 요청이 처리될 때까지 재활용되지 않습니다(타임아웃 후에도 재활용됩니다).

테스트용 스크립트 작성

<?php //pid.php
echo getmypid();
<?php //test.php
$old_pid = file_get_contents(&#39;http://localhost/pid.php&#39;);
$i=1;
while(true){
 $i++;
 $pid = file_get_contents(&#39;http://localhost/pid.php&#39;);
 if($pid!=$old_pid){
 echo $i;
 break;
 }
}

테스트 결과: (windows+phpstudy)

apache 1000 요청

nginx 500 요청

물론 이 테스트는 apache와 nginx가 하나의 프로세스에서 처리할 수 있는 요청 수만 확인합니다. , 다시 확인해 보겠습니다. 자동 시딩에 대해 방금 결론을 내렸습니다.

<?php //pid1.php
if(isset($_GET[&#39;rand&#39;])){
 echo mt_rand();
}else{
 echo getmypid();
}
<?php //pid2.php
echo mt_rand();
<?php //test.php
$old_pid = file_get_contents(&#39;http://localhost/pid1.php&#39;);
echo "old_pid:{$old_pid}\r\n";
while(true){
 $pid = file_get_contents(&#39;http://localhost/pid1.php&#39;);
 if($pid!=$old_pid){
 echo "new_pid:{$pid}\r\n";
 for($i=0;$i<20;$i++){
  $random = mt_rand(1,2);
  echo file_get_contents("http://localhost/pid".$random.".php?rand=1")." ";
 }

 break;
 }
}

PID로 판단합니다. 새 프로세스가 시작되면 두 페이지 중 하나에서 mt_rand()의 출력을 무작위로 얻습니다.

old_pid:972 new_pid:7752 1513334371 2014450250 1319669412 499559587 117728762 1465174656 1671827592 1703046841 464496438 1974338231 46646067 981271768 1070717272 571887250 922467166 606646473 134605134 857256637 1971727275 2104203195

첫 번째 난수 1513334371을 사용하여 폭발합니다. 시드:

smldhz@vm:~/php_mt_seed-3.2$ ./php_mt_seed 1513334371 Found 0, trying 704643072 - 738197503, speed 28562751 seeds per second seed = 735487048 Found 1, trying 1308622848 - 1342177279, speed 28824291 seeds per second seed = 1337331453 Found 2, trying 3254779904 - 3288334335, speed 28811010 seeds per second seed = 3283082581 Found 3, trying 4261412864 - 4294967295, speed 28677071 seeds per second Found 3

가능한 시드 3개를 폭발시켰습니다. 숫자는 매우 작습니다. 하나씩 수동으로 테스트했습니다.

<?php mt_srand(735487048);//手工播种
for($i=0;$i<21;$i++){
 echo mt_rand()." ";
}

출력:

처음 20개는 위 스크립트에서 얻은 것과 정확히 동일합니다. 확인된 시드는 1513334371입니다. . 시드를 사용하면 mt_rand()를 여러 번 호출하여 생성된 난수를 계산할 수 있습니다. 예를 들어 이 스크립트에서는 21자리 숫자를 생성했는데 마지막 숫자는 1515656265입니다. 지금 스크립트를 실행한 후 해당 사이트를 방문하지 않았다면 http://localhost/pid2.php를 열어도 동일한 1515656265를 보실 수 있습니다.

그래서 우리는 결론을 내렸습니다:

php의 자동 시딩은 php cgi 프로세스에서 mt_rand()가 처음으로 호출될 때 발생합니다. 방문한 페이지에 관계없이 요청이 동일한 프로세스에 의해 처리되는 한 처음에 자동으로 뿌려진 동일한 시드를 공유합니다.

php_mt_seed

우리는 난수 생성이 위에서 rand = seed+(i*10) 으로 가정된 특정 함수에 따라 다르다는 것을 이미 알고 있습니다. 이러한 간단한 함수의 경우 물론 솔루션(그룹)을 (구두로) 직접 계산할 수 있지만 실제로 mt_rand()에서 사용하는 함수는 상당히 복잡하여 반전할 수 없습니다. 효과적인 크래킹 방법은 모든 시드를 철저하게 열거하고, 시드를 기반으로 난수열을 생성한 다음 이를 알려진 난수열과 비교하여 시드가 올바른지 확인하는 것입니다. php_mt_seed^phpmtseed는 매우 빠르며 2^32비트 시드를 실행하는 데 몇 분 밖에 걸리지 않습니다. 단일 mt_rand()의 출력을 기반으로 가능한 시드를 직접 폭발시킬 수 있습니다(위의 예). 물론 mt_rand(1,100)과 같이 MIN MAX 출력을 제한하는 시드를 폭발시킬 수도 있습니다(아래 예에서 유용함).

보안 문제

이렇게 말했는데 난수는 왜 안전하지 않습니까? 실제로 기능 자체에는 아무런 문제가 없으며, 생성된 난수를 보안 암호화 목적으로 사용해서는 안 된다는 점을 관계자도 분명히 밝혔습니다(중국어 버전 매뉴얼에는 이런 내용이 적혀있지 않지만). 문제는 개발자가 이것이 진정한 난수가 아니라는 것을 깨닫지 못한다는 것입니다. 우리는 알려진 일련의 난수에서 씨앗이 폭발할 수 있다는 것을 이미 알고 있습니다. 즉, 임의의 페이지에 출력 난수 또는 그 파생 값(가역적 난수 값)이 있는 한 다른 페이지의 난수는 더 이상 "난수"가 아닙니다. 난수 출력의 일반적인 예로는 인증 코드, 임의의 파일 이름 등이 있습니다. 암호화 키 등 비밀번호 확인 값을 가져오는 등 보안 확인을 위해 일반적인 난수를 사용합니다. 이상적인 공격 시나리오:

한밤 중에 아파치(nginx)가 모든 PHP 프로세스를 다시 가져오기를 기다리고(다음 방문 시 다시 시드되도록 하기 위해) 확인 코드 페이지를 한 번 방문하고 인증번호 문자를 기준으로 난수를 생성한 후, 난수를 기준으로 폭발 난수 시드를 생성합니다. 그런 다음 비밀번호 검색 페이지를 방문하면 생성된 비밀번호 검색 링크는 임의의 숫자를 기반으로 합니다. 우리는 이 링크를 쉽게 계산하고 관리자 비밀번호를 검색할 수 있습니다... XXOO

Example

PHPCMS MT_RAND SEED CRACK이 인증 키 유출을 유발합니다. Yu Niu가 저보다 글을 더 잘 씁니다. 그의 Discuz x3.2 인증 키 유출이 실제로 비슷하다는 것을 보세요. 공식 패치가 공개되었으며, 관심 있는 분들은 직접 분석해 보시기 바랍니다.

관련 권장사항:

PHP의 참 및 거짓 난수

난수 생성을 위한 PHP의 rand() 함수

난수 중복 제거 생성기를 구현하는 JavaScript의 예

위 내용은 PHP에서 mt_rand() 난수의 안전한 예에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
과대 광고 : 오늘 PHP의 역할을 평가합니다과대 광고 : 오늘 PHP의 역할을 평가합니다Apr 12, 2025 am 12:17 AM

PHP는 현대적인 프로그래밍, 특히 웹 개발 분야에서 강력하고 널리 사용되는 도구로 남아 있습니다. 1) PHP는 사용하기 쉽고 데이터베이스와 완벽하게 통합되며 많은 개발자에게 가장 먼저 선택됩니다. 2) 동적 컨텐츠 생성 및 객체 지향 프로그래밍을 지원하여 웹 사이트를 신속하게 작성하고 유지 관리하는 데 적합합니다. 3) 데이터베이스 쿼리를 캐싱하고 최적화함으로써 PHP의 성능을 향상시킬 수 있으며, 광범위한 커뮤니티와 풍부한 생태계는 오늘날의 기술 스택에 여전히 중요합니다.

PHP의 약한 참고 자료는 무엇이며 언제 유용합니까?PHP의 약한 참고 자료는 무엇이며 언제 유용합니까?Apr 12, 2025 am 12:13 AM

PHP에서는 약한 참조가 약한 회의 클래스를 통해 구현되며 쓰레기 수집가가 물체를 되 찾는 것을 방해하지 않습니다. 약한 참조는 캐싱 시스템 및 이벤트 리스너와 같은 시나리오에 적합합니다. 물체의 생존을 보장 할 수 없으며 쓰레기 수집이 지연 될 수 있음에 주목해야합니다.

PHP의 __invoke 마법 방법을 설명하십시오.PHP의 __invoke 마법 방법을 설명하십시오.Apr 12, 2025 am 12:07 AM

\ _ \ _ 호출 메소드를 사용하면 객체를 함수처럼 호출 할 수 있습니다. 1. 객체를 호출 할 수 있도록 메소드를 호출하는 \ _ \ _ 정의하십시오. 2. $ obj (...) 구문을 사용할 때 PHP는 \ _ \ _ invoke 메소드를 실행합니다. 3. 로깅 및 계산기, 코드 유연성 및 가독성 향상과 같은 시나리오에 적합합니다.

동시성에 대해 PHP 8.1의 섬유를 설명하십시오.동시성에 대해 PHP 8.1의 섬유를 설명하십시오.Apr 12, 2025 am 12:05 AM

섬유는 PHP8.1에 도입되어 동시 처리 기능을 향상시켰다. 1) 섬유는 코 루틴과 유사한 가벼운 동시성 모델입니다. 2) 개발자는 작업의 실행 흐름을 수동으로 제어 할 수 있으며 I/O 집약적 작업을 처리하는 데 적합합니다. 3) 섬유를 사용하면보다 효율적이고 반응이 좋은 코드를 작성할 수 있습니다.

PHP 커뮤니티 : 자원, 지원 및 개발PHP 커뮤니티 : 자원, 지원 및 개발Apr 12, 2025 am 12:04 AM

PHP 커뮤니티는 개발자 성장을 돕기 위해 풍부한 자원과 지원을 제공합니다. 1) 자료에는 공식 문서, 튜토리얼, 블로그 및 Laravel 및 Symfony와 같은 오픈 소스 프로젝트가 포함됩니다. 2) 지원은 StackoverFlow, Reddit 및 Slack 채널을 통해 얻을 수 있습니다. 3) RFC에 따라 개발 동향을 배울 수 있습니다. 4) 적극적인 참여, 코드에 대한 기여 및 학습 공유를 통해 커뮤니티에 통합 될 수 있습니다.

PHP vs. Python : 차이점 이해PHP vs. Python : 차이점 이해Apr 11, 2025 am 12:15 AM

PHP와 Python은 각각 고유 한 장점이 있으며 선택은 프로젝트 요구 사항을 기반으로해야합니다. 1.PHP는 간단한 구문과 높은 실행 효율로 웹 개발에 적합합니다. 2. Python은 간결한 구문 및 풍부한 라이브러리를 갖춘 데이터 과학 및 기계 학습에 적합합니다.

PHP : 죽어 가거나 단순히 적응하고 있습니까?PHP : 죽어 가거나 단순히 적응하고 있습니까?Apr 11, 2025 am 12:13 AM

PHP는 죽지 않고 끊임없이 적응하고 진화합니다. 1) PHP는 1994 년부터 새로운 기술 트렌드에 적응하기 위해 여러 버전 반복을 겪었습니다. 2) 현재 전자 상거래, 컨텐츠 관리 시스템 및 기타 분야에서 널리 사용됩니다. 3) PHP8은 성능과 현대화를 개선하기 위해 JIT 컴파일러 및 기타 기능을 소개합니다. 4) Opcache를 사용하고 PSR-12 표준을 따라 성능 및 코드 품질을 최적화하십시오.

PHP의 미래 : 적응 및 혁신PHP의 미래 : 적응 및 혁신Apr 11, 2025 am 12:01 AM

PHP의 미래는 새로운 기술 트렌드에 적응하고 혁신적인 기능을 도입함으로써 달성 될 것입니다. 1) 클라우드 컴퓨팅, 컨테이너화 및 마이크로 서비스 아키텍처에 적응, Docker 및 Kubernetes 지원; 2) 성능 및 데이터 처리 효율을 향상시키기 위해 JIT 컴파일러 및 열거 유형을 도입합니다. 3) 지속적으로 성능을 최적화하고 모범 사례를 홍보합니다.

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
4 몇 주 전By尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

SublimeText3 Linux 새 버전

SublimeText3 Linux 새 버전

SublimeText3 Linux 최신 버전

mPDF

mPDF

mPDF는 UTF-8로 인코딩된 HTML에서 PDF 파일을 생성할 수 있는 PHP 라이브러리입니다. 원저자인 Ian Back은 자신의 웹 사이트에서 "즉시" PDF 파일을 출력하고 다양한 언어를 처리하기 위해 mPDF를 작성했습니다. HTML2FPDF와 같은 원본 스크립트보다 유니코드 글꼴을 사용할 때 속도가 느리고 더 큰 파일을 생성하지만 CSS 스타일 등을 지원하고 많은 개선 사항이 있습니다. RTL(아랍어, 히브리어), CJK(중국어, 일본어, 한국어)를 포함한 거의 모든 언어를 지원합니다. 중첩된 블록 수준 요소(예: P, DIV)를 지원합니다.

Atom Editor Mac 버전 다운로드

Atom Editor Mac 버전 다운로드

가장 인기 있는 오픈 소스 편집기

DVWA

DVWA

DVWA(Damn Vulnerable Web App)는 매우 취약한 PHP/MySQL 웹 애플리케이션입니다. 주요 목표는 보안 전문가가 법적 환경에서 자신의 기술과 도구를 테스트하고, 웹 개발자가 웹 응용 프로그램 보안 프로세스를 더 잘 이해할 수 있도록 돕고, 교사/학생이 교실 환경 웹 응용 프로그램에서 가르치고 배울 수 있도록 돕는 것입니다. 보안. DVWA의 목표는 다양한 난이도의 간단하고 간단한 인터페이스를 통해 가장 일반적인 웹 취약점 중 일부를 연습하는 것입니다. 이 소프트웨어는

VSCode Windows 64비트 다운로드

VSCode Windows 64비트 다운로드

Microsoft에서 출시한 강력한 무료 IDE 편집기