0

J'ai développé une application de messagerie instantanée utilisant le Facebook Messenger platform. J'ai utilisé Spring Boot avec Tomcat intégré pour la plate-forme Web. L'application devrait fonctionner sur Amazon aws, ouverte sur le WWW, et être utilisée comme un webhook pour recevoir des rappels de Messenger sur https.Meilleure pratique pour le déploiement de l'application de démarrage de démarrage sur Amazon

J'ai besoin d'un conseil pour sécuriser l'application, donc il ne sera pas piraté ou inondé de demandes qui ne viennent pas de Facebook.

Je pensais que l'application nécessitait une connexion sécurisée (ssl), mais l'utilisation de "security.require_ssl = true" dans application.properties n'a pas fonctionné. Peut-être que je ne sais pas quelle est la signification de cela et comment le configurer proprement. Existe-t-il une meilleure pratique pour bloquer les demandes qui ne sont pas des demandes https? Ou un moyen de bloquer les demandes qui sortent de Messenger au niveau de l'application?

Merci beaucoup!

EDIT

En attendant, je bloqué les demandes d'autres adresses IP dans la couche d'application à l'aide de l'intercepteur de gestionnaire:

@Configuration 
public class MyWebApplicationInitializer implements WebApplicationInitializer, WebMvcConfigurer{ 


    @Override 
    public void addInterceptors(InterceptorRegistry registry) { 
     registry.addInterceptor(new HandlerInterceptor() { 

      @Override 
      public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 
        throws Exception { 
       if (! (request.getRemoteAddr().equals("173.252.88.66") || request.getRemoteAddr().equals("127.0.0.1")|| request.getRemoteAddr().equals("0:0:0:0:0:0:0:1"))){ 
        logger.warn("Request is not coming from authorized remote address: " + request.getRemoteAddr()+". Rejecting"); 
        response.getWriter().write("Unauthorized Address"); 
        response.setStatus(401); 
        return false; 
       } else { 
        return true; 
       } 
      } 

} 
+0

De facebook documentation de référence, je vois qu'il ya une possibilité de mettre un jeton de rappel (https://developers.facebook.com/docs/messenger-platform/webhook-reference), en avez-vous configuré un? le recevez-vous du côté de l'application du ressort (comme un chemin ou un paramètre)? –

+0

@GuyBouallet Le jeton est pour une première vérification. Les rappels en cours ne contiennent aucun jeton. Avez-vous vu quelque chose que j'ai raté? –

+1

Avez-vous vérifié s'il existe un en-tête http appelé X-Hub-Signature dans les requêtes reçues par tomcat? –

Répondre

1

Vous devez vérifier l'en-tête HTTP X-Hub-signature disponible dans les demandes envoyées par Facebook à votre URL de webhook.

Dans votre cas, vous pouvez définir un filtre ou un intercepteur pour la vérification de la signature. Vous pouvez également le faire dans votre contrôleur comme dans l'exemple que j'ai trouvé dans RealTimeUpdateController.java du projet social du printemps.

private boolean verifySignature(String payload, String signature) throws Exception { 

     if (!signature.startsWith("sha1=")) { 

      return false; 

     } 

     String expected = signature.substring(5);  

     Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM); 

     SecretKeySpec signingKey = new SecretKeySpec(applicationSecret.getBytes(), HMAC_SHA1_ALGORITHM); 

     mac.init(signingKey); 

     byte[] rawHmac = mac.doFinal(payload.getBytes()); 

     String actual = new String(Hex.encode(rawHmac)); 

     return expected.equals(actual); 

    } 
1

beaucoup à dire alors je suis sûr que je vais manquer quelques points.

  • La définition de SSL est une bonne chose, mais assurez-vous d'obtenir un certificat. lets encrypt est une bonne chose si vous ne voulez pas payer pour le certificat SSL.

    seulement seeing aws offre une alternative à letsencrypt

  • Security Group Vous pouvez voir Groupe de sécurité comme quelque chose de semblable à un pare-feu de sorte que vous pouvez contrôler le port est ouvert, les flux internes et externes.

  • Regardez IAM qui contrôle qui et comment peuvent accéder à votre compte AWS

  • évidente: changer votre mot de passe. ne laissez pas le mot de passe par défaut pour l'installation que vous pouvez faire sur l'instance

lu certains des https://aws.amazon.com/security/security-resources/ pour obtenir plus d'informations sur ce que vous pouvez faire

il ne sera pas piraté ou inondé de demandes

désolé de le dire, mais très probablement il sera - il n'a pas besoin d'être un hacker avancé pour exécuter scanner et scanner IP et vérifier les ports ouverts/connexion brute force etc ...

+0

Votre réponse donne des conseils intéressants, mais elle est axée sur la sécurisation du côté serveur AWS en général. La question implique un client spécifique qui est facebook; La sécurisation de la communication nécessite donc de vérifier quel support facebook (SSL + signature de charge utile). –

1

Grâce à l'aide de Guy Bouallet, j'ai ajouté le contrôle de signature. Je l'ai ajouté dans mon contrôleur et non dans l'intercepteur, pour éviter le problème de How to read data twice in spring qui semble un peu compliqué.

Voici donc est-il:

@RequestMapping(path = "/") 
public void doHandleCallback(@RequestBody String body, @RequestHeader(value = "X-Hub-Signature") String signature) throws IOException { 
    if (!verifyRequestSignature(body.getBytes(), signature)){ 
     logger.error ("Signature mismatch."); 
     throw new MismatchSignatureException(signature); 
    } 
    MessengerCallback callback = mapper.readValue(body, MessengerCallback.class); 
    logger.info("Incoming Callback: " + body); 
    for (EventData entry : callback.getEntry()) { 
     for (ReceivedMessagingObject message : entry.getMessaging()) { 
      if (message.isMessage() || message.isPostback()) { 
       doHandleMessage(message); 
      } 
      else if (message.isDelivery()){ 
       doHandleDelivery(message); 
      } 
     } 
    }  
} 

private boolean verifyRequestSignature(byte[] payload, String signature) { 
    if (!signature.startsWith("sha1=")) 
     return false; 
    String expected = signature.substring(5); 
    System.out.println("Expected signature: " + expected); //for debugging purposes 

    String hashResult = HmacUtils.hmacSha1Hex(APP_SECRET.getBytes(), payload); 
    System.out.println("Calculated signature: " + hashResult); 
    if (hashResult.equals(expected)) { 
     return true; 
    } else { 
     return false; 
    } 

} 

Et ceci est la gestion des exceptions Classe:

@ResponseStatus(value=HttpStatus.BAD_REQUEST, reason="Request Signature mismatch") 
    public class MismatchSignatureException extends RuntimeException { 
    private String signature; 

    public MismatchSignatureException(String signature) { 
     this.signature = signature; 
    } 
    @Override 
    public String getMessage() { 
     return "Signature mismatch: " + signature; 
    } 
+0

Merci pour le partage! –