>  기사  >  백엔드 개발  >  PHP 약한 유형 안전 문제에 대해 이야기

PHP 약한 유형 안전 문제에 대해 이야기

little bottle
little bottle앞으로
2019-04-27 11:37:303058검색

이 기사에서 편집자는 PHP 약한 타이핑에 대해 이야기하고 싶습니다. PHP 약한 타이핑은 코드를 작성할 때 프로그래머에게 큰 편의를 제공하지만 모든 것에는 양면이 있습니다.

0x00 약한 타이핑에 대한 예비 연구

PHP는 개발자가 사용할 수 있는 많은 기능을 제공하며 그 중 하나는 약한 타이핑 메커니즘입니다.

약한 유형 메커니즘에서 이러한 작업을 수행할 수 있습니다.

<?php
$var = 1;
$var = array();
$var = "string";
?>

php는 들어오는 변수의 유형을 엄격하게 확인하지 않지만 변수 유형을 자유롭게 변환할 수도 있습니다.

예를 들어 $a == $b

$a = null; $b = false; //为真
$a = &#39;&#39;; $b = 0; //同样为真

의 비교에서, PHP 커널 개발자는 원래 선언이 필요하지 않은 이 시스템을 통해 프로그래머가 더 효율적으로 개발하기를 원했기 때문에 거의 모든 내장 함수에 그리고 프로그램의 변수가 프로그래머의 불규칙성으로 인해 자주 오류를 보고하는 것을 방지하기 위해 기본 구조에는 느슨한 비교 및 ​​변환이 많이 사용됩니다. 그러나 이는 보안 문제를 야기합니다.

0x02 지식 준비 PHP 커널 zval 구조

PHP에서 선언된 변수는 zval 구조를 사용하여 ZE에 저장됩니다.

zval은 zend/zend.h에 정의됩니다. h

typedef struct _zval_struct zval;  
struct _zval_struct {  
  /* Variable information */  
  zvalue_value value; /* value */  
  zend_uint refcount__gc;  
  zend_uchar type;/* active type */  
  zend_uchar is_ref__gc;  
};  
typedef union _zvalue_value {  
  long lval;  /* long value */  
  double dval;/* double value */  
  struct {  
    char *val;  
    int len;  
  } str;  
  HashTable *ht;  /* hash table value */  
  zend_object_value obj;  
} zvalue_value;

PHP는 유형을 사용하여 변수 유형을 결정하고 store it in value

위는 PHP 커널의 약한 유형을 캡슐화한 것이며, 나중에 이야기할 모든 것의 원칙이자 기초이기도 합니다.

0x03 변수의 강제

방금 배운 내용을 통해 zval.type이 zval.value에 저장된 유형을 결정한다는 것을 알 수 있습니다.

소스 코드가 제한되지 않은 유형 비교 또는 수학 연산을 수행하면 zval.type이 변경될 수 있으며 동시에 zval.value의 내용이 변경되는 데 영향을 미칠 수 있습니다.

int가 문자열을 만날 때

cp.1 수학 연산

PHP가 몇 가지 수학적 계산을 수행할 때

