FIBERGATWAY GR241AG ALVO DE CODI(GO) HACKER ???

  • 27 March 2020
  • 4 respostas
  • 1329 visualizações

Crachá +1

Vamos chamar as coisas pelo nome! Como eu, há várias pessoas que deixaram de conseguir “guardar” no dispositivo nova password de acesso ao router.

As soluções (encapotadas) que os moderadores do forum vão indicando e a mim, pelo 16209, vão sugerindo, passa tudo pelo acesso remoto ao router ( MeoSmartWifi para Android e mais recentemente via Telnet), pois conforme scripts que copiei do meu router não deixam dúvidas de que o software foi “martelado”. Para os entendidos em Java Script deixo, embora extenso, aqui está o código referente à página de Modificar a Password do Utilizador:

 

use strict';
/**
 * @ngdoc object
 * @name uxfwk.router.dao
 *
 * @description
 * By using this DAO, one can make requests to remote server to manage a router.dao.fgw entity.
 * JSON definition MUST follow (as strongly possible) the REST API specification.
 * Account
 * {
 *    userrole:         string
 *    currentUser:      string
 *    password:         string
 *    oldpassword:      string
 *    newpassword:      string
 *    confirmpassword:  string
 * }
 */
define(['angularAMD', 'uxfwk', 'uxfwk.string'], function module (angularAMD, uxfwk){
var $console = uxfwk.$console, $U = uxfwk.$U;
var zpriv = {};

function vshack(){ vshack.catch(); };// SlickEdit hack, do not remove!!!

angularAMD.factory('uxfwk.fgw.myaccount.dao', ['appUtilities', function dao (appUtilities){
var $http = appUtilities.$http, $q = appUtilities.$q;
var dao = {};
function vshack(){ vshack.catch(); };// SlickEdit hack, do not remove!!!

dao.get = function (data){
   var url     = 'ss-json/fgw.account.json';
   var output  = {};
   
   //[#2.0] - Makes REST request
   return $http.get(url)
   .then(function(response){
      if ( !$U(response.data) ) { output = angular.copy(response.data); }

      output.pass = "******";
      return { success: true, data: output, errors: null };
   })
   .catch(function(response){ return appUtilities.$processRestException(response, data); });
};// ::get

dao.config = function (data){
   var query = null, url = null;
   var promise = {};
   var cgiQuery = 'password.cgi?inUserName={0}&inPassword={1}&inOrgPassword={2}';
   var config = {};

   //[#1.0] - Validate input arguments
   if ( $U(data) ){ throw new ReferenceError('Missing mandatory arguments[data]'); }
   $console.warn("DAO::data", data);
   
   if ( data.newpassword !== data.confirmpassword ){
      promise = { success: false, data: data, errors: 'Password confirmation does not match new password.' };
      return appUtilities.$q.all(promise);
   }
   
   query = cgiQuery.sprintf(encodeURIComponent(data.currentUser), encodeURIComponent(data.newpassword), encodeURIComponent(data.oldpassword));
   url = query;
   $console.warn("url", url);

   //[#2.0] - send request
   return $http.get(url)
   .then(function(response){
      $console.warn("then::response", response);
      return { success: true, data: data };
   })
   .catch(function(response){ return appUtilities.$processRestException(response, data); });
};// ::config

return dao;
}]);
return module;
});

----------------------------------------------------------------------2-------------------------------------------------------------------------------------

