Tips for safeguarding AJAX or javascript-based web applications

Utilizing AJAX, this function retrieves information about an image in the database with the ID of 219 when a button is clicked.

Any visitor to this webpage has the ability to alter the JavaScript code by inspecting the source code. By modifying the code and then clicking the button, they can execute the changed code (such as altering image_id from 219 to 300) to retrieve information about any image simply by changing the image_id.

The crucial question is how do we prevent such client-side attacks or XSS?

function clicked () {
    var xhttp = new XMLHttpRequest () ;

    xhttp.onreadystatechange = function () {
        if (this.readyState == 4 && this.status == 200){
            var obj = JSON.parse (this.responseText);
            alert (obj.description);
        }
    };

    xhttp.open ("POST","get_title_description.php", true);
    xhttp.setRequestHeader ("Content-type", "application/x-www-form-urlencoded");
    xhttp.send ("image_id=219") ;
}

Answer №1

To generate and validate a cookie, you can utilize the following code snippet:

define('COOKIE_TOKEN', 'my_token');

class BaseAuth
{
  protected $uid;

  private static function base64url_encode(string $s): string
  {
    return strtr($s,'+/=','-|_');
  }

  private static function base64url_decode(string $s): string
  {
    return strtr($s,'-|_','+/=');
  }

  // Ensuring encrypted characters are URL-safe by encoding after encryption
  protected function token_encode(String $string): string
  {
    $iv_size = openssl_cipher_iv_length(TYPE_CRYPT);
    $iv = openssl_random_pseudo_bytes($iv_size);

    $encrypted_string = @openssl_encrypt($string, TYPE_CRYPT, SALT, 0, $iv);

    // Need IV for decoding, so return IV + encrypted string
    return self::base64url_encode($encrypted_string).'!'.self::base64url_encode(base64_encode($iv));
  }

  // Decoding from URL-safe before decryption
  protected function token_decode(String $string): string
  {
    list($encrypted_string, $iv) = explode('!', $string);
    $string = @openssl_decrypt(self::base64url_decode($encrypted_string), TYPE_CRYPT, SALT, 0, base64_decode(self::base64url_decode($iv)));
    return $string;
  }

  // Logging out the user
  public function clear_cookie()
  {
    setcookie(COOKIE_TOKEN, '', time() - 300, '/api', '', FALSE, TRUE); // non-secure; HTTP-only
  }

  private function userIP(): string
  {
    return $_SERVER['REMOTE_ADDR'];
  }

  // Validating login token
  public function authorized(): bool
  {
    if(isset($_COOKIE[COOKIE_TOKEN]))
    {
      $stamp = time();
      $text = $this->token_decode($_COOKIE[COOKIE_TOKEN]);
      if($text != '')
      {
        $json = json_decode($text,TRUE);
        if(json_last_error() == JSON_ERROR_NONE)
        {
          if($json['at'] <= $stamp AND $json['exp'] > $stamp AND $json['ip'] == $this->userIP() AND $json['id'] != 0)
          {
            $res = $db->query("SELECT id,active,last_update,last_update > '".$json['last']."'::timestamptz AS expired FROM account WHERE id = ".$json['id']);
            $info = $db->fetch_assoc($res);
            if($info['active'] != 0)
            {
              if($info['expired'] == 0)
              {
                $this->sendToken($info);
                $this->uid = $json['id'];
                return TRUE;
              }
            }
          }
        }
      }
      $this->clear_cookie();
    }
    return FALSE;
  }

