真的是放假在老家与世隔绝久了,题目都写不出来了…还坑了队友,emmmm先记录一下再说。
babyupload
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
| <?php error_reporting(0); session_save_path("/var/babyctf/"); session_start(); require_once "/flag"; highlight_file(__FILE__); if($_SESSION['username'] ==='admin') { $filename='/var/babyctf/success.txt'; if(file_exists($filename)){ safe_delete($filename); die($flag); } } else{ $_SESSION['username'] ='guest'; } $direction = filter_input(INPUT_POST, 'direction'); $attr = filter_input(INPUT_POST, 'attr'); $dir_path = "/var/babyctf/".$attr; if($attr==="private"){ $dir_path .= "/".$_SESSION['username']; } if($direction === "upload"){ try{ if(!is_uploaded_file($_FILES['up_file']['tmp_name'])){ throw new RuntimeException('invalid upload'); } $file_path = $dir_path."/".$_FILES['up_file']['name']; $file_path .= "_".hash_file("sha256",$_FILES['up_file']['tmp_name']); if(preg_match('/(../|..\\)/', $file_path)){ throw new RuntimeException('invalid file path'); } @mkdir($dir_path, 0700, TRUE); if(move_uploaded_file($_FILES['up_file']['tmp_name'],$file_path)){ $upload_result = "uploaded"; }else{ throw new RuntimeException('error while saving'); } } catch (RuntimeException $e) { $upload_result = $e->getMessage(); } } elseif ($direction === "download") { try{ $filename = basename(filter_input(INPUT_POST, 'filename')); $file_path = $dir_path."/".$filename; if(preg_match('/(../|..\\)/', $file_path)){ throw new RuntimeException('invalid file path'); } if(!file_exists($file_path)) { throw new RuntimeException('file not exist'); } header('Content-Type: application/force-download'); header('Content-Length: '.filesize($file_path)); header('Content-Disposition: attachment; filename="'.substr($filename, 0, -65).'"'); if(readfile($file_path)){ $download_result = "downloaded"; }else{ throw new RuntimeException('error while saving'); } } catch (RuntimeException $e) { $download_result = $e->getMessage(); } exit; } ?>
|
这题的意图很明显,告诉了我们session上传的路径,看完代码发现当满足
1 2 3 4
| $_SESSION['username'] ==='admin' & $filename='/var/babyctf/success.txt'; if(file_exists($filename)
|
我们就可以拿到flag。顺着下来看代码,告诉了我们session的位置,有下载功能,尝试过后发现能读取。
1
| direction=download&filename=sess_xxxxxxx
|
可以读到session的格式
1
| <0x08>usernames:5:"guest";
|
我们可以直接构造一个admin的session去上传。
上传文件命名规则
1 2
| $file_path = $dir_path."/".$_FILES['up_file']['name']; $file_path .= "_".hash_file("sha256",$_FILES['up_file']['tmp_name']);
|
可以不传递attr参数,将文件名为sess,就会有/var/babyctf/sess_hashfile(“sha256”)类似session文件命名规则的文件出现。
hash是随机函数,但是hashfile则是根据文件生成的hash值,我们可以控制上传内容也就能控制hash值。
就有了先POST attr=&direction=upload&filename=sess(文件内容为<0x08>usernames:5:”admin”;)上传
读取sess_hash_file()可以读取成功。
绕过#2、#3,我们发现一行
1
| $dir_path = "/var/babyctf/".$attr;
|
我们可以利用这点,上传attr=success.txt&direction=upload&….,构造一个success.txt的目录来绕过判断,再带着我们之前上传的session(修改PHPSESSID=hash_file()),访问抓包即可获得flag。