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

JavaScript Processing Multiple Input Values to Produce an Output

Hello, I am working on creating a stamp script that will allow users to enter their name and address into three fields. Later, these fields will be displayed in the stamp edition. Currently, I have set up 3 input fields where users can input their data. He ...

Oops! Looks like the 'opennebula' module is missing in your Meteor.JS project

I've attempted using meteorhacks:npm but encountered the same issues. While working on a Meteor.JS application with iron:router installed, I'm facing difficulties loading the NPM module "opennebula" (found at https://github.com/OpenNebula/addon- ...

Cannot retrieve JSON values in Filestack v3

I am currently working with Filestack (Filepicker) V3 to upload multiple files and retrieve filename, url, and mimetype. Based on the Filestack documentation for this latest release and a previous question that was asked here, I have implemented the follow ...

What is the best way to toggle the visibility of fields on a modal in a Ruby on Rails

I am working on an application that utilizes Rails 4.1 and Ruby 2.1.2. The show.html.erb view for the Assignment Model in this application is as follows: <h1><%= "#{'Source URL'}"%> <div class="source-url"><%= @assignment.so ...

Implement admin-on-rest framework within my current project

Currently, I am in the process of building an admin-tool website using Material UI. To handle asynchronous calls, I have integrated Redux Saga into my project for calling services. The Admin on Rest framework offers some beneficial components like the Data ...

Exclude a variety of keys using wildcards or regex when conducting comparisons

How can I exclude certain properties in a JSON object that contain specific characters? var obj1 = {name: "James", age: 17, creation: "13-02-2016", deletion: "13-04-2016", foo_x:"", foo_y:"", foo_z:""} var obj2 = {name: "Maria", age: 17, creation: "13-02- ...

Scrolling presentation with dynamic animations

Does anyone have any suggestions for creating a scrolling effect similar to the one on this website? I want to implement a scroll effect where each presentation page is revealed one by one when the user scrolls using their mouse wheel, encouraging them to ...

Ways to eliminate a value once a checkbox is deselected

I am currently developing a search box that includes three separate fields which will be populated with data using AJAX based on the user's selection. Here is the HTML structure I have implemented: <div id="states"> <input type="checkbo ...

Ending a timed function in AngularJS 1

As part of my Angular JS 1 learning journey, I am working on a small test involving text areas that display text using Angular functions when a user enters and exits them. The enter function has a 3-second delay, while the exit function waits for 5 seconds ...

Managing websites on Android when the keyboard is displayed

I am currently facing an issue with my webpage on Android (Galaxy SIII). The problem occurs when visitors try to enter their email in the form at the bottom of the page. The keyboard becomes visible, causing the design to look messy. When using Chrome, the ...

What is the process for retrieving the value of `submit.preloader_id = "div#some-id";` within the `beforesend` function of an ajax call?

In my JavaScript code, I have the following written: var formSubmit = { preloaderId: "", send:function (formId) { var url = $(formId).attr("action"); $.ajax({ type: "POST", url: url, data: $(formId).serialize(), dataTy ...

An issue arises in the NodeJS Express authentication process when attempting to set headers after they have already been sent,

Currently, I am working on developing a basic authentication system using the POST method. app.post("/api/auth",function(req,resp) { var username = req.body.username||req.param('username'); var password = req.body.password||req.param(&a ...

Routes are no longer being qualified by Express once a subdomain is incorporated

We had developed a compact app that was working flawlessly, but then we were tasked with transforming it into something accessible for others in our organization to utilize... and that led to everything breaking down. Our initial setup included a simple ex ...

Having difficulty with printing a particular div

I need help with printing a specific div containing checkboxes using jQuery. The checkboxes are initially checked based on data from a database, but when I try to print the div, the checkboxes remain unchecked in the print view. Below is the code snippet ...

The render() method of the component is failing to execute even after the mobx store value has been updated

After successfully updating the store before fetching data from the server, everything seems to be working fine. However, once the data is fetched and the store is updated again, the render() method does not get called. Check out this code snippet @acti ...

I am working with Vue.js 2.0 and attempting to send an event from a `child component`

I've been working with Vue.js 2.0 and I'm facing an issue trying to emit an event from a child component to the parent component, but unfortunately, it's not functioning as expected. Here is a glimpse of my code: child component: <temp ...

What is the method for automatically verifying elements within nested ng-repeats?

My div contains ng-repeat elements that are interconnected. Each ng-repeat element has checkboxes, and I want to automatically check the related elements in other ng-repeats when a top ng-repeat element is checked. Here is the actual representation of the ...

JavaScript watermark with alternating/dual mode

In the following code snippet, I have implemented a function to make window.status switch between displaying "a" and "b." function alternateViaIntrvl() { setInterval('alterStatus()', 500); } var altrCounter = 0; function alerted() { var ...

Enhance your user interface by incorporating badges into specific elements using Bootstrap version 5.2

I am currently using the most recent version of Bootstrap v5.2 and Vue 3 (for learning purposes). While searching on Stackoverflow, I came across a similar question, but it was related to an older Bootstrap version. In my project, I have a select element ...

Enhance Your Website with Interactive Tooltips Using Twitter Bootstrap

In Twitter bootstrap, the default trigger for tooltips is hover. If I want to make the tooltip display on focus instead, I can add data-trigger="focus". But how do I make it so the tooltip displays both on hover and on focus? ...