The TMS website sucks so I made a captcha autofiller

In keep­ing with the spirit of the times, I’ve started play­ing in the Nepali Stock Exchange play­ground. It is a strange, dis­torted world for some­one like me who’s used to the de­ter­min­ism of the com­puter realm. And so far, it has just proved to be a more fash­ion­able way of los­ing money. But it’s ad­dic­tive!

If you’ve ever had to use Nepal Stock Exchange’s Trade Management System (often called just TMS), you prob­a­bly hate it. It is at best an in­com­pe­tently made soft­ware with many glar­ing is­sues, hosted over a woe­fully un­der­pow­ered in­fra­struc­ture that can­not even han­dle the most pre­dictable of traf­fic spikes. On more than one oc­ca­sion I’ve over­sold or un­der­sold shares be­cause it’s UI was out of sync with it’s data­base.

The TMSs lo­gin captcha is the epit­ome of this in­com­pe­tence and neg­li­gence.

If you did­n’t know, a captcha is sup­posed to be a chal­lenge that only hu­mans can solve in a rea­son­able time. A ma­li­cious com­puter pro­gram which, if un­op­posed, could ex­e­cute hun­dreds of thou­sands of re­quests every sec­ond test­ing var­i­ous user­name:pass­word com­bos or se­cu­rity vul­ner­a­bil­i­ties, or just plain over­load­ing the sys­tem so that it be­comes un­re­spon­sive to le­git­i­mate users, is blocked by the captcha.

With that de­f­i­n­i­tion, how­ever, the TMSs captcha” ac­tu­ally turns out to be an anti-captcha, the ex­act op­po­site. It ap­pears as a chal­lenge to the user, who has to man­u­ally type it out every time. But it is com­pletely trans­par­ent to any half-de­cent com­puter script. In fact, when you hit the lo­gin but­ton, the captcha is not even sent to the server. It’s a purely cos­metic ef­fect. It’s like a gate that you have to painstak­ingly un­lock every time, but every bur­glar can pass through it as if it was­n’t even there.

The TMS captcha implementation

Even a cur­sory in­spec­tion will show that the im­ple­men­ta­tion of the TMS captcha sys­tem is not an ac­tual captcha. Any OCR like Google Lens can read it read­ily, mak­ing it very cheap to over­come.

But you don’t have to go that far. The captcha’s ran­dom text is gen­er­ated in the browser by a sim­ple JavaScript code, and it’s laid over an sta­tic im­age. The css user-select prop­erty is set to none so you can’t just copy the text from over the im­age and paste it in the captcha field.

Which means it should be ac­ces­si­ble via the DOM:

Unsurprisingly, it is.

Now, if you can read the text from the DOM, it’s not a big deal to write it back to DOM:

document.getElementById("captchaEnter").value =
  document.getElementById("randomfield").value;

This piece of code will aut­ofill the captcha in­put.

A problem arises

An in­ter­est­ing prob­lem that emerges is that when you aut­ofill the captcha in­put via JavaScript then and hit Login, the web­site still says Incorrect Captcha” even when the captcha is ac­tu­ally cor­rect.

But how could that be? Could the TMSs sys­tem be more well thought out than I expected?

You wish! Turns out, they’re us­ing a fron­tend frame­work (Angular.js). Angular.js internally main­tains a state, with the val­ues of all in­puts. That state gets al­tered only when the cor­re­spond­ing in­put’s input event is fired. Otherwise the value change is not reg­is­tered. But that’s easy to fire. Here:

const $ = (_) => document.getElementById(_);
$("captchaEnter").value = $("randomfield").value;
$("captchaEnter").dispatchEvent(new Event("input")); // Fire the event to trigger angular state change

And with that, the captcha auto-filler works.

Making a chrome extension

Now that I’ve come this far, I might as well make a chrome ex­ten­sion. so that I don’t have to deal with this again. Chrome ex­ten­sions are pretty easy to make. It takes like 10 min­utes to make some­thing this sim­ple. Here’s the rel­e­vant part of the code:

  1. manifest.json
{
  "name": "TMS Captcha Autofiller",
  "description": "This extention will autofill TMS captchas. Made by nirav.com.np",
  "version": "0.5",
  "manifest_version": 3,
  "content_scripts": [
    {
      "matches": ["https://*.nepsetms.com.np/login"],
      "js": ["contentScript.js"]
    }
  ]
}
  1. contentScript.js
{
  const $ = (_) => document.getElementById(_); //aliasing a long fn call
  function l() {
    $("captchaEnter").value = $("randomfield").value;
    $("captchaEnter").dispatchEvent(new Event("input")); // Fire the event to trigger angular state change
  }
  window.onload = l;
}

Done. Put these two files in a folder and im­port it from the chrome ex­ten­sion page (chrome://extensions).

A slightly more dec­o­rated ver­sion is pub­lished in my Github: github.com/​ni­rav­codes/​TM­SCaptchaAut­oFiller.

You can go there and in­stall that ver­sion in­stead.

Update: The ex­ten­sion is now avail­able in Google Extension store. So you can down­load the app from of­fi­cial Google chan­nel. Download Here

Request to the TMS devs

Please change the font in the captcha field from sans serif to a serif one if that’s the least you do. Thousands of peo­ple need­lessly con­fuse capital i and small L every­day.

Update

The web­sites have been fixed and the captcha font has been changed to a leg­i­ble one. Thanks devs. Now go fix the other is­sues.