  public function login(String $username, String $password): bool
  {
    $stm = $db-prepare("SELECT id,user_name AS username,user_pass,full_name,active,last_update,COALESCE(blocked_until,NOW()) > NOW() AS blocked 
      FROM account WHERE user_name = :user");
    $res = $stm->execute(array('user' => strtolower($json['username'])));
    if($res->rowCount())
    {
      $info = $db->fetch_assoc($res);
      if($info['active'] == 0)
      {
        return FALSE;
      }
      elseif($info['blocked'] != 0)
      {
        $db->query("UPDATE account SET blocked_until = NOW() + INTERVAL 5 minute WHERE id = ".$info['id']);
        return FALSE;
      }
      elseif(!password_verify($password, $info['user_pass']))
      {
        $db->query("UPDATE account SET blocked_until = NOW() + INTERVAL 5 minute WHERE id = ".$info['id']);
        return FALSE;
      }
      else
      {
        unset($info['user_pass']);
        unset($info['blocked']);
        $this->sendToken($info);
        return TRUE;
      }
    }
  }
}

If authentication and authorization are not required, and you just need unpredictable image IDs, UUIDs can be used.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Instead of loading JSON contents using jQuery AJAX at page load, consider loading it dynamically while typing in the search box

It's odd that there is an XHR request for search results as soon as my page loads. Even though it's hidden from the user, a substantial amount of json data is being loaded. Take a look at my code: $.ajax({ type: "POST", url: "http://localho ...

Sending JSON array data via Ajax POST method to a C# API

I am encountering an issue where I want to send an array in a JSON string to an API and then handle the data. Despite my efforts in creating a class and attempting to map it, I am receiving it as null The AJAX call portion that I am working with is as fol ...

Require help with personalizing a jQuery horizontal menu

I recently downloaded this amazing menu for my first website project By clicking the download source link, you can access the code Now, I need your kind help with two issues: Issue 1: The menu seems to be getting hidden under other elements on the page ...

$_SESSION[] Remains Unset

I have encountered an issue with my login system. Whenever I send a request via AJAX connection, the session is failing to set. Here is the code for sending the connection: function onSubmit(form){ var username = form.username.value; var password ...

Show information on the following screen by utilizing ajax when the button is pressed

I need to implement functionality on my cshtml page, ListZoneRecords.cshtml, where clicking on a zone row should display its details on another page. I am looking to achieve this using ajax. //ListZoneRecords.cshtml <script> $('#btn_sbmt_details ...

Error: Attempting to access the 'clipboard' property on an undefined object results in a TypeError when invoking this.$q.electron.clipboard

I'm currently working on incorporating copy to clipboard functionality into my app using Electron. This is the command I am using: methods: { copyToClipboard () { if (process.env.MODE === 'electron') { this.$q.electro ...

Achieving nested routes without the need for nested templates

My Ember routes are structured like this: App.Router.map(function() { this.resource("subreddit", { path: "/r/:subreddit_id" }, function() { this.resource('link', { path: '/:link_id'} ); }); }); However, ...

Is it possible to dynamically insert a ng-mouseover in AngularJS using Javascript?

It seems like there is an issue with this code: var run_div = document.createElement('div'); run_div.className = 'whatever'; run_div.textContent = 'whatever'; run_div.setAttribute('ng-mouseover', 'console.log(&b ...

It appears that the ngRepeatWatch feature is causing a slowdown in Batarang

After reviewing the Batarang analysis of my AngularJS app, I have discovered the following: ngRepeatWatch | 64.2% | 136.0ms Surprisingly, this instruction takes up 10 times more time than the next reported instructions. Could this indicate that I am pot ...

Failure to display updated property value

After rendering an array of objects, I am attempting to add a new property using a function. However, the new property value is not displaying on the page even though it is present when I log the object in the console. The new property that I want to add ...

Error: Uncaught promise rejection - The function is undefined in the context of Vue.js and Electron

I've been experimenting with anime.js to animate elements using promise functions. However, I'm encountering an issue where the second function does not run after the previous one successfully completes. <script> import Splash from '. ...

Navigating within a class-based component using Next.js: A brief guide

Is it possible to create a redirect from within an onSubmit call while maintaining CampaignNew as a class-based component? I have provided the code snippet below, and I am looking for guidance on achieving this. import React, { Component } from "rea ...

Using HTML and JavaScript, we can set two different color values - one for the background and one for the h1 title

I am trying to save two values, one for the h1 tag and one for the body background. I want the user to select color 1 and color 2. When I press the third button, all changes should be applied and the colors should change. I have attempted this but with no ...

Can you explain the distinction between $scope.$root and $rootScope?

When looking at controllers, I noticed that $scope includes $root. Can you explain what $root is and how it differs from the $rootScope that can be injected into the controller? ...

Tips for updating multiple fields in Prisma ORM

Is there a way to upsert multiple fields in Prisma ORM using just one query? I'm looking for a solution that allows me to upsert all fields at once, without having to do it individually. Is this possible? ...

Using Local Storage to store arrays in JavaScript/jQuery

Currently, I am implementing a set of multiple buttons each containing data-id and data-name Below is my concept along with some sample code for reference: $(".clickCompare").click(function ({ var id = $(this).attr('data-id'); var ...

What led the Typescript Team to decide against making === the default option?

Given that Typescript is known for its type safety, it can seem odd that the == operator still exists. Is there a specific rationale behind this decision? ...

Is it possible to update the version of NPM?

Having an issue with installing packages for my React-Native project due to a NPM version error. How can I upgrade it? Currently using version 4 ...

What is the significance of the "component" prop within MUI components?

I am a beginner in React and HTML. Currently, I am using MUI and React to create my own website. I am currently attempting to add an "Upload button" that will allow me to select an image file when clicked. Below is the official implementation: <Button ...

Objects remaining static

I'm currently working on a VueJS component that has the ability to export data into .xlsx format. To achieve this functionality, I am utilizing the json2xls library, which requires an array of objects with identical keys (representing column names) to ...