MEDIUM clickjackingsailsdynamodb

Clickjacking in Sails with Dynamodb

Clickjacking in Sails with Dynamodb — how this specific combination creates or exposes the vulnerability

Clickjacking is a client-side interface manipulation attack where an attacker tricks a user into clicking or interacting with a hidden or disguised UI element. In a Sails application that uses Dynamodb as its primary data store, the risk emerges from a mismatch between rendering behavior and data access controls. Sails, an MVC web framework for Node.js, often renders views that embed data retrieved from Dynamodb via Waterline ORM-like adapters. If those views do not enforce appropriate UI-level protections, an attacker can embed the application’s own pages inside an <iframe> and overlay invisible controls, causing unintended actions when the authenticated user interacts with the page.

Specifically, when Sails serves pages that perform state-changing operations (such as updating a user’s email or initiating a payment) via POST requests, and those pages are rendered without anti-clickjacking defenses, an attacker can craft a malicious page that loads the Sails view inside a transparent iframe. Because the request originates from a user with valid Dynamodb-stored session credentials, the server processes the request as legitimate. Dynamodb itself does not enforce UI protections; it only stores and retrieves data. Therefore, if Sails does not set appropriate response headers or enforce frame-busting techniques, the application remains vulnerable even though Dynamodb access controls are correctly configured.

The exposure is compounded when Sails endpoints return JSON that is consumed directly by client-side templates without additional context checks. An attacker can use social engineering to lure a victim to a page that loads the vulnerable Sails view, leveraging the trust the user has in the domain. Because the request includes valid session cookies or tokens stored by the browser, the server-side logic that reads from and writes to Dynamodb executes without recognizing that the UI context is hostile. This means the vulnerability is not in Dynamodb’s access patterns but in how Sails presents and protects the UI that triggers data operations.

Dynamodb-Specific Remediation in Sails — concrete code fixes

Remediation focuses on preventing the Sails application from being embedded in an external context and ensuring that state-changing operations verify the request origin and intent. Below are concrete steps and code examples tailored for a Sails app using Dynamodb.

  • Set X-Frame-Options header in Sails responses. In config/http.js, add middleware to prevent framing:
// config/http.js
module.exports.http = {
  middleware: {
    order: ['startRequestTimer', 'cookieParser', 'session', 'myClickjackingProtection', 'bodyParser', 'handleBodyParserError', 'compress', 'methodOverride', 'poweredBy', '$custom', 'www', 'favicon', '404', '500'],
    myClickjackingProtection: function (req, res, next) {
      res.set('X-Frame-Options', 'DENY');
      return next();
    }
  }
};
  • Use Content-Security-Policy frame-ancestors directive for modern browsers. In the same middleware, add:
    myClickjackingProtection: function (req, res, next) {
      res.set('X-Frame-Options', 'DENY');
      res.set('Content-Security-Policy', "frame-ancestors 'none';");
      return next();
    }
  • Implement frame-busting JavaScript in views that must be embedded in trusted contexts. In your EJS or Pug view file:
<script>
  if (window.self !== window.top) {
    window.top.location = window.self.location;
  }
</script>
  • Validate the origin of state-changing requests on the server. Even though Dynamodb does not enforce UI-layer checks, Sails controllers should verify the request’s referer or use anti-CSRF tokens:
// api/controllers/UserController.js
module.exports.updateEmail = async function (req, res) {
  const referer = req.headers.referer;
  const allowedOrigin = 'https://yourdomain.com';
  if (!referer || !referer.startsWith(allowedOrigin)) {
    return res.status(403).json({ error: 'Invalid request origin' });
  }
  const email = req.body.email;
  const dynamodb = new (require('aws-sdk')).DynamoDB.DocumentClient();
  const params = {
    TableName: 'users',
    Key: { userId: req.session.userId },
    UpdateExpression: 'set email = :val',
    ExpressionAttributeValues: { ':val': email },
    ReturnValues: 'UPDATED_NEW'
  };
  try {
    const data = await dynamodb.update(params).promise();
    return res.ok(data);
  } catch (err) {
    return res.serverError(err);
  }
};
  • Ensure that sensitive actions require re-authentication or multi-step confirmation. For high-risk operations, prompt the user again before executing DynamoDB writes, reducing the impact of a successful clickjacking attempt.

Frequently Asked Questions

Does Dynamodb enforce any UI-level protections against clickjacking?
No. Dynamodb is a database service and does not enforce UI or framing policies. Protection must be implemented at the application layer in Sails.
Are X-Frame-Options and CSP frame-ancestors sufficient on their own?
They significantly reduce risk but should be combined with server-side origin validation and secure session management to prevent clickjacking in Sails applications using Dynamodb.