解决CRLF日志注入
CRLF 简介
CRLF的含义是回车和换行。这些元素嵌入在HTTP标头和其他软件代码中,以表示行尾(EOL)标记。当攻击者能够将CRLF序列注入HTTP流时,就会出现漏洞。通过引入这种意外的CRLF注入,攻击者能够恶意利用CRLF漏洞来操纵Web应用程序的功能。
CRLF 攻击示例
攻击者通过接口访问网站时,可以在参数中添加\r\n,然后再输入“connect failed”之类的误导性信息,如果攻击成功的话,日志中就会出现换行,在新行中出现“connect failed”,这样,就有可能导致管理员花费很多精力去解决一个不存在的错误。
CRLF注入的修复建议
CRLF注射很容易预防:
- 始终遵循永不信任用户输入的规则。
- 清理并中和所有用户提供的数据或正确编码HTTP标头中的输出,否则这些输出将对用户可见,以防止注入CRLF序列及其后果。
CRLF防御示例
例如有个post请求,localhost:8080/appPay/newOrder ,请求参数如下所示:
{
"orderId":"89077",
"skuId":"1",
"order":"1istainjection\r\n order created success!"
}
我们可以考虑以下方案:
1.在对应业务代码中提前对参数进行校验,去除特殊字符串
2.添加过滤器
首先方案1的话,属于头疼医头,脚疼医脚,如果被攻击的业务比较多的话,改起来相当麻烦
方案2 的话,我们需要实现一个类继承HttpServletRequestWrapper,从而获取HttpServletRequest传过来的参数值,对其进行修改后,然后通过过滤器传递下去。
定义过滤器ParameterFilter
package com.webStudy.notes;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;@WebFilter
public class ParameterFilter implements Filter {@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {MyRequestWrapper request = new MyRequestWrapper((HttpServletRequest)servletRequest);filterChain.doFilter(request,servletResponse);}
}
实现自己的MyRequestWrapper (常用的手段)
package com.webStudy.notes;import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.regex.Matcher;
import java.util.regex.Pattern;public class MyRequestWrapper extends HttpServletRequestWrapper {private static String REGEX ="[\\r,\\n]";private static Pattern pattern = Pattern.compile(REGEX);private final String body;public MyRequestWrapper(HttpServletRequest request) throws IOException {super(request);StringBuilder sb = new StringBuilder();InputStream ins = request.getInputStream();BufferedReader isr = null;try{if(ins != null){isr = new BufferedReader(new InputStreamReader(ins));char[] charBuffer = new char[128];int readCount = 0;while((readCount = isr.read(charBuffer)) != -1){sb.append(charBuffer,0,readCount);}}else{sb.append("");}}catch (IOException e){throw e;}finally {if(isr != null) {isr.close();}}body = changeBodyStr(sb.toString());}//某些情况下,可能出现\r\n被转义,也就是参数中表示为\\r,\\n,这种情况需要直接替换字符串"\\r","\\n",可以自行实现private String changeBodyStr(String bodyString){Matcher matcher = pattern.matcher(bodyString);return matcher.replaceAll("").trim();}@Overridepublic BufferedReader getReader() throws IOException {return new BufferedReader(new InputStreamReader(this.getInputStream()));}//从流中读取一次Body信息后,流就被关闭了,所以需要重写一个方法来返回新的ServletInputStream@Overridepublic ServletInputStream getInputStream() throws IOException {final ByteArrayInputStream byteArrayIns = new ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8));return new ServletInputStream() {@Overridepublic boolean isFinished() {return false;}@Overridepublic boolean isReady() {return false;}@Overridepublic void setReadListener(ReadListener readListener) {}@Overridepublic int read() throws IOException {return byteArrayIns.read();}};}
}
除了以上两种,还可以考虑通过AOP,拦截所有controller,再修改body,也许通过@initBinder也可以做一些操作(未验证)
还有个思路是直接不让日志中打印"\r\n",比如logback中的Layout组件,其作用为:
对LoggingEvent进行格式化,返回一个String,然后通过OutputStream.write()方法,把格式化之后的日志信息写到目的地。
logback配置,参考方案2 的思路,我们也可以通过extends PatternLayout的方式写个自己的PatternLayout,来对日志信息做处理,然后输出到目的地。
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"><layout class="自定义layout类" />
</encoder>
以上是我个人对CRLF日志注入的一个总结,希望能对大家有所帮助。
参考文章:
https://www.jianshu.com/p/47de9e15b2b7
https://blog.csdn.net/zxygww/article/details/47045055
https://www.jianshu.com/p/a0eb78b8c775?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation
解决CRLF日志注入相关推荐
- 安全开发Java:日志注入,并没那么简单
本文分享自华为云社区<Java云服务开发安全问题解析--日志注入,并没那么简单>,原文作者:breakDraw. 案例故事 某个新系统上线了,小A在其中开发了个简单的登录模块,会在日志里记 ...
- 解决MongoDB 日志文件过大,清理后还占用很大磁盘空间的问题
解决MongoDB 日志文件过大,清理后还占用很大磁盘空间的问题 参考文章: (1)解决MongoDB 日志文件过大,清理后还占用很大磁盘空间的问题 (2)https://www.cnblogs.co ...
- 解决静态方法调用注入的service
解决静态方法调用注入的service 参考文章: (1)解决静态方法调用注入的service (2)https://www.cnblogs.com/xiaoshahai/p/11610898.html ...
- [zabbix]解决binlog日志过大/web界面中文乱码问题
转载来源: [zabbix]解决binlog日志过大/web界面中文乱码问题 : https://www.jianshu.com/p/44cace796206 记录之前在跑项目过程中遇到的一次binl ...
- Azure NSG Flow Log 引发的自嗨 -- 事件驱动的日志注入
上一回我们对 NSG Flow Log 方案的整体架构做了介绍,大家可以参考下面的架构图,快速回忆一下.本文我们主要聚焦在事件驱动的日志注入部分,即架构图中流程中的第一到第三步. NSG Flow L ...
- 宝塔面板使用WWW用户执行计划任务命令 解决laravel日志权限问题 宝塔设置计划任务执行用户
宝塔面板使用WWW用户执行计划任务命令 解决laravel日志权限问题 宝塔设置计划任务执行用户 问题背景 宝塔面板的计划任务默认执行用户是root,如果任务里有打印日志的操作,则自动创建的log文件 ...
- 解决定时任务无法注入的问题,配置类
在定时任务执行的时候,当时间点到了,执行job的时候,有时候需要用到某些bean,但是自动注入是不行的,所以只能想其他办法, 新建class加入该配置类方可解决 package com.jszb.rz ...
- 如何解决后台日志显示Nacos客户端不断重复拉取配置的问题
文章目录 如何解决后台日志显示Nacos客户端不断重复拉取配置的问题 问题描述 问题原因 解决方法 临时解决方法 永久解决方法 如何解决后台日志显示Nacos客户端不断重复拉取配置的问题 问题描述 后 ...
- java log4j logback jcl_内部分享:如何解决Java日志框架冲突问题。
来源:https://urlify.cn/E7zEfq # 前言 Java 有很多的日志框架可以选择,当同一个项目中出现多种日志框架时就很容易出现日志框架冲突的问题,导致日志打印不出来.本文将以一次典 ...
最新文章
- 交替最小二乘+ALS+推荐+Spark
- 管理者的智慧:靠制度管人,不靠人管人
- 039_Dialog对话框
- 计量经济学和机器学习方法的在假设上的区别
- JAVA听力源码,英语听力练习
- 计算机常用主题词,标引主题词的目的是( )。A.反映文件的全部内容B.便于计算机检索和管理C.供归_考题宝...
- python图片识别是否p过_Python+Opencv进行识别相似图片
- 消息队列一直建立tcp连接_云架构那些事儿:为什么我的TCP连接建立异常?
- linux下msmtp+mutt+shell发送邮件
- Matplotlib 中文用户指南 8.2 我们最喜欢的秘籍
- f分布表完整图a=0.01_基于时频分布和CNN的信号调制识别分类方法
- docker出现问题:You cannot remove a running container 解决方案
- c语言求最小值函数min的用法,C语言--min的宏定义
- java软件工程师基本技能_Java软件工程师主要有什么技能
- 【TIC6657 DSP学习笔记】02 RTSC平台配置组件创建
- 【精选】基于EasyX的贪吃蛇小游戏
- 图像处理技术:图像切割、标签、贴纸花字,超细开发详解
- 第6回 スライドによるページナビゲーション
- The server time zone value ‘‘ is unrecognized or represents more than one time zone
- van-icon自定义图标的引入
热门文章
- 戴尔计算机和台式机区别吗,戴尔的台式机怎么样?戴尔的台式机有什么优缺点...
- qstring如何初始化_学习QT之QString详解
- 盛普向全球招募LeSoleil莱素理防治药物系列对COVID-19已知所有变异毒株的临床研究再验证合作机构的公告
- 带参数的QString
- 计算机毕业设计php的汽车俱乐部会员管理系统
- Pix2Pix(2017)+CycleGAN+Pix2PixHD
- 瞧瞧别人家的API接口,那叫一个优雅
- C语言关键字浅析-const
- 笔记本调整ubuntu14.04界面、字体大小
- 人生有多少时间浪费在眼泪,与狭窄之间