xss

package module
v0.0.0-...-7a0dab8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 29, 2019 License: MIT Imports: 12 Imported by: 8

README

Xss Middleware

XssMw is an middleware written in Golang for the Gin web framework. Although, it should be useable with any Go web framework which utilizes Golang's "net/http" native library in a similiar way to Gin.

The idea behind XssMw is to "auto remove XSS" from user submitted input.

It's applied on http GET, POST and PUT Requests only

The XSS filtering is performed by HTML sanitizer Bluemonday.

The default is to the strictest policy - StrictPolicy()

How To Use it?

Using the defaults, It will skip filtering for a field named 'password' but will run the filter on everything else. Uses the Bluemonday strictest policy - StrictPolicy()

package main

import "gopkg.in/gin-gonic/gin.v1"
import "github.com/dvwright/xss-mw"

func main() {
    r := gin.Default()

    // include as standard middleware
    var xssMdlwr xss.XssMw
    r.Use(xssMdlwr.RemoveXss())

    r.GET("/ping", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })
    r.Run() // listen and serve on 0.0.0.0:8080
}

Using some config options, here It will skip filtering for a fields named 'password', "create_date" and "token" but will run the filter on everything else.

Uses Bluemonday UGCPolicy

package main

import "gopkg.in/gin-gonic/gin.v1"
import "github.com/dvwright/xss-mw"

func main() {
    r := gin.Default()

    xssMdlwr := &xss.XssMw{
            FieldsToSkip: []string{"password", "create_date", "token"},
            BmPolicy:     "UGCPolicy",
    }
    r.Use(xssMdlwr.RemoveXss())

    r.GET("/ping", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })
    r.Run() // listen and serve on 0.0.0.0:8080
}

Data

Currently, it removes (deletes) all HTML and malicious detected input from user input on

the submitted request to the server.

It handles three Request types:

  • JSON requests - Content-Type application/json

  • Form Encoded - Content-Type application/x-www-form-urlencoded

  • Multipart Form Data - Content-Type multipart/form-data

A future plan is have a feature to store all user submitted data intact and have the option to

filter it out on the http Response, so you can choose your preference. - in other words - data would be stored in the database as it was submitted and removed in Responses back to the user. pros: data integrity, cons: XSS exploits still present

NOTE: This is Beta level code with minimal actual real world usage

Contributing

You are welcome to contribute to this project.

Please update/add tests as appropriate.

Send pull request against the Develop branch.

Please use the same formatting as the Go authors. Run code through gofmt before submitting.

Thanks

Misc

Thanks to

https://github.com/goware/jsonp

https://github.com/appleboy/gin-jwt/tree/v2.1.1

Whose source I read throughly to aid in writing this

and of course

https://github.com/microcosm-cc/bluemonday

and the gin middleware

and

https://static.googleusercontent.com/intl/hu/about/appsecurity/learning/xss/

for inspiring me to to look for and not finding a framework, so attempting to write one.

A note on manually escaping input Writing your own code for escaping input and then properly and consistently applying it is extremely difficult. We do not recommend that you manually escape user-supplied data. Instead, we strongly recommend that you use a templating system or web development framework that provides context-aware auto-escaping.

Documentation

Overview

XssMw provides an "auto remove XSS" from all user submitted input.

It's applied on POST, PUT, and GET Requests only.

We currently support three Request types:

* JSON requests - Content-Type application/json

* Form Encoded - Content-Type application/x-www-form-urlencoded

* Multipart Form Data - Content-Type multipart/form-data

XSS filtering is performed by HTML sanitizer https://github.com/microcosm-cc/bluemonday

The two packaged policies are available, UGCPolicy or StrictPolicy

The default is to the strictest policy - StrictPolicy()

use of UGCPolicy is untested at this time

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type XssMw

type XssMw struct {
	// List of fields to not filter. i.e. password, created_on, created_at, etc
	// password is set to skip by the system i.e. FieldsToSkip = []string{"password", "cre_date"}
	FieldsToSkip []string

	// Bluemonday comes with two default policies
	// Two options StrictPolicy // the default
	//             UGCPolicy
	// or you can specify you own policy
	// define it somewhere in your package so that you can call it here
	// see https://github.com/microcosm-cc/bluemonday/blob/master/policies.go
	// This must contain one of three possible settings:
	//             StrictPolicy // the default
	//             UGCPolicy
	//             New          // Specify your own policy - not yet supported
	BmPolicy string
}

Config struct for passing options

func (*XssMw) ConstructJson

func (mw *XssMw) ConstructJson(xmj XssMwJson, buff bytes.Buffer) bytes.Buffer

De-constructs the http request body removes undesirable content keeps the good content to construct returns the cleaned http request Map to Bytes (struct to json string...)

func (*XssMw) GetBlueMondayPolicy

func (mw *XssMw) GetBlueMondayPolicy() *bluemonday.Policy

