Insecurely generated token - OTP - Scala
Need
Secure generation and transmission of OTP tokens
Context
- Usage of Scala for building scalable and high-performance applications
- Usage of play.api.mvc for handling HTTP requests and responses in Play Framework
- Usage of play.api.libs.json for JSON parsing and manipulation in Play Framework
Description
Insecure Code Example
import play.api.mvc._
import play.api.libs.json._
class Application extends Controller {
def generateOTP = Action { request =>
val json = request.body.asJson.get
val phoneNumber = (json \\ "phoneNumber").as[String]
val otp = generateClientSideOTP(phoneNumber)
Ok(Json.obj("status" -> "success", "OTP" -> otp))
}
def generateClientSideOTP(phoneNumber: String): String = {
// OTP generation logic here
val otp = phoneNumber.take(4) // This is a simple and insecure OTP generation logic for demonstration purposes
otp
}
}
The above code represents a Scala backend application using the Play framework that generates an OTP client-side and sends it to the server. This approach is insecure because the OTP is generated on the client-side, making it susceptible to interception by an attacker. The `generateOTP` function is an action that extracts the phone number from the request body and passes it to the `generateClientSideOTP` function to generate the OTP. The OTP is then sent back to the client in the response. The `generateClientSideOTP` function generates the OTP based on the phone number. In this case, it simply takes the first 4 characters of the phone number as the OTP. This is a very simplistic and insecure method of generating an OTP, and it's used here only for demonstration purposes. The vulnerability here is that an attacker can intercept the request and gain access to the OTP. Since the OTP is generated on the client-side and sent to the server, the attacker doesn't need access to the phone number used. They only need to intercept the request to access the OTP and continue the application flow.
Steps
- Move the OTP generation logic to the server-side
- Generate a cryptographically secure random OTP
- Use a secure method to transmit the OTP to the client-side
- Implement proper validation and expiration for the OTP
Secure Code Example
import play.api.mvc._
import play.api.libs.json._
import java.security.SecureRandom
class Application extends Controller {
def generateOTP = Action { request =>
val json = request.body.asJson.get
val phoneNumber = (json \\ "phoneNumber").as[String]
val otp = generateServerSideOTP()
// Send OTP to the client side securely, e.g., via SMS
Ok(Json.obj("status" -> "success"))
}
def generateServerSideOTP(): String = {
val random = new SecureRandom()
val otp = new Array[Byte](4)
random.nextBytes(otp)
otp.map("%02x".format(_)).mkString
}
}
The OTP generation logic has been moved to the server-side. The `generateServerSideOTP` function generates a cryptographically secure random OTP using the `SecureRandom` class. The OTP is then converted to a hexadecimal string. The OTP is no longer sent in the response to the client. Instead, it should be sent to the client-side securely, for example, via SMS. This is not shown in the code as it depends on the specific SMS gateway used. The client-side should then send the OTP back to the server for validation. The server should implement proper validation and expiration for the OTP. This is not shown in the code as it depends on the specific requirements and infrastructure of the application.
References
Last updated
2023/09/18