Secure Development Lifecycle Practices

Secure Development Lifecycle Practices
Secure Development Lifecycle Practices

We, as developers, focus on the business and performance first. Thus, we ignore security most of the times. In this post, we are going to talk about the secure development lifecycle practices. In summary, we will cover the most common mistakes and how to solve them.

SQL Injection

Here, as you know, this is quite an old problem. Meanwhile, with the ORM frameworks we can easily overcome this.

Problem

Our queries can include statements that we don’t expect. As a result, attackers can manipulate our data.

How

For example, the below code adds the input sent from the client.

1
2
String query = "select * products where title = " + input;
connection.runQuery(query);

When client sends the input like below, it can drop your complete table.

1
input = "''; drop table users";

How To Secure

By using ORM tools (like Hibernate) we can overcome SQL injection easily.

IDOR

Problem

In general, we use sequential identifiers for each record. Thus, when attacker discovers this, she/he can try to fetch any data by trying other ids.

How

In this case we consider our API calls. Like the code below, we call values with their IDs.

1
2
3
http.get("foo.bar/product?userId=432&id=213").then((response) -> {
    document.info.product = response.data;
});

For this reason, a user can fetch any data by trying other IDs like:

1
2
3
http.get("foo.bar/product?userId=23&id=524").then((response) -> {
    document.info.product = response.data;
});

How To Secure

Indeed, by using a different representation of IDs and limiting access of data for any user.

1
2
3
http.get("foo.bar/product?userId=0231-3524-1253-523&id=2532-5352-5323-5325").then((response) -> {
    document.info.product = response.data;
});

Secure Passwords

Problem

Whenever you encode passwords to save into DB, you must use enoughly secured algorithms.

How

As long as you use MD5 (SHA1) your encryption is not enough secured.

How To Secure

Nowadays, the most secured encryption is SHA3. Moreover, if you want an algorithm which is not possible to decrypt, you can use the below code.

1
SHA3(SHA2(value) + CONSTANT_8_CHAR)

Here, “CONSTANT_8_CHAR” is an any value that you define as a static key value.

Secure File Upload

Problem

In case uploading a file, we must check the file type correctly. If the code is checking the type only by content type or extension, this is hijackable.

How

Since the below code checks the file type, it is not enough secured.

1
2
3
if (request.contentType.isEqualTo("image/gif")) {
    save(request.getParameter("file"));
}

Of course, an attacker easily can change the content type and also the extension in the file name. Thus, an attacker can upload a malware to our systems.

How To Secure

In reality, the code has to check the extension and also the file header for the type.

1
2
3
4
5
6
7
8
9
10
11
// Headers are only mock samples
List<String> listOfHeadersForGifFile = Arrays.asList(
   "ASE3-AD2J-MB39-NV39",
   "KI45-3M5M-48DK-U789"
);

File gifFile = request.getParameter("file");

if (gifFile.getFileName().suffix() == "gif" && gifFile.containsHeaders(listOfHeadersForGifFile)) {
    save(gifFile);
}

ReDos

Problem

In general, we use Regex patterns to match any String value we want. But, we have to be careful when generating them. A hacker can send a value to our regex matcher that causes infinite computing.

How

Surprisingly, if you pass the value “aaaaaaaaaaaaaaaaaaaaaaaaaaaa!” to the below regex, it won’t stop the execution. Thus, this will cause your server of high usage of CPUs.

1
([a-z]+)+$

How To Secure

As it is described in this link, Do not use nested constructs that have “+” or “*”! For example, “([a-z]+)*” is a badly-written construct that could be rewritten as “[a-z]*” without changing the logic.

Shell Command Injection

Problem

Such as SQL injection, this happens when you don’t check the input to a shell command. An attacker can run any shell command on your machine and take sensitive data.

How

For example, you app shows the result of the command nslookup with an input.

1
response.data = shell.run("nslookup " + request.getParam("input"));

As soon as an attacker inputs “foo.bar && cat$IFS/etc/passwd” it will return the password value located in “$IFS/etc/passwd”.

How To Secure

Likewise, check the input if contains only permitted characters.

1
2
3
4
String input = request.getParam("input");
if (regex.test(input, "[a-z0-9\.]+")) {
    response.data = shell.run("nslookup " + request.getParam("input"));
}

XML Injection

Problem

Again, when getting an input in xml format, an attacker can inject a code that can reveal sensitive data.

How

For example, think that you are getting an input in xml format. If an attacker uses the keyword “SYSTEM” this manipulates the xml parser and causes to reveal some sensitive data.

1
xmlParser.parse(request.getHeader("xmlInput"));
1
2
3
4
5
6
7
http.get("foo.bar/sendXml"). withHeader("xmlInput" , "

<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><!DOCTYPE foo [  <!ELEMENT foo ANY ><!ENTITY xxe SYSTEM \"file:///etc/passwd\" >]><foo>&xxe;</foo>

"
).then((response) -> {
    alert(response.data);
});

How To Secure

Correspondingly, you can simply check if xml input contains keyword “SYSTEM”.

1
2
3
4
String xmlInput = request.getHeader("xmlInput");
if (!xmlInput.contains("SYSTEM")) {
    xmlParser.parse(xmlInput);
}

Mass Assignment

Problem

Generally speaking, in MVC applications we return model to the client. When the model is returned and saved to repository, the fields can be hijacked.

How

To explain, think that you have the below entity.

1
2
3
4
5
6
User {
  Long id;
  String name;
  String surname;
  String salary;
}

Moreover, you are sending it to the client to show and edit the fields, except the salary.

1
http.post("foo.bar/update-user", user);

For the puspose of attacking, an hacker can send this request like below.

1
2
user.salary = 1000000;
http.post("foo.bar/update-user", user);

Thus, this request will change the salary.

1
repository.save(request.getBody());

How To Secure

As a matter of fact, you have to use a data transfer object to send and receive only the fields that you want to show and update.

1
2
3
4
5
6
7
8
9
10
11
UpdateUserRequest {
  Long id;
  String name;
  String surname;
}

UpdateUserRequest request = request.getBody();
User user = repository.findById(request.getId());
user.setName = request.getname();
user.setSurname = request.getSurname();
repository.save(user);

Secure Captcha

Problem

Correspondingly, the captcha solution is used to block DDOS attacks. Besides, if not used correctly, it will not effect.

How

If you are not invalidating a successful captcha from sessions, an hacker can make consecutive requests with a successful captcha request.

1
2
3
if (isValid(session.getParam("captcha"))) {
    userService.login(request);
} // capctha is still valid in the session.

How To Secure

As a matter of fact, you have to invalidate the captcha every time it is used.

1
2
3
4
if (isValid(session.getParam("captcha"))) {
    userService.login(request);
}
session.invalidate("captcha");

Conclusion

Altogether, above are the most important and the mostly ignored security issues. On the whole, we as developers have to beware those tiny but very important things to prevent system security vulnerabilities.

Furthermore, please don’t forget to read my other post about Variable Naming in Programming.