Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to implement Java Log injection

2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article introduces the relevant knowledge of "how to achieve Java log injection". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

Case story

When a new system is online, Xiao A develops a simple login module that records all successful or failed login users in the log.

Xiao A has checked the whitelist of the user name, and incorrect names will also be printed out in the form of WARN to make records.

Like this:

[2021-04-17 16:50:35] [INFO] [main] [Login:308] login success,userName=tony [2021-04-17 16:50:35] [WARN] [main] [Login:308] username is wrong,userName=tony.dssdff

Log docking with the risk audit system, will regularly audit from the log those who have suspicious login behavior every day, such as those who log in in the middle of the night or log in frequently (don't worry about the details, you can do it without audit, just to give an example)

One day, the log audit system indicated that tony login was too frequent and high-risk operations, so the number of tony was blocked.

The following day, more than N innocent users were blocked, causing a large number of dissatisfaction among users. The operation department asked for the crime, and Xiao A took out the following log file as evidence:

[2021-04-17 16:50:35] [INFO] [main] [Login:308] login success,userName=tony [2021-04-17 16:50:35] [WARN] [main] [Login:308] username is wrong,userName=tony.dssdff [2021-04-17 16:50:35] [INFO] [main] [Login:308] login success,userName=tony [2021-04-17 16:50:35] [INFO] [main] [Login:308] login success UserName=tony [2021-04-17 16:50:35] [INFO] [main] [Login:308] login success,userName=tony [2021-04-17 16:50:35] [INFO] [main] [Login:308] login success,userName=tony

However, tony responded that there was evidence that he was traveling outside that day and that his computer was at home.

At this time, the boss of Xiao A found out the log of the request interface and found that a request was sent at that time, and the username parameter in the interface was:

Username=tony.dssdff [2021-04-17 16:50:35] [INFO] [main] [Login:308] login success,userName=tony [2021-04-17 16:50:35] [INFO] [main] [Login:308] login success,userName=tony [2021-04-17 16:50:35] [INFO] [main] [Login:308] login success,userName=tony [2021-04-17 16:50:35] [INFO] [main] [Login:308] login success,userName=tony

Boy, there is a line break in username. Although I have done a whitelist check, the log has cheated a lot of users in order to record the wrong name with line break. (because the other party may have sent it maliciously using rest-api, it also bypassed the verification of the foreground page.)

As a result, Xiao A's company suffered huge losses, and Xiao A finally lost his job.

Simple rectification method

Little A struggled to find a new company and took over a pile of old code. He decided to take precautions in advance and add line wrapping to the externally entered log parameters.

He wrote a method as follows:

/ * obtain purified messages, filter line breaks, and avoid log injection * @ param message * @ return * / public static String getCleanedMsg (String message) {if (message = = null) {return ";} message = message.replace ('\ nmessages,'_'). Replace ('\ ringing,'_'); return message;}

And add this method to the place where you log yourself.

LOGGER.warn ("username is wrong,userName= {}", getCleanedMsg (userName))

However, I remembered that the system was relatively old and had many similar parameters, so I searched for it and found that there were more than 1000 logs with parameters, many of which were left to him by his predecessors.

So he revised and checked one by one with a sense of responsibility, and it took him more than a month to sort out all the external input parameters and add the getCLeanMsg method. At the end of the year, due to insufficient output, he memorized the lowest performance, was depressed, and lost his hair again.

Unified modification of log4j2 configuration message

Xiao A was changed to a new project team, and this time he decided not to repeat the same mistake and simplify it in other ways. All the logs in his project are printed in log4j2. If you can make use of the framework's ability to get rid of all the new lines of the log, it would be good to strictly ensure that the log output is only 1 line.

So I began to study the official documents of log4j2 carefully. He found the location related to the log output format in it, as follows: https://logging.apache.org/log4j/2.x/manual/layouts.html

He searched for\ nor newline keywords and found the following:

It is clearly written in the document that line feeds can be filtered using% enc {% m} {CRLF}. So the one in log4j2.xml is changed to the following:

Test, and eventually all logs will have only one line. The log that used to cause problems has also become

Username=tony.dssdff\ r\ n [2021-04-17 16:50:35] [INFO] [main] [Login:308] login success,userName=tony

Therefore, it will not be parsed by log system errors, and it also saves the risk of troubleshooting one by one.

Log4j2 modifies mesage in exception

After a month, suddenly the log audit gave another alarm, and finally it was a false alarm again. I went to read the log and found that it looked like this:

[2021-04-17 16:50:35] [INFO] [main] [Login:308] unknown error happendjava.lang.RuntimeException: name,name=%s [2021-04-17 16:50:35] [INFO] [main] [Login:308] login success,userName=tony [2021-04-17 16:50:35] [INFO] [main] [Login:308] login success,userName=tony [2021-04-17 16:50:35] [INFO] [main] [Login:308] login success UserName=tony [2021-04-17 16:50:35] [INFO] [main] [Login:308] login success,userName=tony at java.net.SocketInputStream.socketRead0 (Native Method) ~ [?] At java.net.SocketInputStream.socketRead (SocketInputStream.java:115) ~ [?] At java.net.SocketInputStream.read (SocketInputStream.java:168) ~ [?] At java.net.SocketInputStream.read (SocketInputStream.java:140) ~ [?] At sun.security.ssl.SSLSocketInputRecord.read (SSLSocketInputRecord.java:448) ~ [?]

Boy, it turns out that when printing logs in some places, the unhandled exception stack is also printed out. The first line of the exception stack is often the exception name + message, which can also be maliciously exploited.

Xiao A rummaged through the log4j2 document and found no symbol that could handle line breaks in an exception. Only a ThrowablePatternConverter was found. The document told him that you can customize this ThrowablePatternConverter to print the exception you want.

So he wrote a UndefineThrowablePatternConvert himself, in which he rewrote the logic of log stack printing

/ * A format conversion class that does specific encoding of exceptions * when used Add% eEx to layout * * @ since 2021-4-16 * / @ Plugin (name = "UndefineThrowablePatternConverter", category = PatternConverter.CATEGORY) / / self-defined layout key @ ConverterKeys ({"uEx"}) public class UndefineThrowablePatternConverter extends ThrowablePatternConverter {/ * ThrowableProxy * / static class EncodeThrowableProxy extends ThrowableProxy {public EncodeThrowableProxy (Throwable throwable) {super (throwable) with specific encoding processing } / / encode\ r and\ n to avoid injecting @ Override public String getMessage () {String encodeMessage = super.getMessage (). ReplaceAll ("\ r", "\ r") .replaceAll ("\ n", "\ n"); return encodeMessage }} protected UndefineThrowablePatternConverter (Configuration config, String [] options) {super ("UndefineThrowable", "throwable", options, config);} / / log4j2 uses reflection to call the newInstance static method for construction, so this method must be implemented. Public static UndefineThrowablePatternConverter newInstance (final Configuration config, final String [] options) {return new UndefineThrowablePatternConverter (config, options);} @ Override public void format (final LogEvent event, final StringBuilder toAppendTo) {Throwable throwable = event.getThrown (); if (throwable = = null) {return;} / / use custom EncodeThrowableProxy, which rewrites ThrowableProxy's getMessage method EncodeThrowableProxy proxy = new EncodeThrowableProxy (throwable) / / add to toAppendTo proxy.formatExtendedStackTraceTo (toAppendTo, options.getIgnorePackages (), options.getTextRenderer (), getSuffix (event), options.getSeparator ());}}

And add% uEx to the PatternLayout, and you will use the format here to generate the stack string.

"how to achieve Java log injection" content is introduced here, thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report