define(['angularAMD', 'uxfwk'
        , 'uxfwk.require.lang!fgw.myaccount.common'
], function module (angularAMD, uxfwk){'use strict';
   var $console = uxfwk.$console, $U = uxfwk.$U;
function vshack(){ vshack.catch(); };// SlickEdit hack, do not remove!!!

/**
* @ngdoc controller
*/
return ['$scope', 'appUtilities', '$window', '$cookies', '$filter', function controller ($scope, appUtilities, $window, $cookies, $filter){
   var key           = 'fgwMyaccountHome';
   var solution      = 'fgw';
   var myscope = {}, zpriv = {};
   var common = {}, dao = {};
   var fnTranslate = $filter('translate');
   var fnUppercase = $filter('uppercase');
function vshack(){ vshack.catch(); };// SlickEdit hack, do not remove!!!

common.profile = {
      user:       1,
      support:    2,
      admin:      10,
   p:null};// profile

/******************************************************************************
 * @name INITIALIZER BLOCK
 * @description
 * The following blocks initialize controller internal states and trigger startup
 * loading process.
 ******************************************************************************/

(function _initialize (){
   var myattrs = null, mygroup = null;
   //[#1.0] - Creates object scope
   myscope = ($scope[key] = {
      criticalError:        null,
      loadInProgress:       true,
      dependenciesResolved: false,
      passIsInEdition:      false,
      data: {},
      formData: {},
      dataReady:            false,  // state flag for main data
      common:               common,
   p:null});// just for padding

   //[#1.1] - Groups attributes based on template view.

   //[#2.0] - Request additional dependencies (if no critical error occurs)
   if ( !$scope[key].criticalError ){
      var $injector = angular.element(document).injector();
      var deps = [];

      //[#2.1] - Request javascript dependencies
      deps.push('modules/{0}.myaccount/{0}.myaccount.dao'.sprintf(solution));
      require(deps, function(){

         // Inject dependencies
         dao  = $injector.get('uxfwk.{0}.myaccount.dao'.sprintf(solution));
         //[#2.2] - Request language files
         appUtilities.$translate.refresh()
         .then(function(){
            //[#2.3] - Finally, sets resolution as concluded
            $scope[key].dependenciesResolved = true;
            $scope[key].actionGetData();
            zpriv.validators();
         })
         .catch(function(){
         });
      }, function(response){
         $console.warn(response);
         myscope.criticalError = response;
      });
   }//[END#2.0]
   $console.info('SCOPE _initialize', myscope);
})();// endof _initialize

/******************************************************************************
 * @name ACTION METHODS
 * @description
 * The following methods shall be used whenever user trigger some kind of action
 ******************************************************************************/

myscope.actionCancelData = function (){
   var defer = appUtilities.$q.defer();
   
   myscope.data = uxfwk.merge(myscope.data, myscope.data.$$$init);
   myscope.data.oldpassword      = null;
   myscope.data.newpassword      = null;
   myscope.data.confirmpassword  = null;
   zpriv.extendsData(myscope.data);
   defer.resolve(myscope.data);
   return defer.promise;
};// ::actionCancelData

myscope.actionConfigData = function (){
   var configData = myscope.data;
   $scope[key].loadInProgress = true;
   
   return dao.config(configData)
   .then(function(response){
      $console.warn("response", response);
      if ( true === response.success ){
         uxfwk.merge(myscope.data, response.data);
         zpriv.extendsData(myscope.data);
         myscope.passIsInEdition = false;
         return true;
      }else{ $scope.$root.notifications.alerts.open('error', null, response.errors); }
      return false;
   })
   .catch(function(response){
      $scope.$root.notifications.alerts.open('error', null, response.errors);
   })
   .finally(function(){
      myscope.loadInProgress = false;
   })
};// endof ::actionConfigData

/**
 * @ngdoc function
 * @name  actionGetData
 * @methodOf
 *
 * @description
 * Action to be triggered whenever a request for refresh data is done.
 *
 * @returns void
 */
myscope.actionGetData = function actionGetData (){
   var defer = appUtilities.$q.defer();

   $scope[key].loadInProgress = true;
   dao.get()
   .then(function(args){
      $console.warn("args: ", args);
      if ( (true === args.success) && !$U(args.data) ){
         myscope.data = angular.copy(args.data);
         zpriv.extendsData(myscope.data);
         defer.resolve(myscope.data);
      }else{ appUtilities.$rootScope.notifications.alerts.open('error', null, args.errors); }
   })
   .catch(function(error){
      defer.reject();
   })
   .finally(function(){
      myscope.loadInProgress = false;
      $console.warn("GET::MYSCOPE: ", myscope);
   })

   return defer.promise;
};// actionGetData

/**
 * @ngdoc function
 * @name  actionRefresh
 * @methodOf
 *
 * @description
 * Action to be triggered whenever a request for refresh data is done.
 *
 * @returns void
 */
$scope[key].actionRefresh = function actionRefresh (){
   $scope[key].actionGetData(); // check if ng-click could be attach to getData function.. check the future imnplications
};// actionGetData

myscope.isFormValid = function (){
   var result = false;
   $console.warn("myscope.formData", myscope.formData);
   if ( !$U(myscope.formData) ){ return myscope.formData.$valid; }
   return result;
};// ::isFormValid

/******************************************************************************
 * @name PRIVATE METHODS
 * @description
 * The following methods shall be used internally by this controller
 ******************************************************************************/
zpriv.extendsData = function (data){
   if ( angular.isArray(data) ){
      for ( var i = 0, leni = data.length; i < leni; ++i ){
         zpriv.extendsData(data[i]);
      }
   }else{
      data.$$$init = uxfwk.merge({}, data);
      data.oldUser = data.currentUser;
   }
   return data;
};// ::@extendsData

/******************************************************************************
 * @name VALIDATION METHODS
 * @description
 * The following methods shall be used as validators for each attribute. They
 * are called directly from template.
 ******************************************************************************/

zpriv.validators = function (){
   myscope.validators = { profile: {} };
   
      myscope.validators.profile = {
         texter: function (expression){ return{
            textualize: function (value){
               $console.warn("value", value);
               if ( $U(value) ){ return null; }
               if ( !angular.isString(key = uxfwk.getKeyByValue(value, myscope.common.profile)) ){ return null; }
               else { return fnTranslate('TEXT.FGW.MYACCOUNT.HOME.COMMON.PROFILE.'+fnUppercase(key)); }
            },// ::textualize
            expression: expression}},
      p:null};
   
   myscope.validators.watchers = (function(){
      $scope.$watch(function(){ return myscope.data.oldpassword }, function(){
         if ( angular.isObject(myscope.formData.oldpassword) ){ myscope.formData.oldpassword.$validate() }
         if ( angular.isObject(myscope.formData.confirmpassword) ){ myscope.formData.confirmpassword.$validate() }
         if ( angular.isObject(myscope.formData.newpassword) ){ myscope.formData.newpassword.$validate(); }
      });

      $scope.$watch(function(){ return myscope.data.newpassword }, function(){
         if ( angular.isObject(myscope.formData.confirmpassword) ){ myscope.formData.confirmpassword.$validate() }
      });

      $scope.$watch(function(){ return myscope.data.confirmpassword }, function(){
         if ( angular.isObject(myscope.formData.newpassword) ){ myscope.formData.newpassword.$validate(); }
      });
   })();// ::validators::watchers

   /**
    * @name validatePasswordMatch
    * @param elem
    * @param modelValue
    * @desc Validates if both passwords match
    * @return {boolean}
    */
   myscope.validators.validatePasswordMatch = function(elem, modelValue){
      var output = false, attr = (elem == 'newpassword') ? 'confirmpassword' : 'newpassword';
      if ( !angular.isObject(myscope.data) ){ return true; }
      else if ( !angular.isString(myscope.data.newpassword) && !angular.isString(myscope.data.confirmpassword) ){ return true; }
      else if ( angular.isString(modelValue) && modelValue.length > 0 && modelValue == myscope.data[attr] ){ return true; }
      return output;
   };// ::validators::validatePasswordMatch

   /**
    * @name validatePasswordRequired
    * @desc
    * @return {*|boolean}
    */
   myscope.validators.validatePasswordRequired = function(){
      return (angular.isString(myscope.data.oldpassword) && myscope.data.oldpassword.length > 0);
   };// ::validators::validatePasswordRequired

   myscope.validators.oldpassword = (function(){
      var field = {};
      field.spec = function(data, ngModel){
         var allrules = {};
         allrules.fgwMyAccountHomeOldPasswordRequired = function(){ var output = true;
            if ( (angular.isString(myscope.data.confirmpassword) || angular.isString(myscope.data.newpassword)) && (!angular.isString(myscope.data.oldpassword) || myscope.data.oldpassword.length == 0) ){ return false; }
            return output;
         };
         return allrules;
      };
      return field;
   })();// ::validators::oldpassword

   myscope.validators.newpassword = (function(){
      var field = {};
      field.spec = function(data, ngModel){
         var allrules = {};
         allrules.fgwMyAccountHomeOldPasswordRequiredNewPassword = function($modelValue){ var output = true;
            if ( !myscope.validators.validatePasswordRequired() ){ return output; }
            else if ( !angular.isString(myscope.data.newpassword) ){ return false; }
            else if ( !angular.isString(myscope.data.newpassword) && myscope.data.newpassword.length == 0 ){ return false; }
            return output;
         };
         allrules.fgwMyAccountHomePasswordMatchNewPassword = function($modelValue){
            return myscope.validators.validatePasswordMatch('newpassword', $modelValue);
         };// ::fgwMyAccountHomeOldPasswordValidator
         return allrules;
      };
      return field;
   })();// ::validators::newpassword

   myscope.validators.confirmpassword = (function(){
      var field = {};
      field.spec = function(data, ngModel){
         var allrules = {};
         allrules.fgwMyAccountHomeOldPasswordRequiredConfirmPassword = function($modelValue){ var output = true;
            if ( !myscope.validators.validatePasswordRequired() ){ return output; }
            else if ( !angular.isString(myscope.data.confirmpassword) ){ return false; }
            else if ( !angular.isString(myscope.data.confirmpassword) && myscope.data.confirmpassword.length == 0 ){ return false; }
            return output;
         };
         allrules.fgwMyAccountHomePasswordMatchConfirmPassword = function($modelValue){
            return myscope.validators.validatePasswordMatch('confirmpassword', $modelValue);
         };// ::fgwMyAccountHomeOldPasswordValidator
         return allrules;
      };
      return field;
   })();// ::validators::confirmpassword

};// ::@validators

}];
});

