language-agnostic url sanitization spam-prevention

language agnostic - Detectando un URL(travieso o agradable) o un enlace en una cadena de texto



language-agnostic sanitization (13)

¿Cómo puedo detectar (con expresiones regulares o heurísticas) un enlace a un sitio web en una cadena de texto, como un comentario?

El objetivo es evitar el spam. El HTML está desprotegido, así que necesito detectar las invitaciones para copiar y pegar. No debe ser económico para un spammer publicar enlaces porque la mayoría de los usuarios no pueden acceder a la página . Me gustaría sugerencias, referencias o discusiones sobre las mejores prácticas.

Algunos objetivos:

  • La fruta http://some-fqdn/some/valid/path.ext como URL bien formadas ( http://some-fqdn/some/valid/path.ext )
  • URL pero sin el prefijo http:// (es decir, un FQDN válido + ruta HTTP válida)
  • Cualquier otro negocio divertido

Por supuesto, estoy bloqueando el spam, pero el mismo proceso podría usarse para vincular automáticamente el texto.

Ideas

Aquí hay algunas cosas que estoy pensando.

  • El contenido es en prosa en el idioma nativo, así que puedo ser feliz en la detección
  • ¿Debo quitar todos los espacios en blanco primero, para ver " www .example.com "? ¿Los usuarios comunes sabrían eliminar el espacio ellos mismos, o hacer navegadores que digan "do-what-I-mean" y quitárselos?
  • Tal vez múltiples pases es una mejor estrategia, con escaneos para:
    • URL bien formadas
    • Todos los espacios no en blanco seguidos de ''.'' seguido de cualquier TLD válido
    • ¿Algo más?

preguntas relacionadas

He leído esto y ahora están documentados aquí, por lo que solo puede hacer referencia a las expresiones regulares en esas preguntas si lo desea.

Actualización y resumen

¡Vaya, aquí hay una heurística muy buena! Para mí, el mejor bang-for-the-buck es una síntesis de lo siguiente:

  1. La técnica de @Jon Bright para detectar TLD (un buen punto de choque defensivo)
  2. Para esas cadenas sospechosas, reemplace el punto con un personaje que parezca un punto según @capar
  3. Un buen personaje con aspecto de punto es @ Sharkey''s subscripted & middot; (es decir, " · "). & middot; también es un límite de palabras por lo que es más difícil copiar y pegar de manera informal.

Eso debería hacer que el CPM de un spammer sea lo suficientemente bajo para mis necesidades; los comentarios del usuario "marcar como inadecuado" deberían captar cualquier otra cosa. Otras soluciones enumeradas también son muy útiles:

  • Elimina todos los cuadrantes con puntos (el comentario de @ Sharkey a su propia respuesta)
  • Requisito de @ Sporkmonger para Javascript del lado del cliente que inserta un campo oculto requerido en el formulario.
  • Hacer ping al lado del servidor URL para establecer si se trata de un sitio web. (Quizás podría ejecutar el HTML a través de SpamAssassin u otro filtro bayesiano según @Nathan ...)
  • Mirando la fuente de Chrome para su barra de direcciones inteligentes para ver qué trucos inteligentes usa Google
  • Llamando a OWASP AntiSAMY u otros servicios web para detectar spam / malware.

Bueno, obviamente las frutas que cuelgan son cosas que comienzan con http: // y www. Intentar filtrar cosas como "www .g mail. Com" lleva a interesantes preguntas filosóficas sobre qué tan lejos quieres ir. ¿Quieres llevarlo al siguiente paso y filtrar también "www dot gee mail dot com"? ¿Qué hay de descripciones abstractas de una URL, como "La abreviatura de World Wide Web seguido de un punto, seguido de la letra g, seguido de la palabra correo seguido de un punto, concluyó con la abreviatura de TLD para comercial".

Es importante trazar la línea de qué tipo de cosas vas a tratar de filtrar antes de continuar tratando de diseñar tu algoritmo. Creo que la línea debe dibujarse en el nivel donde "gmail.com" se considera una url, pero "gmail.com" no. De lo contrario, es probable que obtenga falsos positivos cada vez que alguien no capitalice la primera letra de una oración.


