How to identify that uploaded image is malicious (using SailsJS and Skipper)?

174 views Asked by At

I faced an interesting question about uploading images at the SailsJS application. I want to upload images from the frontend side to the backend side (NodeJs, SailsJS), validate the image (images), to be sure that images are doesn't include malicious data (like hidden scripts inside image content), and then send this images to AWS storage (S3 bucket)).

On the front end side, everything is done in accordance with SailsJS requirements (text fields are on the top of the form, file on the bottom).

Tools for upload:

For images upload, I use skipper (skipper-better-S3) which is a built-in module in SailsJS. Skipper extends the HTTP body parser used in Sails and Express.

To implement this, I use the code mentioned below:

    Vault.read((err, result) => {
      if (err) {
        console.log('Vault S3 Error', err);
      } else {
        request.file('logo').upload({
          adapter: require('skipper-better-s3'),
          key: result.access_key,
          secret: result.secret_key,
          bucket: sails.config.s3.bucket,
          maxBytes: sails.config.globals.multipleMaxLogoSize,
          dirname: `some-directory/${client.id}/logo`,
          s3config: {
            signatureVersion: 'v4',
            sslEnabled: true,
            sessionToken: result.security_token
          },
          s3params: {
            ACL: 'private',
            SSEKMSKeyId: process.env.AWS_S3_KMS_KEY_ARN,
            ServerSideEncryption: 'aws:kms',
          }
        }, (error, uploadedFiles) => {
          if (uploadedFiles.length === 0 ? true : Utility.isValidImage(uploadedFiles[0].filename)) {
            if (error) {
              sails.log.error(error);
              return response.serverError();
            }

            if (uploadedFiles.length > 0) {
              uploadedFiles.forEach(uploadedFile => { client.logo = `/logo/${client.id}/${uploadedFile[0].fd.split('/').pop()}`;
              client.displayName = request.body.displayName ? request.body.displayName : client.displayName;
              client.save().then(() => {
                return response.ok({});
              }, (error) => {
                sails.log.error(error);
                return response.serverError(error);
              }
            )})
          } else if (conditionForBadRequest) {
              return response.badRequest();
            }
          } else {
            sails.log.error('Invalid Image Type');
            return response.badRequest('Invalid Image Type');
          }
    });
  }
})
        

This code snippet can check if the image has the correct extension (ending), but it doesn't allow us to check if the image includes malicious scripts (Cross-Site Scripting, Persistent XSS).

Based on the mentioned above I have two questions:

  1. How it is possible to check if the uploaded image (it content) includes malicious scripts as we know that image content can be intercepted with the help of some tools (Burp Suite)?

  2. What is the best place for the validation of the image? Maybe it's better to do at saveAs property of request.file('logo').upload() function?

Any help appreciated.

0

There are 0 answers