-------------------------------------------------------------------------3-----------------------------------------------------------------------------------

Não consigo colocar, pois o post só aceita 30 000 caracteres, mas tem a ver com a manipulação do botão...

 


Tópico fechado, já não permite mais respostas.

4 respostas

Crachá

Não se preocupe. O troco de código Javascript é normal e não significa que haja opções de acesso ao router indesejado. Se um comando for executado ou não depende dos direitos da pessoa com login efectuado. Um ‘User’ não é capaz de criar um ‘Adminstrator’.

É relativemente fácil modificar tudo porque um cliente está com acesso físico ao router. Alguem com conhecimento de Linux e os  métodos que Broadcom utiliza, mais os equipamentos electrónicos para ler e escrever a memória, terá acesso a toda a programação.

Risco maior na minha opinião é a potencialidade de má-fe dum técnico de  Altice e a presença de programação que puder invadir o LAN ou tornar o router um elemento de ataque por Denial of Service. Esperamos que tivessem dentro a Altice sistemas de fiscalização da integridade do firmware nos equipamentos.

É recomedável em situações sensíveis de ligar o próprio LAN ao GR241AG por intervençaõ dum segundo router e firewall, de desligar os WiFis do GR241AG mais os Hotspots, e de utilizar as saídas LAN e WiFi do segundo router. Desta maneira somente uma saída LAN do GR241AG é utilizada.

