Synology SA-18-15 : Photo Station - Privilege Escalation and CRLF
Get access to album shared with other groups
Summary
By modifying his description, a user is able to access albums shared with a specific group.
Proof Of Concept
Requirements:
- Create a user “test” without any specific right
- Create a “restricted” group
First, we will get the restricted group id:
# cat /etc/group | grep restricted
restricted:x:65537:
The restricted group has the 65537 ID.
Now, we can add an album to the PhotoStation and share it with the restricted group.
We can see that the test user does not have any access to this album.
Now, on the test account, we can disconnect from PhotoStation and change the user’s description with this value:
(65537)
If we return to PhotoStation with the test user, we now have access to the restricted album.
Explanation
The vulnerability is present in all synophoto_dsm_user parsing functions.
if (preg_match('/\((\d+)\)/', $item, $match)) {
$groups[] = $match[1];
}
During the login process, the /usr/syno/bin/synophoto_dsm_user is called with “–getinfo $user” parameter.
The original result of this command is :
# /usr/syno/bin/synophoto_dsm_user --getinfo test
User Name: [test]
User Type: [AUTH_LOCAL]
User uid : [1027]
User gid : [100]
Fullname : []
User Dir : [/var/services/homes/test]
User Shell: [/sbin/nologin]
Expired : [false]
User Mail: []
Alloc Size: [110]
AdminGroup: [0]
Member Of: [1]
(100) users
We can see all the groups of this user at the end.
With the special Description, the result is the following:
# /usr/syno/bin/synophoto_dsm_user --getinfo test
User Name: [test]
User Type: [AUTH_LOCAL]
User uid : [1027]
User gid : [100]
Fullname : [(65537)]
User Dir : [/var/services/homes/test]
User Shell: [/sbin/nologin]
Expired : [false]
User Mail: []
Alloc Size: [117]
AdminGroup: [0]
Member Of: [1]
(100) users
The regex used to match groups also matches our crafted description.
The parsing function is used on multiple files:
- photo_login.php
- webapi/authutil.php
- include/photo/synophoto_csPhotoMisc.php
- login.php
Remediation
Compare groups array size in PHP with the group size give by the synophoto_dsm_user program.
Empty groups array when Member Of: is reached.
CRLF flaw in DSM allows getting admin access to the PhotoStation
Summary
A CRLF (Carriage Return Line Feed) affects the Description field of users in the DSM.
This vulnerability allows modifying the result of the program /usr/syno/bin/synophoto_dsm_user used by PhotoStation to get the user’s autorization from the DSM. This vulnerability allows attackers to get administrator’s privileges on the application.
Proof Of Concept
We can reuse the test user created in the last vulnerability.
Like the other vulnerability, we will change the description field for the DSM user, but with special characters.
With a request interceptor, we will edit the description field with this value:
%0AUser Name: [root
Which represents this text (a carriage return is present in fullname)
Now, we have to connect with the DSM link (with sid,usr and SynoToken parameters). A connection from the PhotoStation interface doesn’t lead to the bug.
We are automatically connected as admin
But we can see in logs that the test user has been logged.
Explanation
This vulnerability is located in the loginFromDsm function in the login.php file.
When the test user uses the DSM link to enter the PhotoStation, the loginFromDsm is called. The user is authenticated with the following command:
# /usr/syno/bin/synophoto_dsm_user --current test aMrmsYG8F8LW.DWTY7O3CO72HI 192.168.0.8 AMijHxIFDF9R
true
If the user is valid on DSM, all information about the user is retrieved:
# /usr/syno/bin/synophoto_dsm_user --getinfo test
User Name: [test]
User Type: [AUTH_LOCAL]
User uid : [1027]
User gid : [100]
Fullname : []
User Dir : [/var/services/homes/test]
User Shell: [/sbin/nologin]
Expired : [false]
User Mail: []
Alloc Size: [129]
AdminGroup: [0]
Member Of: [1]
(100) users
With these informations, the parsing function SYNOPHOTO_LoginUserDataPaser is called to extract data from this result.
This function read lines in order. With this behavior, if we inject a new User Name: ,we are able to manipulate the username extracted.
With the crafted description of the user, here is the result of the command:
# /usr/syno/bin/synophoto_dsm_user --getinfo test
User Name: [test]
User Type: [AUTH_LOCAL]
User uid : [1027]
User gid : [100]
Fullname : []
User Name: [root]
User Dir : [/var/services/homes/test]
User Shell: [/sbin/nologin]
Expired : [false]
User Mail: []
Alloc Size: [129]
AdminGroup: [0]
Member Of: [1]
(100) users
The following PHP code sets the session value, which gives us admin privileges.
if (strtoupper($user) == "ADMIN" || strtoupper($user_info[0]) == strtoupper(SYNOPHOTO_ADMIN_NAME) ) {// admin
$_SESSION[SYNOPHOTO_ADMIN_USER]['admin_syno_user'] = SYNOPHOTO_ADMIN_PASS;
}
We can’t change the $user value, but we can change $user_info[0] value. The SYNOPHOTO_ADMIN_NAME value is root.
With this session field, we are considered “administrator” on all the PhotoStation application.
Remediation
The remediation has to be done on the DSM and the PhotoStation application.
I don’t check the impact of the CRLF on all DSM and packages, but it’s possible to have unwanted behavior with this vulnerability.
For the DSM, a character limitation on the server side can be applied to allow only good characters.
On the PhotoStation, the parsing function has to be changed to avoid unwanted values.
Here is an example of a patch:
function SYNOPHOTO_LoginUserDataPaser($pUser,$user,$ip)
{
global $SYNOPHOTO_DSM_USER_INFO;
$result = array();
if (!is_array($pUser)) {
return null;
}
$groups = array();
$groups_size = 0;
foreach ($pUser as $item) {
if (preg_match('/^\((\d+)\)/', $item, $match)) { //^ -> The group line have to start with (num)
$groups[] = $match[1];
}
if (!preg_match('/(^\w+\s?\w+)\s*\:/', $item, $match) || !preg_match('/\[(.*)\]/', $item, $match_val)) {
continue;
}
if (preg_match('/Member Of: \[(.*)\]/',$item,$group_match)){ // Get number of group
$groups = array();
$groups_size = $group_match[1];
if(sizeof($groups) != 0){
PhotoLog::Add($user." wants to access secret pictures... "."[".$ip."].", false, $user);
}
}
if (false !== $index = array_search($match[1], $SYNOPHOTO_DSM_USER_INFO)) {
if(isset($result[$index])){ // If field is overwrite.
PhotoLog::Add($user." try to attack the platform... "."[".$ip."].", false, $user);
exit(0);
}
$result[$index] = $match_val[1];
}
}
$result['groups'] = implode(',', $groups);
if(sizeof($groups) != $groups_size){
PhotoLog::Add($user." wants to access secret pictures... "."[".$ip."].", false, $user);
exit(0);
}
return $result;
}
This patch requires two additional variables to be passed to the analysis function ($user, $ip). If this patch is used without adding these parameters, it is possible to simply remove them and change the log message.
We can see on the log page that the two types of attacks are blocked.
CSRF in PhotoStation allow an attacker to get an admin account on PhotoStation
The admin part of the PhotoStation application is not protected against CSRF (Cross-Site Request Forgery) and allow an attacker to get an administrator account on the PhotoStation by sending a crafted webpage to the administrator.
Remediation
Add an anti-CSRF token to all sensitive form.