Considere incorporar la API OWASP AntiSAMY ...


Dado que principalmente está buscando invitaciones para copiar y pegar en la barra de direcciones de un navegador, vale la pena echarle un vistazo al código utilizado en los navegadores de código abierto (como Chrome o Mozilla) para decidir si el texto ingresó en la "barra de direcciones". equivalente "es una consulta de búsqueda o un intento de navegación URL.


Estoy concentrando mi respuesta en tratar de evitar los spammers. Esto lleva a dos suposiciones: las personas que usan el sistema intentarán activamente contravenir su verificación y su objetivo es detectar la presencia de una URL, no extraer la URL completa. Esta solución se vería diferente si tu objetivo es otra cosa.

Creo que tu mejor opción será con el TLD. Existen los ccTLD de dos letras y la lista comparativamente pequeña (actualmente) de otros. Estos deben tener el prefijo por un punto y el sufijo por una barra o un límite de palabra. Como otros han notado, esto no va a ser perfecto. No hay forma de obtener "buyfunkypharmaceuticals. It" sin rechazar el legítimo "Lo intenté de nuevo. No funciona" o algo similar. Dicho todo eso, esta sería mi sugerencia:

[^/b]/.([a-zA-Z]{2}|aero|asia|biz|cat|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|net|org|pro|tel|travel)[/b/]

Cosas que esto obtendrá:

Por supuesto, se interrumpirá tan pronto como las personas empiecen a ofuscar sus URL, reemplazando a "." con "punto". Pero asumiendo nuevamente que los spammers son su objetivo aquí, si comienzan a hacer ese tipo de cosas, sus tasas de clics descenderán otro par de órdenes de magnitud hacia cero. El grupo de personas lo suficientemente informado como para desofuscar una URL y el grupo de personas no suficientemente informadas para visitar sitios de spam tienen, creo, una intersección minúscula. Esta solución debería permitirle detectar todas las URL que son copiables y pegadas a la barra de direcciones, mientras mantiene el daño colateral al mínimo.


Me gusta la respuesta de capar hasta ahora, pero lidiar con las fuentes Unicode puede ser un poco complicado, con los navegadores más antiguos a menudo mostrando algo curioso o una pequeña caja ... y la ubicación del U + 05B4 es un poco extraña. .. para mí, aparece fuera de las tuberías aquí | ִ | a pesar de que está entre ellos.

Hay una práctica y middot; (·) Sin embargo, que rompe corta y pega de la misma manera. Su alineación vertical se puede corregir <sub> ing, por ejemplo:

· com

Perverso, pero eficaz en FF3 de todos modos, no se puede cortar y pegar como una URL. El <sub> es bastante bueno, ya que es visualmente obvio por qué no se puede pegar la URL.

Los puntos que no se encuentran en las URL sospechosas se pueden dejar solos, por lo que, por ejemplo, podría hacer

s//b/./b/<sub>&middot;<//sub>/g

Otra opción es insertar algún tipo de entidad de ancho cero al lado de los puntos sospechosos, pero cosas como & zwj; y & zwnj; y & zwsp; no parece funcionar en FF3.


Necesitaba solo la detección de URL http simples con el protocolo / out, suponiendo que se proporciona el protocolo o un prefijo ''www''. El enlace mencionado above me pareció bastante útil, pero al final salí con esto:

http(s?)://(/S+/.)+/S+|www/d?/.(/S+/.)+/S+

Obviamente, esto no prueba el cumplimiento del estándar dns.


No estoy seguro de si la detección de URL con una expresión regular es la forma correcta de resolver este problema. Por lo general, se perderá algún tipo de caso marginal oscuro que los spammers podrán explotar si están lo suficientemente motivados.

Si su objetivo es solo filtrar el spam de los comentarios, entonces quizás quiera pensar en Bayesian filtrado Bayesian . Ha demostrado ser muy preciso al marcar el correo electrónico como spam, también podría hacer lo mismo por usted, dependiendo del volumen de texto que necesita filtrar.


