|
31
|
Programación / Desarrollo Web / Recomendaciones para baneos_bloqueos automaticos.
|
en: 23 Diciembre 2019, 05:04 am
|
Tengo implementado un sistema de bloqueos por URL (ya saben tipo /wp/login.php etc...), Usert Agent (Claramente modificados), Session (Previamente detectadas).
Si alguno de la lista se encuentra en el blacklist la IP se bloquea por algunas horas y ando un codigo de error 500.
La pregunta por recomendación aquí: ¿Es el mejor camino a seguir?, es decir ¿Bloquear el acceso y mandar error 500 o 404 es la mejor forma de proceder?
Saludos
|
|
|
32
|
Programación / Desarrollo Web / (Solucionado) Duda implementando "HMAC-based One-time Password Algorithm"
|
en: 21 Diciembre 2019, 00:02 am
|
Bueno, lo pongo aqui por que no se si corresponde mas a seguridad o PHP, pero su implementación ayuda mucho en el desarrollo WEB. Que algun moderador lo mueva a donde sea mas conveniente. Estoy implementando el algoritmo para HOTP (HMAC-based One-time Password Algorithm) En su modalidad basada en el tiempo de UNIX Actualemente tengo lo siguiente: /* dd if=/dev/urandom of=./key.dat bs=1024 count=1 */
El código actualmente genera un hash distinto cada 30 segundos exactos mi duda es como llegar a los 6 u 8 dígitos que muestra la aplicaciones de Authenticator como la de google. Nota para los que me digan que no utilize sha1, lo utilize por que wikipedia indica que es el default, pero espero que pueda ser configurable para utilizar sha256 y alguno de la misma familia. https://en.wikipedia.org/wiki/HMAC-based_One-time_Password_algorithmSaludos.
Solucionado gracias a las observaciones de MinusFour. La funcion quedo de la siguiente manera: function hotp($key,$c) { $mask = ['f' => '7','e' => '6','d' => '5','c' => '4','b' => '3','a' => '2','9' => '1','8' => '0']; $offset = intval($hash_value_str[39],16)*2; $extract = substr($hash_value_str,$offset,8); if(isset($mask[$extract[0]])) { $extract[0] = $mask[$extract[0]]; } return ($value % 1000000); }
Y para utilizarlo solo basta llamarla: $key = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; printf("%06d\n",hotp ($key,$ct));
Esto arroja los 6 dígitos que deben de coincidir con la aplicación de Autenticador que tengamos instalada en el móvil. Para este ejemplo se puede configurar manualmente como se muestra en una las imágenes.
|
|
|
33
|
Foros Generales / Dudas Generales / Emoji Fingerprint
|
en: 20 Diciembre 2019, 09:04 am
|
Estoy armando una base de datos algo grande con "firmas" de emojis de distintos navegadores, los emojis varían mucho a veces por tamaño y/o cambios del diseño entre modelos de equipos y/o marcas asi como de versión del sistema operativo. En fin, muchas variaciones disponibles: Ejemplo mismo código de emoji distintos fingerprint La pregunta aquí seria cual es la mejor forma de "identificar el navegador y demas datos" con el menor numero de que "consultas". Se me ocurre algún tipo de búsqueda binaria categorizando primero el sistema operativo y después el navegador, y tal vez por último el modelo pero solo una idea. Espero sus comentarios. Saludos!
TL;DR; Por ciero el tema mas o menos viene del articulo que publique en mi blog Dibujar emojis en canvas html5
|
|
|
34
|
Programación / Desarrollo Web / [Aporte] Validacion de token de forma Criptografica, evitar ataques CSRF
|
en: 13 Diciembre 2019, 19:32 pm
|
Entrada tambien en mi blog: Validacion de token de forma Criptografica, evitar ataques CSRFBueno esto viene del tema que abrio el usuario MiguelCanellas [Aporte]: Sistema Anti ataques CSRF (Espero sugerencias). La forma mas sencilla de genera un token sin incluir nada de criptografia y que se envie al usuario para posteriormente ser validado es la siguiente: $token = hash("sha256",random_bytes (32));
Esto nos produce una cadena hash sha256 apartir de 1Kilobyte de datos random. La cosa seria sencilla guardarlo en la $_SESSION en el server y mandarlo al usuario, si lo devuelve comparamos que sean iguales y listo no hay mucho pierde. Se necesita mas seguridad.... ? El simple hecho que tengamos una cadena hash sha256 apartir de 1Kilobyte de datos random. hace casi imposible que alguien pueda generar el token por si solo y que coincida con el que generamos nosotros, podriamos incrementar la cantidad de bytes generados por la funcion openssl_random_pseudo_bytes simplemente incrementando su valor. Ahora si realmente queremos proteger la informacion mediante criptografia tenemos que hacer las cosas bien. Una implentacion rapida para ejemplificar este proceso es la siguiente: <?php $cipher = 'AES-256-CBC'; //SUIT de cirado utilizada $strkey = "s3cr3tk3yh4x0r"; //Clave en el servidor, secreta, cambiar esta clave de ejemplo POR FAVOR de preferencia utilizar una clave generada de forma segura con openssl_random_pseudo_bytes o /dev/random $realkey = hash("sha256",$strkey,true); //Hash de la clave en formato Raw $ivlen = openssl_cipher_iv_length($cipher); // Obtenemos el tamaño del Vector Inicializado de acuardo a la Suit de cifrado que estemos utilizando $iv = openssl_random_pseudo_bytes($ivlen); // Obtenemos $ivlen bytes random no nos interesa saber su valor $token = hash("sha256",random_bytes (32)); //Token sin cifrar este valor nuca lo ve el UserAgent $token_cifrado = openssl_encrypt($token,$cipher,$realkey,OPENSSL_RAW_DATA,$iv); $salida = base64_encode($token_cifrado); //Este valor si lo ve el User Agent echo "token: ".$token."\n"; echo "token cifrado, salida raw: ".$token_cifrado ."\n"; echo "token cifrado, salida base64: ".$salida."\n"; $token_decifrado = openssl_decrypt($entrada,$cipher,$realkey,OPENSSL_RAW_DATA,$iv); echo "token decifrado: ".$token_decifrado ."\n"; if($token_decifrado == $token) { echo "token correcto\n"; } else { echo "token Incorrecto\n"; } ?>
Si vemos el codigo anterior el "token" que enviaremos al usuario es la salida en base64 del token previamente cifrado. Acontinuacion una posible salida de las casi infinitas salidas.... token: 5ab8aac170554a2683e0cc0534a34e80d0f16031a13faa3c3a5ee44902b2c6a1 token cifrado, salida raw: CU?!,F8C4d1su SN{|큮vDjUa=qQKKKȀE#(@/I token cifrado, salida base64: AUO6plUB9j8h+IvsyixGOAfZQzRkCzG84XN1vN7X2Aq2CVNOont87YGudsJEq2q1VWE9vZhxqJWfUUviv0tL9ciA+kWTI74oGEAvl4sSSak= token decifrado: 5ab8aac170554a2683e0cc0534a34e80d0f16031a13faa3c3a5ee44902b2c6a1 token correcto
La idea en este caso es enviar la informacion cifrada al usurio y cuando este la envie devuelta se descifra y se compara con la almacenada previamente en la $_SESSION del usuario. Cosas que se pueden mejorar el valor de nuestra Key inicial podria ser un archivo random en nuestro servidor generado previamente, podriamos tener una llave distinta por usuario, etc etc etc...
|
|
|
35
|
Programación / Desarrollo Web / Como crear un formulario de comentarios para tu web
|
en: 13 Diciembre 2019, 05:09 am
|
Funte: Como crear un formulario de comentarios para tu webPues nada lo primero es tener el Formulario en HTML. Posterior mente el javascript para validar el formulario antes de enviarlo El script en el Backend para volver a validar los datos. El metodo de almacenamiento del comentario (Base de datos) Un sistema para evitar que saturen de comentarios basura Y al final pero mas importante EVITAR SER HACKEADO (xss, sql, file inclusion etc etc etc etc etc) El codigo en HTML para el formulario utilizando Boostrap: <h4>Deja un comentario </h4> <p></small>Tu dirección de correo electrónico no será publicada. <b>Los campos obligatorios están marcados con * </b></small></p> <label for="exampleInputUsername">Nombre * </label> <input type="text" class="form-control" id="exampleInputUsername" aria-describedby="usernameHelp"> <small id="usernameHelp" class="form-text text-muted">Nombre para mostrar, este campo si va a ser mostrado </small> <label for="exampleInputEmail">Correo Electronico * </label> <input type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp"> <small id="emailHelp" class="form-text text-muted">Tu direccion de correo electronico no sera publicada </small> <input type="text" class="form-control" id="exampleInputWEB" aria-describedby="webHelp"> <small id="webHelp" class="form-text text-muted">Direccion WEB Segura valida ejemplo: https://www.example.com/ </small> <label for="exampleTextAreaComentario">Comentario * </label> <textarea class="form-control" id="exampleTextAreaComentario" rows="5" aria-describedby="comentarioHelp"></textarea> <small id="comentarioHelp" class="form-text text-muted">Todos los comentarios seran moderados antes de ser publicados </small> <div class="form-group form-check"> <input type="checkbox" class="form-check-input" id="exampleCheckboxSubscribe"> <label class="form-check-label" for="exampleCheckboxSubscribe">Recibir notificaciones de Respuestas a tus comentarios </label> <button type="button" class="btn btn-primary">Publicar Comentario </button> <button type="button" class="btn btn-secondary">Vista Previa </button> <div id="comentario_vista_previa">
Resultado:
|
|
|
36
|
Programación / Desarrollo Web / Utilizar reCAPTCHA v3 para evitar intentos de fuerza bruta
|
en: 11 Diciembre 2019, 02:04 am
|
Fuente Utilizar reCAPTCHA v3 para evitar intentos de fuerza brutaEn el Post que acabo de publicar básicamente se muestra el código en javascript y en PHP para implementar el reCAPTCHA v3 en un Formulario para evitar ataques de fuerza bruta. Codigo en PHP: <?php try { //Validar datos POST or GET aqui. 'secret' => "SECRET KEY HERE THIS VALUE MUST BE PRIVATE...", 'response' => $_POST['reCAPTCHA_Token'],//Token devuelto por Google al Front End y enviado a este formulario 'remoteip' => $_SERVER['REMOTE_ADDR'] //Direccion IP publica del cliente que envia el formulario ) ); 'method' => 'POST', 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => $post_data ) ); $response = file_get_contents('https://www.google.com/recaptcha/api/siteverify', false, $context); if($result->action != $_POST["action"]) { throw new Exception("Google recaptcha action missmatch"); } if($result->score < 0.5) { throw new Exception("Google recaptcha score too low"); } //Devuelta a las validaciones actuales de seguridad para los datos recibidos }catch(Exception $e) { //catch exception here } ?>
saludos!
|
|
|
37
|
Programación / Desarrollo Web / (Solucionado) Problema con data de Ajax
|
en: 8 Diciembre 2018, 18:04 pm
|
Hola que tal espero y me puedan ayudar, tengo un error de lo mas tonto. Sin embargo no se por que el jquery no esta enviando el data mediante Ajax. JS function local_search() { $.ajax({ async: true, type: "GET", accepts: "application/json", url: "/api/search", data: { s: $("#input_str").value }, success: function (result) { alert(result.ok); } }); }
HTML: <input id="input_str" type="text">
Puedo ver que si hace la peticion al servidor, pero no envia nunca la data RAW Request Host: localhost User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0 Accept: undefined Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: http://localhost/ X-Requested-With: XMLHttpRequest Connection: keep-alive Pragma: no-cache Cache-Control: no-cache
SoluciónCodigo Incorrecto data: { s: $("#input_str").value }, Codigo Correcto[code] data: { s: $("#input_str").val() }, [/code]
|
|
|
38
|
Foros Generales / Noticias / Hackean Quora?
|
en: 4 Diciembre 2018, 03:05 am
|
Dear ......
We are writing to let you know that we recently discovered that some user data was compromised as a result of unauthorized access to our systems by a malicious third party. We are very sorry for any concern or inconvenience this may cause. We are working rapidly to investigate the situation further and take the appropriate steps to prevent such incidents in the future.
What Happened
On Friday we discovered that some user data was compromised by a third party who gained unauthorized access to our systems. We're still investigating the precise causes and in addition to the work being conducted by our internal security teams, we have retained a leading digital forensics and security firm to assist us. We have also notified law enforcement officials.
While the investigation is still ongoing, we have already taken steps to contain the incident, and our efforts to protect our users and prevent this type of incident from happening in the future are our top priority as a company.
What information was involved
The following information of yours may have been compromised:
Account and user information, e.g. name, email, IP, user ID, encrypted password, user account settings, personalization data
Public actions and content including drafts, e.g. questions, answers, comments, blog posts, upvotes
Data imported from linked networks when authorized by you, e.g. contacts, demographic information, interests, access tokens (now invalidated)
Questions and answers that were written anonymously are not affected by this breach as we do not store the identities of people who post anonymous content.
What we are doing
While our investigation continues, we're taking additional steps to improve our security:
We’re in the process of notifying users whose data has been compromised. Out of an abundance of caution, we are logging out all Quora users who may have been affected, and, if they use a password as their authentication method, we are invalidating their passwords. We believe we’ve identified the root cause and taken steps to address the issue, although our investigation is ongoing and we’ll continue to make security improvements.
We will continue to work both internally and with our outside experts to gain a full understanding of what happened and take any further action as needed.
What you can do
We’ve included more detailed information about more specific questions you may have in our help center, which you can find here.
While the passwords were encrypted (hashed with a salt that varies for each user), it is generally a best practice not to reuse the same password across multiple services, and we recommend that people change their passwords if they are doing so.
Conclusion
It is our responsibility to make sure things like this don’t happen, and we failed to meet that responsibility. We recognize that in order to maintain user trust, we need to work very hard to make sure this does not happen again. There’s little hope of sharing and growing the world’s knowledge if those doing so cannot feel safe and secure, and cannot trust that their information will remain private. We are continuing to work very hard to remedy the situation, and we hope over time to prove that we are worthy of your trust.
The Quora Team
|
|
|
39
|
Programación / Programación C/C++ / Error con send de Winsock (Solucionado)
|
en: 1 Diciembre 2018, 23:21 pm
|
Muy buen dia. Estoy trabajando con un servidor http de lo mas básico posible. Tengo un error al momento de enviar el contenido. El navegador a veces recibe los archivos incompletos y no logro ubicar el error. El navegador indica que solo recibe 768KB para el penultimo archivo "/test.mp3" La salida del programa indica lo siguiente para ese archivo. Leido indica la cantidad de bytes que a leido desde el archivo: fseek(contenido ,offset ,SEEK_SET ); leido = fread(buffer ,1,size ,contenido ); printf("Leido %i %s\n",leido ,path ); if(leido != size) { fprintf(stderr ,"fread() read %i vs request %i\n",leido ,size ); }
leido toma la cantidad que devuelve fread, si leido y size son distintos el programa termina inmediatamente. Posteriormente mando ese buffer leido al comando send. int send_all(SOCKET descriptor, const void *buffer, size_t length, int flags) { ssize_t n; const char *p = buffer; while (length > 0) { n = send(descriptor, p, length, flags); if (n <= 0) return -1; p += n; length -= n; } return 0; }
send all indica mediante la variable "n" la cantidad de datos enviados por send. Asi mismo en los headers recibe correctamente el mismo numero indicado por el programa: Asi que dado que la cantidad de items leidos por fread es la misma que la cantidad de bytes enviados por send, no entiendo por que el navegador no recibe todo el archivo, ya que al momento de tratar de reproducirlo esta incompleto. Saludos
Al final quedo solucionado modificando la funcion send all. Por alguna razon dice que a enviado todos lo 2 MB pero el navegador solo recibio los 700 KB. Modique la funcion para que envie de 64 bytes por vez y ahora envio el documento completo int send_all(SOCKET descriptor, const void *buffer, int length, int flags) { int n,s; const char *p = buffer; while (length > 0) { s = ( length > 64 ) ? 64: length; n = send(descriptor, p, s, flags); if (n <= 0) return -1; p += n; length -= n; } return 0; }
Y el programa marca exactamente la misma cantidad. Saludos!
|
|
|
40
|
Programación / Programación C/C++ / Primero en Entrar, primero en salir FIFO, Cola o Fila
|
en: 30 Noviembre 2018, 18:38 pm
|
No es lo mas eficiente, hay muchas cosas se podrian mejorar, en especifico la forma en la que se organizan el arreglo de elementos actuales en la Fila, sin embargo funciono para el proposito. Yo se que la mayoría de estas estructuras ya están implementadas. Pero no se puede decir que eres programador si no sabes implementarlas por tu cuenta. /* El tipo de dato se puede cambiar dependiendo de la implementación que se le quiera dar, también se tendrían que cambiar los tipos de datos devueltos por las funciones En este caso yo quería un arreglo de apuntadores char* por lo cual el contenedor es char** */ typedef struct str_queue { char **queue; int len; int max; }Queue; Queue *create_queue() { Queue *r = malloc(sizeof(struct str_queue )); r->len = 0; r->max = 2; r ->queue = malloc(sizeof(char*)*r ->max ); return r; } void free_queue(Queue *q) { if(q) { if(q->queue) } } void en_queue(Queue *q, char *ptr) { if((q->len+1) == q->max) { q->max *= 2; q ->queue = realloc(q ->queue ,q ->max *sizeof(char*)); } if(q->queue != NULL) { q->queue[q->len] = ptr; q->len++; } } char * de_queue(Queue *q) { char *r = NULL; int i = 0; if(q->len >= 1) { r = q->queue[0]; q->len--; while(i < q->len) { q->queue[i] = q->queue[i+1]; i++; } q->queue[i] = NULL; } return r; }
Yo en su momento lo utilize para un post, donde realizaba una versión iterativa y necesitaba almacenar en una Cola el listado de los directorios que aun faltaba por recorrer: problema de memoria con readdir (Solucionado)Ejemplo de uso: int main() { char *cadenas[10] = { "Cadena_0","Cadena_1","Cadena_2","Cadena_3","Cadena_4","Cadena_5","Cadena_6","Cadena_7","Cadena_8","Cadena_9"}; char *actual; int index1,index2,i =0; Queue *q = create_queue(); while(i < 10) { printf("Agregando a la fila: %s\n",cadenas [index1 ]); en_queue(q,cadenas[index1]); printf("Agregando a la fila: %s\n",cadenas [index2 ]); en_queue(q,cadenas[index2]); printf("Saliendo de la fila %s\n",de_queue (q )); i++; } free_queue(q); }
Como es randon la salida es variada, pero podemos observar el funcionamiento: Agregando a la fila: Cadena_5 Agregando a la fila: Cadena_5 Saliendo de la fila Cadena_5 Agregando a la fila: Cadena_8 Agregando a la fila: Cadena_2 Saliendo de la fila Cadena_5 Agregando a la fila: Cadena_5 Agregando a la fila: Cadena_7 Saliendo de la fila Cadena_8 Agregando a la fila: Cadena_8 Agregando a la fila: Cadena_7 Saliendo de la fila Cadena_2 Agregando a la fila: Cadena_9 Agregando a la fila: Cadena_2 Saliendo de la fila Cadena_5 Agregando a la fila: Cadena_1 Agregando a la fila: Cadena_3 Saliendo de la fila Cadena_7 Agregando a la fila: Cadena_8 Agregando a la fila: Cadena_5 Saliendo de la fila Cadena_8 Agregando a la fila: Cadena_0 Agregando a la fila: Cadena_3 Saliendo de la fila Cadena_7 Agregando a la fila: Cadena_4 Agregando a la fila: Cadena_0 Saliendo de la fila Cadena_9 Agregando a la fila: Cadena_7 Agregando a la fila: Cadena_1 Saliendo de la fila Cadena_2
Funcion actualizada de de_queue char * de_queue(Queue *q) { char *r = NULL; int i = 0; if(q->len >= 1) { r = q->queue[0]; q->len--; while(i < q->len) { q->queue[i] = q->queue[i+1]; i++; } q->queue[i] = NULL; } return r; }
|
|
|
|
|
|
|