Skip to content

Commit

Permalink
fix: block arbitrary file index (#2497)
Browse files Browse the repository at this point in the history
  • Loading branch information
bzp2010 committed Jul 6, 2022
1 parent 36f1ba9 commit bfc9c31
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 9 deletions.
41 changes: 41 additions & 0 deletions api/internal/filter/invalid_request.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package filter

import (
"net/url"
"strings"

"github.com/gin-gonic/gin"
)

// InvalidRequest provides a filtering mechanism for illegitimate requests
func InvalidRequest() gin.HandlerFunc {
return func(c *gin.Context) {
if !checkURL(c.Request.URL) {
c.AbortWithStatus(403)
}
c.Next()
}
}

func checkURL(url *url.URL) bool {
if strings.Contains(url.Path, "..") {
return false
}
return true
}
30 changes: 30 additions & 0 deletions api/internal/filter/invalid_request_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package filter

import (
"net/url"
"testing"

"github.com/stretchr/testify/assert"
)

func TestURLCheck_double_dot(t *testing.T) {
assert.Equal(t, false, checkURL(&url.URL{Path: "../../../etc/hosts"}))
assert.Equal(t, false, checkURL(&url.URL{Path: "/../../../etc/hosts"}))
assert.Equal(t, true, checkURL(&url.URL{Path: "/etc/hosts"}))
}
7 changes: 5 additions & 2 deletions api/internal/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,11 @@ func SetUpRouter() *gin.Engine {
}
r := gin.New()
logger := log.GetLogger(log.AccessLog)
r.Use(gzip.Gzip(gzip.DefaultCompression))
r.Use(filter.CORS(), filter.RequestId(), filter.IPFilter(), filter.RequestLogHandler(logger), filter.SchemaCheck(), filter.RecoverHandler(), filter.Authentication())
// security
r.Use(filter.RequestLogHandler(logger), filter.IPFilter(), filter.InvalidRequest(), filter.Authentication())

// misc
r.Use(gzip.Gzip(gzip.DefaultCompression), filter.CORS(), filter.RequestId(), filter.SchemaCheck(), filter.RecoverHandler())
r.Use(static.Serve("/", static.LocalFile(filepath.Join(conf.WorkDir, conf.WebDir), false)))
r.NoRoute(func(c *gin.Context) {
c.File(fmt.Sprintf("%s/index.html", filepath.Join(conf.WorkDir, conf.WebDir)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package gzip
package middlewares_test

import (
"net/http"

"github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo"

"github.com/apisix/manager-api/test/e2e/base"
)

var _ = ginkgo.Describe("Gzip enable", func() {
ginkgo.It("get index.html", func() {
var _ = Describe("Gzip enable", func() {
It("get index.html", func() {
base.RunTestCase(base.HttpTestCase{
Object: base.ManagerApiExpect(),
Method: http.MethodGet,
Expand Down
42 changes: 42 additions & 0 deletions api/test/e2e/middlewares/invalid_request_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package middlewares_test

import (
"net/http"

. "github.com/onsi/ginkgo"

"github.com/apisix/manager-api/test/e2e/base"
)

var _ = Describe("Invalid Request", func() {
It("double dot in URL path (arbitrary file index)", func() {
base.RunTestCase(base.HttpTestCase{
Object: base.ManagerApiExpect(),
Method: http.MethodGet,
Path: "/../../../../etc/hosts",
ExpectStatus: http.StatusForbidden,
})
base.RunTestCase(base.HttpTestCase{
Object: base.ManagerApiExpect(),
Method: http.MethodGet,
Path: "/.%2e/%2e%2e/../etc/hosts",
ExpectStatus: http.StatusForbidden,
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package gzip_test
package middlewares_test

import (
"testing"
Expand All @@ -23,7 +23,7 @@ import (
. "github.com/onsi/gomega"
)

func TestGzip(t *testing.T) {
func TestMiddlewares(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "gzip suite")
RunSpecs(t, "Middlewares Suite")
}

0 comments on commit bfc9c31

Please sign in to comment.