Por supuesto, usted se da cuenta de que si los spammers deciden usar tinuyrl o dichos servicios para acortar sus URL, su problema empeorará. Es posible que deba escribir un código para buscar las URL reales en ese caso, utilizando un servicio como decodificador TinyURL


Sé que esto no ayuda con el texto de enlace automático, pero ¿qué ocurre si busca y reemplaza todos los períodos de parada completa con un personaje que se parece a lo mismo, como el carácter unicode para el punto hebreo hiriq (U + 05B4)?

El siguiente párrafo es un ejemplo:

Esto podría funcionar ִ El período parece un poco extraño, pero todavía es legible ִ El beneficio, por supuesto, es que cualquier persona que copie y pegue www ִ google ִ com no llegará demasiado lejos ִ :)


Tras hacer varios intentos para escribir esta pieza exacta de código, puedo decir inequívocamente que no podrá hacerlo con absoluta fiabilidad, y ciertamente no podrá detectar todos los formularios URI permitidos por el RFC. Afortunadamente, dado que tiene un conjunto muy limitado de URL que le interesan, puede usar cualquiera de las técnicas anteriores.

Sin embargo, otra cosa que puedo decir con mucha certeza es que si realmente quieres vencer a los spammers, la mejor manera de hacerlo es usar JavaScript. Envíe un fragmento de JavaScript que realice algunos cálculos y repita el cálculo en el lado del servidor. El JavaScript debe copiar el resultado del cálculo en un campo oculto para que, cuando se envíe el comentario, también se envíe el resultado del cálculo. Verifique en el servidor que el cálculo es correcto. La única forma de evitar esta técnica es que los spammers ingresen comentarios manualmente o que comiencen a ejecutar un motor de JavaScript solo para usted. Utilicé esta técnica para reducir el spam en mi sitio de 100 + / día a uno o dos por año. Ahora, el único correo basura que recibo es ingresado por humanos manualmente. Es extraño recibir spam por temas.



Ya hay algunas buenas respuestas aquí, así que no publicaré más. Aunque voy a dar un par de cosas. En primer lugar, asegúrese de probar los protocolos conocidos , cualquier otra cosa puede ser malo. Como alguien cuyo pasatiempo tiene que ver con los enlaces de telnet, es probable que desee incluir más de http (s) en su búsqueda, pero puede querer evitar decir apuntar: u otras URL. Segundo, es que muchas personas delimitarán sus enlaces en corchetes angulares (gt / lt) como < http://theroughnecks.net > o en parens "(url)" y no hay nada peor que hacer clic en un enlace y tener el cierre > o) ir junto con el resto de la url.

PD, lo siento por los enchufes que se autoreferencian;)


Ping la posible URL

Si no te importa un pequeño cómputo del lado del servidor, ¿qué tal algo como esto?

urls = [] for possible_url in extracted_urls(comment): if pingable(possible_url): urls.append(url) #you could do this as a list comprehension, but OP may not know python

Aquí:

  1. extraído_ruedas toma un comentario y usa una expresión regular conservadora para sacar posibles candidatos

  2. pingable en realidad usa una llamada al sistema para determinar si el nombre de host existe en la web. Podría tener un envoltorio simple para analizar la salida de ping.

    [ramanujan: ~ / base] $ ping -c 1 www.google.com

    PING www.l.google.com (74.125.19.147): 56 bytes de datos 64 bytes de 74.125.19.147: icmp_seq = 0 ttl = 246 tiempo = 18.317 ms

    --- www.l.google.com estadísticas de ping --- 1 paquete transmitido, 1 paquete recibido, 0% de pérdida de paquete ida y vuelta min / avg / max / stddev = 18.317 / 18.317 / 18.317 / 0.000 ms

    [ramanujan: ~ / base] $ ping -c 1 fooalksdflajkd.com

    ping: no se puede resolver fooalksdflajkd.com: host desconocido

La desventaja es que si el host da un 404, no lo detectará, pero este es un primer corte bastante bueno: la mejor forma de verificar que una dirección es un sitio web es intentar navegar hasta él. También podría intentar obtener esa URL, pero eso es más pesado.