Synology SA-18-15 : Photo Station - Privilege Escalation and CRLF

CVE 2018-8925 CVE 2018-8926 Synology SA-18:15

DSM 6.5.1-15254 PhotoStation 6.8.4-3468

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:

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.

5f0be826addb7fe2a02395c3cf52e38c.png

c191d878052082893602a596e1778fa0.png

We can see that the test user does not have any access to this album.

347722a12f68662171ab8625f79e422f.png

Now, on the test account, we can disconnect from PhotoStation and change the user’s description with this value:

(65537)

1fb163fd295cba45557bb066239b2227.png

If we return to PhotoStation with the test user, we now have access to the restricted album. b28a81e302377204c78c37424cf05791.png

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:

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

03b16635e8f932eafafb5db1a421b130.png

Which represents this text (a carriage return is present in fullname)

d7553fe2103280afd204df895977ea8f.png

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

c76aad246111d1911dff4273f68c985d.png

But we can see in logs that the test user has been logged.

86add36d7730cca1118af80df81fd3f0.png

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.

d54c0be952de97bea5086699d3679eac.png

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.