Security is a very important aspect of software development. However, securing applications can mean different things. For example, security in Kotlin may refer to being able to run your Kotlin application safely in JVM. Or security may be at the Kotlin language API level.
Another highly important level of security to consider as a developer is application security. Application security here refers to security vulnerabilities that exist when hackers take advantage of the code and features on your application to steal data or crash your entire service.
The Kotlin team has a bigger part in the responsibility for fixing security vulnerabilities relating to JVM and the language APIs. And they do this mostly by releasing updates and patches to Kotlin. In addition to that, they may also publish instructions for blocking vulnerabilities.
Application security, on the other hand, requires more effort from you, the developer. Examples of application security vulnerabilities include SQL injection, command injection, and XSS. So, fixing application security issues includes testing and patching a vulnerability like SQL injection,cross-site scripting, command injection, cross-site request forgery, and HTTP strict transport security header.
In this post, we'll learn about security in Kotlin and see different ways to build a more secure Kotlin app. So, let's get started.
Kotlin Security: Strengths and Weaknesses
Is Kotlin a secure language? What are its strengths and weaknesses? We'll answer both questions in this section.
Strengths
Like many modern programming languages, Kotlin strives to be a secure, fast, and user-friendly tool in the hands of developers. The following are some of Kotlin's strengths.
1. Fewer crashes thanks to null safety: At the language API level, Kotlin offersnull safety to reduce crashes in your application due to unexpected data or user input. When used properly, Kotlin's null safety can prevent NullPointerException.
2. Data encryption: Kotlin has good libraries that make it easier for developers to encrypt data. One example of Kotlin data encryption libraries isJetpack Security.
3. Frequent updates: Security is a continuous process. The team at Kotlin is always identifying new vulnerabilities, and they release patches to address any issues that may have been found.
Weaknesses
Some of Kotlin's security weaknesses include:
1. Reverse engineering—It's possible for someone with enough technical knowledge to reverse engineer your Kotlin app, hence, giving them more understanding of the internal working of your app. Also, if you bundle sensitive data like API credentials in your app, they may be exposed too.
2. Internet-driven APIs—Most programs need to connect to the internet for one reason or another. Kotlin has a few built-in tools for powering the internet-driven functionality of apps. Two examples are HttpsURLConnection and WebView. Making HTTP requests via non-SSL protocol can expose sensitive data in transit. Similarly, wrong use of the WebView API such as allowing the execution of any JavaScript code and allowing users to visit any URL via your app can increase security risk.
Features That Increase Kotlin Security
Underneath, Kotlin is just like other programming languages and contains several security features. However, in this section, we'll take a look at two Kotlin-specific features that make Kotlin more secure.
1. Immutability: One way Kotlin improves on Java is by offering keywords for declaring a variable as mutable or immutable. These keywords are val and var. Variables declared with val are immutable, meaning that you cannot reassign a new value to it later in your program.
2. Null safety: Earlier, we mentioned null safety as one of the strengths of Kotlin. This feature helps developers write more secure applications. For example, with null safety, developers are more likely to catch and provide a safe path for code execution in the event of unexpected null values. In other words, this can reduce the occurrence of a NullPointerException.
Kotlin Libraries and Framework
In this section, we'll take a look at some popular Kotlin libraries and frameworks and how they handle security.
1. Ktor
Ktor is a framework for building web applications and microservices using Kotlin. One example of how you can use Ktor is for developing a RESTful API that a mobile or web app can interact with via HTTP requests. In addition, you can render HTML responses directly using Ktor. In that case, you can build a full-stack web application using Ktor.
Ktor is flexible and can integrate with other tools to build complex applications. For example, you can use Ktor with an SQL database to persist data. However, poor implementation of features may leave your Ktor application open to security issues like SQL injection.
2. Spring
Spring is a popular Java framework for building microservices and general web applications. Starting from the fifth version of the Spring project generator, you can generate a new Spring project using Kotlin.
A Spring application may also be vulnerable to SQL injection and XSS attacks, among others.
3. Javalin
Javalin is a lightweight Java and Kotlin framework that offers WebSocket, async requests, and HTTP2 support. One of the strengths of Javalin includes the fact that it's ideal for building RESTful APIs. For example, it has great support for OpenAPI and can be used with tools like Swagger. In addition, Javalin applications run on Jetty, a very popular JVM web server.
Again, Javalin applications that aren't properly optimized may be vulnerable to security issues.
Kotlin Security Libraries
1. Hibernate Validator
Hibernate Validator is a library for Java and Kotlin for validating data like user input. Applications that parse user input without proper validation are more likely to be vulnerable. As a result, attackers take advantage of them to perform attacks like XSS, SQL injection, and other command injection attacks.
Using this validation library, we can reduce the risk of attack to a great extent. The following is an example of how Hibernate Validator works:
Data class
data class UserDto(
@field:Max(value=100)
@Email()
val email: String,
@field:Min(value=8)
val password: String
)
Application class
fun Application.module() {
val userService = UserService()
val validator = Validation.buildDefaultValidatorFactory().validator
routing {
post("/auth/register/") {
val userDto = call.receive<UserDto>()
userDto.validate(validator)
service.process(userDto)
call.respond(HttpStatusCode.OK)
}
}
}
From the example code above, we use the @Email annotation to validate that the value for email is an actual email address. We also verify that the length of the password is greater than eight characters using the @Min annotation.
2. Ktorm
Ktorm is an object-relational mapping (ORM) framework for Kotlin. In simpler terms, it's a tool that makes working with relational databases like SQL easier.
The following example shows SQL queries using Ktorm API:
Data class
object Users : Table<Nothing>("users_tbl") {
val id = int("id").primaryKey()
val email = varchar("email")
val password = varchar("password")
}
Application class
val database = Database.connect("jdbc:mysql://localhost:3306/mydb", user = "root", password = "")
database
.from(Users)
.select(Users.email)
.forEach { row ->
println(row[Users.email])
}
In the example above, we're printing values from users_tbl. Thanks to Ktorm's Kotlin DSL, we didn't have to write any raw SQL queries.
Using an ORM can reduce the risk of SQL injection. However, it's worth mentioning that if you write a lot of raw SQL queries while using an ORM, your application may still be vulnerable. In the next section, we'll look at other practices for increasing the general security of Kotlin.
Kotlin Security Best Practices
A combination of the following practices can reduce security risk in Kotlin.
1. Validateuser input before parsing or outputting them. Failure to do so can expose your application to SQL injections and XSS attacks.
2. Avoid storing API configuration keys in code. Earlier, we mentioned that one of the risks posed by reverse engineering is the exposure of sensitive information like API keys. In order to reduce this type of risk, you should avoid storing API keys as strings in your application. Instead, use environment variables where possible, or use other methods to encrypt keys.
3. Keep tools up to date. Always keep the version of Kotlin your application is using up to date. In addition, if you're using any other third-party libraries and dependencies, you should also keep them up to date.
4. Encrypt data before sending it over a network. If your application sends sensitive data like messages and passwords over the internet, use good encryption methods to encrypt such data before sending them. Doing so can reduce the risk of data being intersected and read in transit.
Common Security Attacks in Kotlin
Some of the most common application security risks in Koltin include the following:
1. SQL Injection
SQL injection is a type of attack where the attacker manipulates SQL queries on a vulnerable website or application.
In order to perform this type of attack, the attacker usually targets features that accept user inputs. For example, the attacker may manipulate the value for an ID in the URL of a web application.
A good method for preventing SQL injection is by validating user input before using them in SQL queries. Another option for preventing SQL injection is the use of PreparedStatement.
2. Cross-site Scripting (XSS)
XSS is a type of security vulnerability that allows users to inject malicious JavaScript code into a website.
An attacker can perform an XSS attack using various methods, including pages that display user inputs. For example, the attacker may submit malicious code using the reply feature on a website that allows users to reply to posts. The malicious code is then executed any time a regular user loads the page containing the reply.
One effective method for preventing XSS attacks is by validating and sanitizing user inputs.
3. Command Injection
Command injection is an injection attack where the attacker injects malicious code into the server. The server or back end then runs this code like the normal application code, thus, granting the attacker access to data and other resources.
This type of attack can be done via user input. The attacker may inject code via a URL query parameter.
A good practice for preventing command injection is avoiding the use of functions that execute commands in our code. In addition to that, sanitization of user input can reduce risk.
4. Cross-Site Request Forgery (CSRF)
CSRF is a type of attack that takes advantage of the trust a website has for authenticated users. In this attack, unauthorized commands are executed on behalf of an authenticated user.
One way attackers carry out this attack is by tricking unsuspecting authenticated users to click manipulated URLs for the target application.
To beat CSRF, applications should verify whether a request is forged or not before performing commands.
5. HTTP Strict Transport Security Header
HTTP strict transport security header makes it possible for browsers to restrict access to a site to only HTTPS requests. Sending data over the nonsecure HTTP protocol can expose data in transit.
To prevent strict transport security header-related vulnerabilities, enable HTTPS on web applications.
Conclusion
To conclude, here are a few points that sum up our discussion on security in Kotlin:
Kotlin, just like most popular programming languages, gets consistent updates that patch security vulnerabilities.
However, application security depends on how a developer uses features and tools on their app. You should always test your applications for common security vulnerabilities.
Finally, keeping all tools—including third-party dependencies that you use in your application—up to date can also improve security.