Get which Bluemonday policy

func (*XssMw) HandleGETRequest

func (mw *XssMw) HandleGETRequest(c *gin.Context) error

HandleGETRequest handles get request

func (*XssMw) HandleJson

func (mw *XssMw) HandleJson(c *gin.Context) error

Handles request Content-Type = application/json

The four types of data handled.

* 1st type filter - basic key:value - most common

map[string]interface {}{"updated_by":"534", "updated_at":"1480831130", "id":"1", "name":"foo"}

* 2nd type an id with associated ids list

map[string]interface {}{"project_id":"1", "talent_ids":[]interface {}{"1", "4", "8"}}

- NOTE changes from ["1", "4", "8"] to [1,4,8]

* 3rd type an "array of records"

[]interface {}{
   map[string]interface {}{"name":"asd", "url":"/data/1/as",
                           "user_id":"537", "username":"Test User ©", "created_by":"537", "id":"286",
                           "fqdn":"audio class", "project_id":"1", "path":"/tmp/store/1/as",
                           "updated_at":"1480791630", "status":"NEW",
                           "updated_by":"537", "created_at":"1480450694"},
   map[string]interface {}{"name":"asd2", "url":"/data/2/as", etc... },
   map[string]interface {}{"name":"asd3", "url":"/data/3/as", etc... },
   ...
}

* 4th type "complex array/nested records"

 map[string]interface {}{
     "id":"1",
     "users":[]interface {}{
          map[string]interface {}{"id":"1", "flt":"1.345", "user":"TestUser1", "email":"testUser1@example.com", "password":"!@$%^ASDF<html>1", "comment":"<img src=x onerror=alert(0)>", "cre_at":"1481017167"},
          map[string]interface {}{"cre_at":"1481017167", "id":"2", "flt":"2.345", "user":"TestUser2", "email":"testUser2@example.com", "password":"!@$%^ASDF<html>2", "comment":"<img src=x onerror=alert(0)>"}
     }
}

func (*XssMw) HandleMultiPartFormData

func (mw *XssMw) HandleMultiPartFormData(c *gin.Context, ctHdr string) error

Handles Content-Type "multipart/form-data"

skips sanitizing if file upload

Content-Disposition: form-data; name="" filename=""

tries to determine Content-type for form data file upload, defaults to application/octet-stream if unknown

handles basic form field POST request for example:

--3af5c5b7adcb2142f404a8e1ce280c47c58e563e3d4c1e172490737c9909
Content-Disposition: form-data; name="flt"

2.345
--3af5c5b7adcb2142f404a8e1ce280c47c58e563e3d4c1e172490737c9909
Content-Disposition: form-data; name="user"

TestUser
--3af5c5b7adcb2142f404a8e1ce280c47c58e563e3d4c1e172490737c9909
Content-Disposition: form-data; name="email"

testUser@example.com
--3af5c5b7adcb2142f404a8e1ce280c47c58e563e3d4c1e172490737c9909
281         }
Content-Disposition: form-data; name="password"

!@$%^ASDF
--3af5c5b7adcb2142f404a8e1ce280c47c58e563e3d4c1e172490737c9909
Content-Disposition: form-data; name="comment"

&gt;&#39;&gt;\&#34;&gt;
--3af5c5b7adcb2142f404a8e1ce280c47c58e563e3d4c1e172490737c9909
Content-Disposition: form-data; name="cre_at"

1481017167
--3af5c5b7adcb2142f404a8e1ce280c47c58e563e3d4c1e172490737c9909
Content-Disposition: form-data; name="id"

2
--3af5c5b7adcb2142f404a8e1ce280c47c58e563e3d4c1e172490737c9909--

NOTE: form-data name 'password' is skipped (not sanitized)

func (*XssMw) HandleXFormEncoded

func (mw *XssMw) HandleXFormEncoded(c *gin.Context) error

Handles Content-Type "application/x-www-form-urlencoded"

Has been tested with basic param=value form fields only:

comment=<img src=x onerror=alert(0)>
&cre_at=1481017167
&email=testUser@example.com
&flt=2.345
&id=2
&password=TestPass
&user=TestUser

has not been tested on file/data uploads

func (*XssMw) RemoveXss

func (mw *XssMw) RemoveXss() gin.HandlerFunc

XssMw implements the Gin Middleware interface.

func (*XssMw) SetRequestBodyJson

func (mw *XssMw) SetRequestBodyJson(c *gin.Context, buff bytes.Buffer) error

encode processed body back to json and re-set http request body

func (*XssMw) XssRemove

func (mw *XssMw) XssRemove(c *gin.Context) error

Receives an http request object, processes the body, removing html and returns the request.

Headers (and other parts of the request) are passed through unaltered.

Request Method must be "POST" or "PUT"

type XssMwJson

type XssMwJson map[string]interface{}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL