PeopleSoft Token: Difference between revisions

From Leo's Notes
This page was last edited on 27 September 2015, at 09:23.
No edit summary
No edit summary
Line 1: Line 1:
I came upon an article concerning the PS_TOKEN vulnerability where an attacker can brute force the SHA1 signature value in order to obtain the node password for PeopleSoft systems using SSO.
I came upon an article concerning the PS_TOKEN vulnerability where an attacker can brute force the SHA1 signature value in order to obtain the node password for PeopleSoft systems.


Since my university uses PeopleSoft, I took a deeper look into how PS_TOKEN is generated and parsed.
Since my university uses PeopleSoft, I took a deeper look into how PS_TOKEN is generated and parsed.


== Cookie Format ==
== Getting PS_TOKEN ==
The value itself is encoded using base64 and looks something similar to:
A google search can turn up a few hundred sites running PeopleSoft. Just google for:
{{Highlight|lang=text|code=
{{Highlight|lang=text|code=
AAAAqQECAwQAAQAAAAACvAAAAAAAAAAsAARTaGRyAgBOdwgAOAAuADEAMBSEI9HyVMA76K0KLjX552P1scTSuwAAAGkABVNkYXRhXXicHYtBDkBADEWfIZaWbkEGM8JasBMJNjaO4XIO58+06Wublw+8iUkzElTmCyy5Y19MDLT0WNHlzGysBTsHCyeP/OGkLA2eSnsU23g3itY4OjHYWuP1ucgf6kMMnw==
peoplesoft inurl:cmd=login
}}
}}


The actual format of the binary blob that I've found is:
PeopleSoft's web application URLs look something similar to:
http://people-soft.leung.xyz/psp/SiteName
 
Requesting for a specific page such as the password reset page will usually cause a  new PS_TOKEN to be generated.
http://people-soft.leung.xyz/psp/SiteName/EMPLOYEE/HRMS/c/JHR_SECURITY.JHR_FORGOT_PSWD.GBL
 
== Cookie Format ==
The PS_TOKEN cookie is encoded using base64. The actual format of the binary blob that I've found is:
{{Highlight|lang=text|code=
{{Highlight|lang=text|code=
0 : Int32 - length of the entire token
0 : Int32 - length of the entire token
4 : Int32 - Some magic number
4 : Int32 - Some magic number
???
??? - unknown fields
20 : Int32 Header Length
20 : Int32 Header Length
24 : 00 padding?
24 : 00 padding?
Line 29: Line 36:
A String in the data section above is a byte value containing the string length followed by the string.
A String in the data section above is a byte value containing the string length followed by the string.


Parsing the cookie above produces the following values:
Parsing one of the cookies I captured shows the following contents I was able to read.
{{Highlight|lang=text|code=
{{Highlight|lang=text|code=
Full Length: 169
Array
Magic Number: 16909060
(
Header Full Length: 44
    [endian] => Little
Header String: Shdr
    [length] => 167
Unknown field N
    [magic1] => 16909060
Version: 8.10
    [headerLength] => 44
Hash length is 20
    [headerString] => Shdr
Signature: 8423d1f254c03be8ada2e35f9e763f5b1c4d2bb
    [unknownField] => N
Data Length: 105
    [version] => 8.10
Data Header: Sdata
    [signature] => d6ad9e49c2822b3b8df7b874ed13ba5e4ecb
Data Value: ZZZUC826024
    [dataLength] => 103
Data Value: ENG
    [dataHeader] => Sdata
Data Value: PSFT_CS
    [data] => Array
Data Value: 2015-09-25-18.43.15.553453
        (
            [user] => APPLICANT
            [lang] => ENG
            [server] => PSFT_HR
            [datetime] => 2015-09-26-22.46.33.000660
        )
 
    [prefix] => APPLICANTENG2015-09-26-22.46.33.000660PSFT_HR
)
}}
}}



Revision as of 09:23, 27 September 2015

I came upon an article concerning the PS_TOKEN vulnerability where an attacker can brute force the SHA1 signature value in order to obtain the node password for PeopleSoft systems.

Since my university uses PeopleSoft, I took a deeper look into how PS_TOKEN is generated and parsed.

Getting PS_TOKEN

A google search can turn up a few hundred sites running PeopleSoft. Just google for:

peoplesoft inurl:cmd=login

PeopleSoft's web application URLs look something similar to:

http://people-soft.leung.xyz/psp/SiteName

Requesting for a specific page such as the password reset page will usually cause a new PS_TOKEN to be generated.

http://people-soft.leung.xyz/psp/SiteName/EMPLOYEE/HRMS/c/JHR_SECURITY.JHR_FORGOT_PSWD.GBL

Cookie Format

The PS_TOKEN cookie is encoded using base64. The actual format of the binary blob that I've found is:

0 : Int32 - length of the entire token
4 : Int32 - Some magic number
??? - unknown fields
20 : Int32 Header Length
24 : 00 padding?
String - Header string (Shdr)
String - Unknown (N)
00 padding? - 1 byte
String - Version (8.10)
String - SHA1 Signature, 20 bytes as hex
Int32 - Data Section Length
00 padding? - 1 byte
String - Data Header (Sdata)
String - Data Value (zlib data. String values starting at 20 bytes in)

A String in the data section above is a byte value containing the string length followed by the string.

Parsing one of the cookies I captured shows the following contents I was able to read.

Array
(
    [endian] => Little
    [length] => 167
    [magic1] => 16909060
    [headerLength] => 44
    [headerString] => Shdr
    [unknownField] => N
    [version] => 8.10
    [signature] => d6ad9e49c2822b3b8df7b874ed13ba5e4ecb
    [dataLength] => 103
    [dataHeader] => Sdata
    [data] => Array
        (
            [user] => APPLICANT
            [lang] => ENG
            [server] => PSFT_HR
            [datetime] => 2015-09-26-22.46.33.000660
        )

    [prefix] => APPLICANTENG2015-09-26-22.46.33.000660PSFT_HR
)

A Simple Parser

Here's a parser which I wrote in PHP. It will correctly detect the endianness of the values and read the binary properly. It also checks the hash against some default passwords.

<phorkie>https://phorkie.leo.home.steamr.com/11/embed</phorkie>

Signature Generation

According to Oracle's documentation, the SHA1 signature is generated using:

SHA1_Hash ( UserID + Lang + Date Time issued + Issuing System + Local Node Pswd )

Basically, the first 4 values which are given as part of the PS_TOKEN value (acting as the salt) is hashed with the node password in order to create a signature. This is then used on subsequent requests to the server to verify the person's identity. Since the salt and the hash is known, an offline brute force attack can be done in order to find the node password.

Cracking The Node Password

Since I can't figure out how to get John to crack a SHA1 hash with a prefixed string, I modified the parser script I wrote in PHP to read passwords through stdin to test.

What I'm unsure at this point is how PeopleSoft hashes the values to generate the signature. The string values I read from the PS_TOKEN cookie appears to have null values inserted between each ASCII character which almost seems to hint that the string is encoded in UTF-8.

At the moment, I hash the guess three times: Once with the null bytes before each ASCII character, one after each ASCII character, and one without any null bytes.

See Also