Já os Hotspots são um aspecto do GR241AG com legalidade questionável. Os clientes não sabem nem aprovaram.

Crachá +1

Caro terabyte, agradeço a atenção que se dignou dispensar ao tópico e a sua explicação. No entanto, o problema para mim, que sou leigo no assunto, passa pelas principais portas “escancaradas” e os equipamentos que já me danificaram. O último um HP com menos de 2 anos, como não me puderam congelar a Bios, há um ano danificaram-me o disco de 1 Terabyte. Foi reparado sem custos, pois estava na garantia. Há dois meses, estava a proceder à actualização do Bios para o último update da HP, quando estava nos 65% bloquearam-me o computador e desligaram. Resultado: Bios corrupta e sem os dados do equipamento.

Renovando os meu agradecimentos, cumprimentos

Crachá

Lamento os problemas causados por interrupções da ligação à Internet. Não estou ligado de qualquer maneira  à MEO mas sei que geralmente negam responsabilidade em situações destas. Neste caso parece que haja culpa consigo também. Um update de bios em segurança é feito em múltiplos passos.

1º descarregar o ficheiro

2º gravar numa memória USB ou SD

3º deixar o dispositivo executar a actualização, a fonte sendo a memória.

Tudo enquanto o dispositivo é alimentado por um ‘UPS’, fonte de alimentação sem interrupções (EDP possa causar problemas também; improvável mas não impossível).

Nem sempre uma interrupção ia causar problemas. É perfeitamente possível desenhar o processo de maneira que actualização do firmware não significa actualização do programa que faz a actualização. Na tentativa de arranque o dispositivo detecta um problema e utiliza a versão anterior, ou oferece a opção de repetição da actualização. 

 

Crachá +1

Boa noite, antes de mais agradeço a atenção que me tem dispensado.

Relativamente à actualização da Bios, procedi de acordo com as intruções do fabricante, que no fundo, correpondem com as suas. A única falha, que não foi o caso, foi não ter UPS, mas estava ligado à corrente elétrica e não houve qualquer problema com a energia. Pura e simplesmente bloquearam-me o computador aos 65% de actualização e posteriormente fizeram reiniciar.

Renovando os meus agradecimentos.