PHP는 일반적인 오픈소스 스크립트 언어로 C, Java, Perl 등 우수한 언어의 구문을 혼합한 것입니다. 또한 개발자가 사용할 수 있는 수많은 함수 라이브러리도 제공합니다. 그러나 부적절하게 사용하면 PHP는 응용 프로그램에 매우 큰 보안 위험을 가져올 수도 있습니다.
이 기사에서는 PHP 애플리케이션에서 자주 발생하는 몇 가지 문제에 대해 심층 분석을 수행합니다. 특히 "=="(비교 연산자)를 사용하여 문자열 비교를 수행할 때 일부 보안 문제가 발생할 수 있습니다. . 최근 이 주제에 대해 많은 기사가 논의되었지만, 나는 이 문제를 어떻게 활용하여 대상을 침투하고 공격할 수 있는지를 "블랙박스 테스트"의 관점에서 논의하기로 결정했습니다. 먼저, 이 문제의 근본 원인을 분석하여 작동 메커니즘을 더 깊이 이해하고 이 보안 문제를 최대한 피할 수 있도록 하겠습니다.
문제 설명실제로 "==" 같은 비교 연산자를 사용해 연산을 하면 이런 상황이 나옵니다. 위 예제의 문제는 PHP에서 제공하는 '형변환'이라는 함수이므로 취약점으로 볼 수 없습니다. 본질적으로 특정 비교 연산자(예: ==, !=, )를 사용하여 작업할 때 PHP는 먼저 비교에 참여하는 데이터 유형을 결정하려고 시도합니다. 그러나 이러한 유형 변환 메커니즘으로 인해 계산 결과가 예상 결과와 크게 다를 수 있으며 매우 심각한 보안 문제도 발생할 수 있습니다. 보안 연구 전문가들은 이 문제에 대한 전체 공개 보고서에서 다음과 같이 썼습니다. 이러한 유형 변환 메커니즘은 권한 상승으로 이어질 수 있으며 심지어 프로그램의 비밀번호 확인 프로세스를 안전하지 않게 만들 수도 있습니다.
보시다시피, "=="를 사용하여 이러한 숫자 문자열을 비교할 때, 이때 비교에 포함되는 것은 문자열에 있는 숫자의 실제 크기는 보안 관점에서 매우 흥미로운 문제입니다. 이 경우 과학적 표기법을 사용하여 숫자를 표현하고 이를 문자열에 넣으면 PHP는 자동으로 이를 숫자 유형으로 처리합니다. 이러한 출력 유형을 얻는 이유는 PHP가 처리를 위해 해시 알고리즘(보통 16진수 값으로 표시)을 사용하기 때문입니다. 예를 들어 숫자가 0이면 PHP는 느슨한 비교 중에 해당 유형을 자동으로 변환하지만 해당 값은 항상 0입니다. 특정 해싱 알고리즘의 경우 비밀번호를 교체할 수 있습니다. 예를 들어, 비밀번호 해시가 과학적 표기법을 사용하여 숫자로 변환되면 다른 비밀번호 해시와 일치할 가능성이 높습니다. 이런 방식으로 완전히 다른 비밀번호라도 시스템 확인을 통과할 수 있습니다. 하지만 흥미로운 점은 과학적 표기법으로 표현된 특정 숫자를 비교할 때 놀라운 결과가 나올 수 있다는 것입니다.
import random import hashlib import re import string import sys prof = re.compile("^0+ed*$") # you can also consider: re.compile("^d*e0+$") prefix = string.lower(sys.argv[1])+'!'+string.upper(sys.argv[1])+"%s" num=0 while True: num+=1 b = hashlib.sha256(prefix % num).hexdigest() if (b[0]=='0' and prof.match(b)): print(prefix+str(num),b)
비밀번호 계산 결과는 아래와 같이 매우 유사합니다.
비교를 위해 두 개의 비밀번호를 무작위로 선택할 수 있습니다. 결과는 다음과 같습니다.
위와 같은 계산 결과를 얻을 수 없다면 운이 좋다고 생각해야 합니다. 사용자 이름과 비밀번호를 함께 묶은 다음 "솔트" 값이 포함된 해시 알고리즘을 사용하여 계산해 볼 수 있습니다. 이를 달성하려면 코드의 작은 부분만 수정하면 됩니다. 수정된 스크립트를 얻으려면 "여기"를 클릭하세요.