Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
LinuxSuRen
jenkins
提交
ea302e1f
J
jenkins
项目概览
LinuxSuRen
/
jenkins
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
jenkins
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
ea302e1f
编写于
1月 11, 2021
作者:
J
Jeff Thompson
提交者:
Jenkins CERT CI
1月 11, 2021
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[SECURITY-1986]
上级
89ec0c40
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
229 addition
and
0 deletion
+229
-0
core/src/main/java/hudson/model/labels/LabelAtom.java
core/src/main/java/hudson/model/labels/LabelAtom.java
+22
-0
test/src/test/java/hudson/model/labels/LabelAtomSecurity1986Test.java
...t/java/hudson/model/labels/LabelAtomSecurity1986Test.java
+207
-0
未找到文件。
core/src/main/java/hudson/model/labels/LabelAtom.java
浏览文件 @
ea302e1f
...
@@ -33,13 +33,16 @@ import hudson.XmlFile;
...
@@ -33,13 +33,16 @@ import hudson.XmlFile;
import
hudson.model.Action
;
import
hudson.model.Action
;
import
hudson.model.Descriptor.FormException
;
import
hudson.model.Descriptor.FormException
;
import
hudson.model.Failure
;
import
hudson.model.Failure
;
import
hudson.model.FileParameterValue
;
import
hudson.util.*
;
import
hudson.util.*
;
import
jenkins.model.Jenkins
;
import
jenkins.model.Jenkins
;
import
hudson.model.Label
;
import
hudson.model.Label
;
import
hudson.model.Saveable
;
import
hudson.model.Saveable
;
import
hudson.model.listeners.SaveableListener
;
import
hudson.model.listeners.SaveableListener
;
import
jenkins.util.SystemProperties
;
import
org.kohsuke.accmod.Restricted
;
import
org.kohsuke.accmod.Restricted
;
import
org.kohsuke.accmod.restrictions.DoNotUse
;
import
org.kohsuke.accmod.restrictions.DoNotUse
;
import
org.kohsuke.accmod.restrictions.NoExternalUse
;
import
org.kohsuke.stapler.StaplerRequest
;
import
org.kohsuke.stapler.StaplerRequest
;
import
org.kohsuke.stapler.StaplerResponse
;
import
org.kohsuke.stapler.StaplerResponse
;
import
org.kohsuke.stapler.export.Exported
;
import
org.kohsuke.stapler.export.Exported
;
...
@@ -56,6 +59,8 @@ import java.util.Set;
...
@@ -56,6 +59,8 @@ import java.util.Set;
import
java.util.Vector
;
import
java.util.Vector
;
import
java.util.logging.Level
;
import
java.util.logging.Level
;
import
java.util.logging.Logger
;
import
java.util.logging.Logger
;
import
java.util.regex.Pattern
;
import
edu.umd.cs.findbugs.annotations.CheckForNull
;
import
edu.umd.cs.findbugs.annotations.CheckForNull
;
import
edu.umd.cs.findbugs.annotations.Nullable
;
import
edu.umd.cs.findbugs.annotations.Nullable
;
...
@@ -66,6 +71,12 @@ import edu.umd.cs.findbugs.annotations.Nullable;
...
@@ -66,6 +71,12 @@ import edu.umd.cs.findbugs.annotations.Nullable;
* @since 1.372
* @since 1.372
*/
*/
public
class
LabelAtom
extends
Label
implements
Saveable
{
public
class
LabelAtom
extends
Label
implements
Saveable
{
private
static
final
Pattern
PROHIBITED_DOUBLE_DOT
=
Pattern
.
compile
(
".*\\.\\.[\\\\/].*"
);
private
static
/* Script Console modifiable */
boolean
ALLOW_FOLDER_TRAVERSAL
=
SystemProperties
.
getBoolean
(
LabelAtom
.
class
.
getName
()
+
".allowFolderTraversal"
);
private
DescribableList
<
LabelAtomProperty
,
LabelAtomPropertyDescriptor
>
properties
=
private
DescribableList
<
LabelAtomProperty
,
LabelAtomPropertyDescriptor
>
properties
=
new
DescribableList
<>(
this
);
new
DescribableList
<>(
this
);
...
@@ -167,6 +178,9 @@ public class LabelAtom extends Label implements Saveable {
...
@@ -167,6 +178,9 @@ public class LabelAtom extends Label implements Saveable {
}
}
public
void
save
()
throws
IOException
{
public
void
save
()
throws
IOException
{
if
(
isInvalidName
())
{
throw
new
IOException
(
"Invalid label"
);
}
if
(
BulkChange
.
contains
(
this
))
return
;
if
(
BulkChange
.
contains
(
this
))
return
;
try
{
try
{
getConfigFile
().
write
(
this
);
getConfigFile
().
write
(
this
);
...
@@ -206,6 +220,10 @@ public class LabelAtom extends Label implements Saveable {
...
@@ -206,6 +220,10 @@ public class LabelAtom extends Label implements Saveable {
app
.
checkPermission
(
Jenkins
.
ADMINISTER
);
app
.
checkPermission
(
Jenkins
.
ADMINISTER
);
if
(
isInvalidName
())
{
throw
new
FormException
(
"Invalid label"
,
null
);
}
properties
.
rebuild
(
req
,
req
.
getSubmittedForm
(),
getApplicablePropertyDescriptors
());
properties
.
rebuild
(
req
,
req
.
getSubmittedForm
(),
getApplicablePropertyDescriptors
());
this
.
description
=
req
.
getSubmittedForm
().
getString
(
"description"
);
this
.
description
=
req
.
getSubmittedForm
().
getString
(
"description"
);
...
@@ -216,6 +234,10 @@ public class LabelAtom extends Label implements Saveable {
...
@@ -216,6 +234,10 @@ public class LabelAtom extends Label implements Saveable {
FormApply
.
success
(
"."
).
generateResponse
(
req
,
rsp
,
null
);
FormApply
.
success
(
"."
).
generateResponse
(
req
,
rsp
,
null
);
}
}
private
boolean
isInvalidName
()
{
return
!
ALLOW_FOLDER_TRAVERSAL
&&
PROHIBITED_DOUBLE_DOT
.
matcher
(
name
).
matches
();
}
/**
/**
* Accepts the new description.
* Accepts the new description.
*/
*/
...
...
test/src/test/java/hudson/model/labels/LabelAtomSecurity1986Test.java
0 → 100644
浏览文件 @
ea302e1f
/*
* The MIT License
*
* Copyright (c) 2020, 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
hudson.model.labels
;
import
com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException
;
import
hudson.XmlFile
;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.jvnet.hudson.test.Issue
;
import
org.jvnet.hudson.test.JenkinsRule
;
import
java.io.IOException
;
import
java.net.HttpURLConnection
;
import
static
org
.
hamcrest
.
MatcherAssert
.
assertThat
;
import
static
org
.
hamcrest
.
Matchers
.
equalTo
;
import
static
org
.
hamcrest
.
Matchers
.
is
;
import
static
org
.
junit
.
Assert
.
assertFalse
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
junit
.
Assert
.
fail
;
public
class
LabelAtomSecurity1986Test
{
@Rule
public
JenkinsRule
j
=
new
JenkinsRule
();
@Test
public
void
nonexisting
()
throws
Exception
{
LabelAtom
nonexistent
=
j
.
jenkins
.
getLabelAtom
(
"nonexistent"
);
XmlFile
configFile
=
nonexistent
.
getConfigFile
();
assertFalse
(
configFile
.
getFile
().
exists
());
}
@Test
public
void
normal
()
throws
Exception
{
j
.
submit
(
j
.
createWebClient
().
goTo
(
"labelAtom/foo/configure"
).
getFormByName
(
"config"
));
LabelAtom
foo
=
j
.
jenkins
.
getLabelAtom
(
"foo"
);
XmlFile
configFile
=
foo
.
getConfigFile
();
assertTrue
(
configFile
.
getFile
().
exists
());
assertThat
(
configFile
.
getFile
().
getParentFile
().
getName
(),
equalTo
(
"labels"
));
}
@Test
@Issue
(
"SECURITY-1986"
)
public
void
startsWithDoubleDotSlash
()
throws
Exception
{
try
{
j
.
submit
(
j
.
createWebClient
().
goTo
(
"labelAtom/..%2ffoo/configure"
).
getFormByName
(
"config"
));
fail
(
"Should have rejected label."
);
}
catch
(
FailingHttpStatusCodeException
e
)
{
assertThat
(
e
.
getStatusCode
(),
is
(
HttpURLConnection
.
HTTP_BAD_REQUEST
));
LabelAtom
foo
=
j
.
jenkins
.
getLabelAtom
(
"../foo"
);
XmlFile
configFile
=
foo
.
getConfigFile
();
assertFalse
(
configFile
.
getFile
().
exists
());
}
}
@Test
public
void
startsWithSlash
()
throws
Exception
{
// Not a great result, but it works and doesn't cause problems.
j
.
submit
(
j
.
createWebClient
().
goTo
(
"labelAtom/%2ffoo/configure"
).
getFormByName
(
"config"
));
LabelAtom
foo
=
j
.
jenkins
.
getLabelAtom
(
"/foo"
);
XmlFile
configFile
=
foo
.
getConfigFile
();
assertTrue
(
configFile
.
getFile
().
exists
());
assertThat
(
configFile
.
getFile
().
getParentFile
().
getName
(),
equalTo
(
"labels"
));
}
@Test
public
void
startsWithDoubleDot
()
throws
Exception
{
j
.
submit
(
j
.
createWebClient
().
goTo
(
"labelAtom/..foo/configure"
).
getFormByName
(
"config"
));
LabelAtom
foo
=
j
.
jenkins
.
getLabelAtom
(
"..foo"
);
XmlFile
configFile
=
foo
.
getConfigFile
();
assertTrue
(
configFile
.
getFile
().
exists
());
assertThat
(
configFile
.
getFile
().
getParentFile
().
getName
(),
equalTo
(
"labels"
));
}
@Test
@Issue
(
"SECURITY-1986"
)
public
void
endsWithDoubleDotSlash
()
throws
Exception
{
try
{
j
.
submit
(
j
.
createWebClient
().
goTo
(
"labelAtom/foo..%2f/configure"
).
getFormByName
(
"config"
));
fail
(
"Should have rejected label."
);
}
catch
(
FailingHttpStatusCodeException
e
)
{
assertThat
(
e
.
getStatusCode
(),
is
(
HttpURLConnection
.
HTTP_BAD_REQUEST
));
LabelAtom
foo
=
j
.
jenkins
.
getLabelAtom
(
"foo../"
);
XmlFile
configFile
=
foo
.
getConfigFile
();
assertFalse
(
configFile
.
getFile
().
exists
());
}
}
@Test
public
void
endsWithDoubleDot
()
throws
Exception
{
j
.
submit
(
j
.
createWebClient
().
goTo
(
"labelAtom/foo../configure"
).
getFormByName
(
"config"
));
LabelAtom
foo
=
j
.
jenkins
.
getLabelAtom
(
"foo.."
);
XmlFile
configFile
=
foo
.
getConfigFile
();
assertTrue
(
configFile
.
getFile
().
exists
());
assertThat
(
configFile
.
getFile
().
getParentFile
().
getName
(),
equalTo
(
"labels"
));
}
@Test
@Issue
(
"SECURITY-1986"
)
public
void
startsWithDoubleDotBackslash
()
throws
Exception
{
try
{
j
.
submit
(
j
.
createWebClient
().
goTo
(
"labelAtom/..\\foo/configure"
).
getFormByName
(
"config"
));
fail
(
"Should have rejected label."
);
}
catch
(
FailingHttpStatusCodeException
e
)
{
assertThat
(
e
.
getStatusCode
(),
is
(
HttpURLConnection
.
HTTP_BAD_REQUEST
));
LabelAtom
foo
=
j
.
jenkins
.
getLabelAtom
(
"..\\foo"
);
XmlFile
configFile
=
foo
.
getConfigFile
();
assertFalse
(
configFile
.
getFile
().
exists
());
}
}
@Test
@Issue
(
"SECURITY-1986"
)
public
void
endsWithDoubleDotBackslash
()
throws
Exception
{
try
{
j
.
submit
(
j
.
createWebClient
().
goTo
(
"labelAtom/foo..\\/configure"
).
getFormByName
(
"config"
));
fail
(
"Should have rejected label."
);
}
catch
(
FailingHttpStatusCodeException
e
)
{
assertThat
(
e
.
getStatusCode
(),
is
(
HttpURLConnection
.
HTTP_BAD_REQUEST
));
LabelAtom
foo
=
j
.
jenkins
.
getLabelAtom
(
"foo..\\"
);
XmlFile
configFile
=
foo
.
getConfigFile
();
assertFalse
(
configFile
.
getFile
().
exists
());
}
}
@Test
@Issue
(
"SECURITY-1986"
)
public
void
middleDotsSlashes
()
throws
Exception
{
try
{
j
.
submit
(
j
.
createWebClient
().
goTo
(
"labelAtom/foo%2f..%2fgoo/configure"
).
getFormByName
(
"config"
));
fail
(
"Should have rejected label."
);
}
catch
(
FailingHttpStatusCodeException
e
)
{
assertThat
(
e
.
getStatusCode
(),
is
(
HttpURLConnection
.
HTTP_BAD_REQUEST
));
LabelAtom
foo
=
j
.
jenkins
.
getLabelAtom
(
"foo/../goo"
);
XmlFile
configFile
=
foo
.
getConfigFile
();
assertFalse
(
configFile
.
getFile
().
exists
());
}
}
@Test
@Issue
(
"SECURITY-1986"
)
public
void
middleDotsBackslashes
()
throws
Exception
{
try
{
j
.
submit
(
j
.
createWebClient
().
goTo
(
"labelAtom/foo%\\..\\goo/configure"
).
getFormByName
(
"config"
));
fail
(
"Should have rejected label."
);
}
catch
(
FailingHttpStatusCodeException
e
)
{
assertThat
(
e
.
getStatusCode
(),
is
(
HttpURLConnection
.
HTTP_BAD_REQUEST
));
LabelAtom
foo
=
j
.
jenkins
.
getLabelAtom
(
"foo\\..\\"
);
XmlFile
configFile
=
foo
.
getConfigFile
();
assertFalse
(
configFile
.
getFile
().
exists
());
}
}
@Test
(
expected
=
Exception
.
class
)
@Issue
(
"SECURITY-1986"
)
public
void
programmaticCreationInvalidName
()
throws
IOException
{
LabelAtom
label
=
new
LabelAtom
(
"foo/../goo"
);
label
.
save
();
}
@Test
public
void
programmaticCreation
()
throws
IOException
{
LabelAtom
label
=
new
LabelAtom
(
"foo"
);
label
.
save
();
LabelAtom
foo
=
j
.
jenkins
.
getLabelAtom
(
"foo"
);
XmlFile
configFile
=
foo
.
getConfigFile
();
assertTrue
(
configFile
.
getFile
().
exists
());
assertThat
(
configFile
.
getFile
().
getParentFile
().
getName
(),
equalTo
(
"labels"
));
}
@Test
@Issue
(
"SECURITY-1986"
)
public
void
startsWithTripleDotBackslash
()
throws
Exception
{
try
{
j
.
submit
(
j
.
createWebClient
().
goTo
(
"labelAtom/...%2ffoo/configure"
).
getFormByName
(
"config"
));
fail
(
"Should have rejected label."
);
}
catch
(
FailingHttpStatusCodeException
e
)
{
assertThat
(
e
.
getStatusCode
(),
is
(
HttpURLConnection
.
HTTP_BAD_REQUEST
));
LabelAtom
foo
=
j
.
jenkins
.
getLabelAtom
(
".../foo"
);
XmlFile
configFile
=
foo
.
getConfigFile
();
assertFalse
(
configFile
.
getFile
().
exists
());
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录