ar_dump(0 == &#39;0&#39;); // true
var_dump(0 == &#39;abcdefg&#39;); // true  
var_dump(0 === &#39;abcdefg&#39;); // false
var_dump(1 == &#39;1abcdef&#39;); // true

비교 매개변수 중 하나가 정수이면 다른 매개변수는 강제로 정수로 변환됩니다.

문자열 부분

intval을 정수 부분과 비교하는 것과 같습니다. 실제로 zval.type의 내용을 변경합니다. 특히 '1assd'의 변환 값은 1이고 'asdaf'는 0

입니다.

또한 intval이 숫자가 아닌 첫 번째 단위부터 시작한다는 것을 보여줍니다

또한

var_dump(intval(&#39;3389a&#39;));//输出3389

이 예는 우리에게 다음 코드를 절대 믿지 말라는 것을 알려줍니다

if($a>1000){    
mysql_query(&#39;update ... .... set value=$a&#39;)
}

이 때 분기를 입력하는 것이 정수라고 생각합니다

사실 $a는 1001/**/union...

cp.2 명령문 조건의 느슨한 판단

예를 들어, PHP 스위치는 느슨한 비교를 사용하며 자동으로 intval이 변경됩니다. 0 각각의 경우에 중단이 없으면 포함될 때까지 실행되며 최종적으로 필요한 기능이 실행됩니다. — 배열에 특정 항목이 있는지 확인합니다. 값 매개변수

needle 검색할 값입니다. 참고: needle이 문자열인 경우 비교 시 대/소문자를 구분합니다. 이 배열을 건초더미에 쌓으세요.

strict 세 번째 매개변수 strict의 값이 TRUE이면 in_array() 함수는 needle의 종류가 haystack의 것과 동일한지 여부도 확인합니다.

strict를 추가해야만 유형이 엄격하게 비교된다는 것을 알 수 있습니다. 그러면 ×××를 문자열과 다시 비교하면 어떨까요?

<?php
if (isset($_GET[&#39;which&#39;]))
{
  $which = $_GET[&#39;which&#39;];
  switch ($which)
  {
  case 0:
  case 1:
  case 2:
    require_once $which.&#39;.php&#39;;
    break;
  default:
    echo GWF_HTML::error(&#39;PHP-0817&#39;, &#39;Hacker NoNoNo!&#39;, false);
    break;
  }

배열의 각 값을 반복하고 "==" 비교를 수행합니다("엄격이 설정된 경우 ===" 사용).

결과는 분명합니다

array1에 0인 값이 있는 경우 , 그러면 One 반환은 true가 됩니다. //intval('abc')=0

array2에 1인 값이 있으면 두 번째 반환은 true가 됩니다. //intval('1bc')=1

array_search는 동일합니다. 동일한 원리

여기에는 광범위한 응용 프로그램이 있습니다.

많은 프로그래머가 배열의 값을 확인할 것입니다.

그런 다음 구성된 int 0 또는 1을 완전히 사용하여 감지 기능을 속이고 만들 수 있습니다. return true

요약하자면, PHP가 int로 간주하는 위치에 문자열을 입력하면

var_dump(in_array("abc", $array));

배열이 문자열을 만나면

이 예를 만났습니다. 독일의 ctf에서는 매우 흥미롭습니다. 앞서 이야기한 것은 string과 int의 비교에 관한 것입니다

그러면 배열이 int나 string과 접촉할 때 화학 반응은 어떻게 될까요? 우리는 PHP 매뉴얼에서

정수/부동 소수점 부동 소수점으로의 배열 변환이 요소 수를 반환한다는 것을 알고 있습니다.

bool로의 변환은 배열에 요소가 있는지 여부를 반환하고 문자열로 변환하면 '배열'을 반환합니다. 경고가 표시됩니다.

그럼 실제 적용은 뭘까요?

var_dump(in_array("abc", $array1));</br>
var_dump(in_array("1bc", $array2));

이 브랜치는 strcmp 함수 비교를 통해 두 개가 동일해야 하고 "=="를 입력하려면 두 개가 같지 않아야 함을 알 수 있습니다.

strcmp() 함수는 두 문자열을 비교합니다.

이 함수는 다음을 반환합니다.

0 - 두 문자열이 같은 경우

fcedf75651a30c09a2e5a2a492e4a1550 - 문자열1이 문자열2보다 큰 경우

여기서 strcmp 함수는 실제로 두 문자열을 변환합니다. 변수를 ASCII로 변환한 다음 수학적 뺄셈을 수행하여 그 차이를 int로 반환합니다.

즉, 'a'와 'a'를 입력하여 비교한 결과는 0

그럼 $array를 ‘a'와 비교하면 어떻게 될까요?

$a = &#39;asdfgh&#39;;//字符串类型的a</br>
echo $a[2];  //根据php的offset 会输出&#39;d&#39;</br>
echo $a[x];  //根据php的预测,这里应该是int型,那么输入string,就会被intval成为0 也就是输出&#39;a&#39;

이때 php에서 null이 반환되었습니다!

즉, 기능 검사를 우회하여 항상 true가 되도록 이 기능 오류를 만듭니다.

0x04 항상 약한 유형을 조심하세요

프로그래머로서 약한 유형은 코드를 작성할 때 프로그래머에게 큰 편리함을 제공하지만 $array =array(); 습관을 잊어버리게 만들기도 합니다. 모든 입력은 해롭다고 합니다

사실 모든 입력의 유형도 의심스럽다고 할 수 있습니다. 약한 유형의 PHP에서는 어떤 비교 함수나 수학 연산도 신뢰하지 마세요. 그렇지 않으면 당신은 확실히 PHP에 의해 배신당한 사람입니다.

관련 튜토리얼: PHP 비디오 튜토리얼

위 내용은 PHP 약한 유형 안전 문제에 대해 이야기의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 51cto.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제