tomcat 协议处理程序初始化失败_分析tomcat包解析来构造畸形http包

479bea63fa2fbce59745b723275d0a28.png

No.1

源码下载

http://apache.communilink.net/tomcat/tomcat-9/v9.0.31/src/apache-tomcat-9.0.31-src.zip

No.2

寻找tomcat代码入口

本次分析的源码为tomcat9.0.31

首先寻找代码的入口点

我们在win上一般启动tomcat,都是使用bin目录下的startup.bat

42a337dff192c4e30bd6551801d7c884.png

这里调用了catelina.bat

Catelina第259行设置了mainclass

b4a9c47f6b1962276cadd9d8dfcb20f0.png 9ff6672bbbcee1d613129dbb037d96b8.png

并在361行做了调用

我们通过catelina.bat的mainclass值就能找到入口点

org.apache.catalina.startup.Bootstrap

使用idea打开tomcat源码,找到

5d14e221211f74c1176f469b8221dc9c.png

这里就是tomcat的入口点了。

No.3

Tomcat启动分析

tomcat启动时会先进行一些初始化

网上有张图很详细地描绘了tomcat的启动流程

a9d36cd3e4fb39ebc9e8fa5f7c7a977f.png

我们先看第一部分

64ea933debe7141b54661160eb9178f9.png

先从main方法进入,调用init,然后再执行load方法,从load方法中调用catalina的init方法,我们从代码上跟一下

acd4daf1098ad2fe92011d8fd49e39da.png da18bda701976820c7cf3cf16118f281.png

使用java的反射调用org.apache.catalina.startup.Catalina

之后赋值给catalinaDaemon

返回main方法,跟踪到466行,进入load方法

1f4e057b82f8d2c0af46add8dd55cc5a.png 4607c1cdeb65fc6c7428521e258d4da8.png

最后发现反射调用了org.apache.catalina.startup.Catalina.load

559行是处理server.xml配置信息的功能

da38e3a37ab0d129d7cffbf257ef065e.png

584行调用了server的init方法

932ddae10d768ab7f20cf7e231946e3c.png

也就是流程图的这里

1c3720e481b9f29acaa5aed8531be599.png

进入之后发现是个接口

070e0af076dae16e4c6b78604e3db630.png

这是设计模式里面的模板模式,点击I标志进入实现方法进入lifecyclebase

点击initInternal()

de150d181c7e51a7933892925ca4a131.png e27c3d699ca3ce8746b7075c2e7c2a02.png

找到standardServer

8363697ab60789083107046136623c53.png

发现for循环调用services[i].init();

是因为tomcat不止启动了一个service,然后继续跟进

5aef6b054ab502463c09b2d139e38956.png aa86650e47e03008c3421ebf8e80818c.png

发现和流程图一样 init了三个方法,之后的流程和之前类似就不再分析,

No.4

Tomcat包解析

Tomcat解析http协议是在

最后一步的Protocol Handler里面

生成UML图

af68878acb2b9b1a185639e528c22aec.png

发现tomcat一共支持三种协议,http1.1 http2 和ajp

Ajp就前几天还出了个文件读取及RCE

今天我们分析http11

00feaf849cf0ed65b44313d630e00d45.png

查看构造方法我们知道tomcat解析http协议是使用filter的方式进行解析的,在service方法中我们找到了解析请求行的代码

0ea861b9d4acc71e97a088f18f0883f6.png

跟进方法

1fc22dcac09ac611ca97ac4946bfcc07.png

parsingRequestLinePhase == 2时,开始解析http方法,这里我们可以看见用了一个while循环来查找 sp和ht,当找到sp和ht就代表http方法读取完毕了。

sp是space ht是 tab

04744d929834ed46f928994916712490.png

解析完http方法之后,会将parsingRequestLinePhase改为3

1cc749a563ad95f17e0d48b2f98cd575.png

这里又是一个while循环,因为之前是读取http方法,

当读到空格即为结束,

所以当parsingRequestLinePhase为3时候必然后面是空格,所以这里是当space和tab读取和结束的时候就退出,用于忽略tab和空格

用bp发包发现确实会忽略

abd4345464eca18f6d18ef1522216ab8.png df2ba4e07e3c4fbcf99a36a4e83dcd5d.png

后面的逻辑类似,就讲一下比较有意思的点

parsingRequestLinePhase == 4

1f9f92341a48cd3a21e2b1efb7fa5ef5.png

为了兼容http0.9的风格,这里还会以回车作为终点

0baa0246269dceacfae1ed0282bbfa0f.png

回到http11Processor,

查看inputBuffer. parseHeaders()

9970efb95378359fc1bca7c6667b5428.png

里面是do循环

4bf83396e1a3b4a47f198d94ecc48afd.png

注意在564行开始解析headername

e0047202e66fee79d81f18e39cb067ed.png

COLON是冒号,匹配到冒号就将值加入到headerValue

5612881b6dc8e4ba7aa7f5b4dabf6f7d.png

在框红线的地方,他将坐标改成了HEADER_VALUE_START

所以我们寻找到这里

02362f7e090215f50a5530b1581e028a.png

当值没有sp和ht的时候,开始解析header_value

查看header_value方法

a705541d35b3cefea43de70ef0027ee7.png e60e93e7b2c22ae61aa314550c50d067.png

No.5

总结

总结到之前的那些点,删除没用的行 就能构造出这种有意思的包

34f53329614e0d5211babbf5696af7ed.png

主要达成这种效果还是因为对RFC标准的容错

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值