teler

package module
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Jan 13, 2023 License: Apache-2.0 Imports: 24 Imported by: 5

README

teler-waf

Kitabisa Security GoDoc tests

teler-waf is a comprehensive security solution for Go-based web applications. It acts as an HTTP middleware, providing an easy-to-use interface for integrating IDS functionality with teler IDS into existing Go applications. By using teler-waf, you can help protect against a variety of web-based attacks, such as cross-site scripting (XSS) and SQL injection.

The package comes with a standard net/http.Handler, making it easy to integrate into your application's routing. When a client makes a request to a route protected by teler-waf, the request is first checked against the teler IDS to detect known malicious patterns. If no malicious patterns are detected, the request is then passed through for further processing.

In addition to providing protection against web-based attacks, teler-waf can also help improve the overall security and integrity of your application. It is highly configurable, allowing you to tailor it to fit the specific needs of your application.

See also:

  • kitabisa/teler: Real-time HTTP intrusion detection.
  • dwisiswant0/cox: Cox is bluemonday-wrapper to perform a deep-clean and/or sanitization of (nested-)interfaces from HTML to prevent XSS payloads.

Features

Some core features of teler-waf include:

  • HTTP middleware for Go web applications.
  • Integration of teler IDS functionality.
  • Detection of known malicious patterns using the teler IDS.
    • Common web attacks, such as cross-site scripting (XSS) and SQL injection, etc.
    • CVEs, covers known vulnerabilities and exploits.
    • Bad IP addresses, such as those associated with known malicious actors or botnets.
    • Bad HTTP referers, such as those that are not expected based on the application's URL structure or are known to be associated with malicious actors.
    • Bad crawlers, covers requests from known bad crawlers or scrapers, such as those that are known to cause performance issues or attempt to extract sensitive information from the application.
    • Directory bruteforce attacks, such as by trying common directory names or using dictionary attacks.
  • Configuration options to whitelist specific types of requests based on their URL or headers.
  • Easy integration with many frameworks.
  • High configurability to fit the specific needs of your application.

Overall, teler-waf provides a comprehensive security solution for Go-based web applications, helping to protect against web-based attacks and improve the overall security and integrity of your application.

Install

To install teler-waf in your Go application, run the following command to download and install the teler-waf package:

go get github.com/kitabisa/teler-waf

Usage

Here is an example of how to use teler-waf in a Go application:

  1. Import the teler-waf package in your Go code:
import "github.com/kitabisa/teler-waf"
  1. Use the New function to create a new instance of the Teler type. This function takes a variety of optional parameters that can be used to configure teler-waf to suit the specific needs of your application.
waf := teler.New()
  1. Use the Handler method of the Teler instance to create a net/http.Handler. This handler can then be used in your application's HTTP routing to apply teler-waf's security measures to specific routes.
handler := waf.Handler(http.HandlerFunc(yourHandlerFunc))
  1. Use the handler in your application's HTTP routing to apply teler-waf's security measures to specific routes.
http.Handle("/path", handler)

That's it! You have configured teler-waf in your Go application.

Options:

For a list of the options available to customize teler-waf, see the teler.Options struct.

Examples

Here is an example of how to customize the options and rules for teler-waf:

// main.go
package main

import (
	"net/http"

	"github.com/kitabisa/teler-waf"
	"github.com/kitabisa/teler-waf/request"
	"github.com/kitabisa/teler-waf/threat"
)

var myHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	// This is the handler function for the route that we want to protect
	// with teler-waf's security measures.
	w.Write([]byte("hello world"))
})

var rejectHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	// This is the handler function for the route that we want to be rejected
	// if the teler-waf's security measures are triggered.
	http.Error(w, "Sorry, your request has been denied for security reasons.", http.StatusForbidden)
})

func main() {
	// Create a new instance of the Teler type using the New function
	// and configure it using the Options struct.
	telerMiddleware := teler.New(teler.Options{
		// Exclude specific threats from being checked by the teler-waf.
		Excludes: []threat.Threat{
			threat.BadReferrer,
			threat.BadCrawler,
		},
		// Specify whitelisted URIs (path & query parameters), headers,
		// or IP addresses that will always be allowed by the teler-waf.
		Whitelists: []string{
			`(curl|Go-http-client|okhttp)/*`,
			`^/wp-login\.php`,
			`(?i)Referer: https?:\/\/www\.facebook\.com`,
			`192\.168\.0\.1`,
		},
		// Specify custom rules for the teler-waf to follow.
		Customs: []teler.Rule{
			{
				// Give the rule a name for easy identification.
				Name:      "Log4j Attack",
				// Specify the logical operator to use when evaluating the rule's conditions.
				Condition: "or",
				// Specify the conditions that must be met for the rule to trigger.
				Rules: []teler.Condition{
					{
						// Specify the HTTP method that the rule applies to.
						Method: request.GET,
						// Specify the element of the request that the rule applies to
						// (e.g. URI, headers, body).
						Element: request.URI,
						// Specify the pattern to match against the element of the request.
						Pattern: `\$\{.*:\/\/.*\/?\w+?\}`,
					},
				},
			},
		},
		// Specify the file path to use for logging.
		LogFile: "/tmp/teler.log",
	})

	// Set the rejectHandler as the handler for the telerMiddleware.
	telerMiddleware.SetHandler(rejectHandler)

	// Create a new handler using the handler method of the Teler instance
	// and pass in the myHandler function for the route we want to protect.
	app := telerMiddleware.Handler(myHandler)

	// Use the app handler as the handler for the route.
	http.ListenAndServe("127.0.0.1:3000", app)
}

For more examples of how to use teler-waf or integrate it with any framework, take a look at examples/ directory.

Development

By default, teler-waf caches all incoming requests for 15 minutes & clear them every 20 minutes to improve the performance. However, if you're still customizing the settings to match the requirements of your application, you can disable caching during development by setting the development mode option to true. This will prevent incoming requests from being cached and can be helpful for debugging purposes.

// Create a new instance of the Teler type using
// the New function & enable development mode option.
telerMiddleware := teler.New(teler.Options{
	Development: true,
})
Logs

Here is an example of what the log lines would look like if teler-waf detects a threat on a request:

{"level":"warn","ts":1672261174.5995026,"msg":"bad crawler","id":"654b85325e1b2911258a","category":"BadCrawler","request":{"method":"GET","path":"/","ip_addr":"127.0.0.1:37702","headers":{"Accept":["*/*"],"User-Agent":["curl/7.81.0"]},"body":""}}
{"level":"warn","ts":1672261175.9567692,"msg":"directory bruteforce","id":"b29546945276ed6b1fba","category":"DirectoryBruteforce","request":{"method":"GET","path":"/.git","ip_addr":"127.0.0.1:37716","headers":{"Accept":["*/*"],"User-Agent":["X"]},"body":""}}
{"level":"warn","ts":1672261177.1487508,"msg":"Detects common comment types","id":"75412f2cc0ec1cf79efd","category":"CommonWebAttack","request":{"method":"GET","path":"/?id=1%27%20or%201%3D1%23","ip_addr":"127.0.0.1:37728","headers":{"Accept":["*/*"],"User-Agent":["X"]},"body":""}}

The id is a unique identifier that is generated when a request is rejected by teler-waf. It is included in the HTTP response headers of the request (X-Teler-Req-Id), and can be used to troubleshoot issues with requests that are being made to the website.

For example, if a request to a website returns an HTTP error status code, such as a 403 Forbidden, the teler request ID can be used to identify the specific request that caused the error and help troubleshoot the issue.

Teler request IDs are used by teler-waf to track requests made to its web application and can be useful for debugging and analyzing traffic patterns on a website.

Demo

You are free to use the following site for testing, https://waf.teler.app.

Limitations

Here are some limitations of using teler-waf:

  • Performance overhead: teler-waf may introduce some performance overhead, as the teler-waf will need to process each incoming request. If you have a high volume of traffic, this can potentially slow down the overall performance of your application significantly, especially if you enable the CVEs threat detection. See benchmark below:
$ go test -bench . -cpu=4
goos: linux
goarch: amd64
pkg: github.com/kitabisa/teler-waf
cpu: 11th Gen Intel(R) Core(TM) i9-11900H @ 2.50GHz
BenchmarkTelerDefaultOptions-4               	   44451	     25193 ns/op	    6192 B/op	      97 allocs/op
BenchmarkTelerCommonWebAttackOnly-4          	   47992	     23944 ns/op	    5540 B/op	      88 allocs/op
BenchmarkTelerCVEOnly-4                      	   46393	     23333 ns/op	    5579 B/op	      89 allocs/op
BenchmarkTelerBadIPAddressOnly-4             	   49666	     22309 ns/op	    5395 B/op	      85 allocs/op
BenchmarkTelerBadReferrerOnly-4              	   44422	     23812 ns/op	    5657 B/op	      88 allocs/op
BenchmarkTelerBadCrawlerOnly-4               	   48159	     22064 ns/op	    5601 B/op	      85 allocs/op
BenchmarkTelerDirectoryBruteforceOnly-4      	   48697	     21877 ns/op	    5596 B/op	      85 allocs/op
BenchmarkTelerCustomRule-4                   	   50032	     21905 ns/op	    5391 B/op	      85 allocs/op
BenchmarkTelerWithoutCommonWebAttack-4       	   44625	     24400 ns/op	    5996 B/op	      92 allocs/op
BenchmarkTelerWithoutCVE-4                   	   43975	     24180 ns/op	    5983 B/op	      91 allocs/op
BenchmarkTelerWithoutBadIPAddress-4          	   45967	     24906 ns/op	    6110 B/op	      95 allocs/op
BenchmarkTelerWithoutBadReferrer-4           	   42807	     24173 ns/op	    5938 B/op	      92 allocs/op
BenchmarkTelerWithoutBadCrawler-4            	   44853	     24434 ns/op	    5933 B/op	      95 allocs/op
BenchmarkTelerWithoutDirectoryBruteforce-4   	   43575	     24890 ns/op	    6137 B/op	      95 allocs/op
PASS
ok  	github.com/kitabisa/teler-waf	18.283s

Note: It's important to note that the benchmarking results may vary and may not be consistent. Those results were obtained when there were >1.5k CVE templates and the teler-resources dataset may have increased since then, which may impact the results.

  • Configuration complexity: Configuring teler-waf to suit the specific needs of your application can be complex, and may require a certain level of expertise in web security. This can make it difficult for those who are not familiar with application firewalls and IDS systems to properly set up and use teler-waf.
  • Limited protection: teler-waf is not a perfect security solution, and it may not be able to protect against all possible types of attacks. As with any security system, it is important to regularly monitor and maintain teler-waf to ensure that it is providing the desired level of protection.
Known Issues

To view a list of known issues with teler-waf, please filter the issues by the "known-issue" label.

License

This program is developed and maintained by members of Kitabisa Security Team, and this is not an officially supported Kitabisa product. This program is free software: you can redistribute it and/or modify it under the terms of the Apache license. Kitabisa teler-waf and any contributions are copyright © by Dwi Siswanto 2022-2023.

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Condition

type Condition struct {
	// Method is the HTTP method to match against.
	// It is of type request.Method, which is a type alias for string.
	Method request.Method

	// Element is the request element to match.
	// These element are defined in the request.Element type.
	Element request.Element

	// Pattern is the regular expression to match against the element.
	Pattern string
	// contains filtered or unexported fields
}

Condition specifies a request element to match and a pattern to match against the element.

type Options

type Options struct {
	// Excludes is a list of threat types to exclude from the security checks.
	// These threat types are defined in the threat.Threat type.
	Excludes []threat.Threat

	// Whitelists is a list of regular expressions that match request elements
	// that should be excluded from the security checks. The request elements
	// that can be matched are request URI (path and query parameters), HTTP headers,
	// or client IP address.
	Whitelists []string

	// Customs is a list of custom security rules to apply to incoming requests.
	// These rules can be used to create custom security checks or to override
	// the default security checks provided by teler-waf.
	Customs []Rule

	// LogFile is the file path for the log file to store the security logs.
	// If LogFile is specified, log messages will be written to the specified
	// file in addition to stderr (if NoStderr is false).
	LogFile string

	// NoStderr is a boolean flag indicating whether or not to suppress log messages
	// from being printed to the standard error (stderr) stream. When set to true, log messages
	// will not be printed to stderr. If set to false, log messages will be printed to stderr.
	// By default, log messages are printed to stderr (false).
	NoStderr bool

	// Development is a boolean flag that determines whether the request is cached or not.
	// By default, development mode is disabled (false) or requests will cached.
	Development bool
}

Options is a struct for specifying configuration options for the teler.Teler middleware.

type Rule

type Rule struct {
	// Name is the name of the rule.
	Name string

	// Condition specifies the logical operator to use when evaluating the
	// rule's conditions. Valid values are "and" and "or".
	Condition string

	// Rules is a list of conditions that must be satisfied for the rule to
	// be triggered. Each condition specifies a request element to match and
	// a pattern to match against the element.
	Rules []Condition
}

Rule is custom security rules to apply to incoming requests.

type Teler

type Teler struct {
	// contains filtered or unexported fields
}

Teler is a middleware that helps setup a few basic security features

func New

func New(opts ...Options) *Teler

New constructs a new Teler instance with the supplied options.

Example (Custom)
var myHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	_, _ = w.Write([]byte("hello world"))
})

telerMiddleware := New(Options{
	Excludes: []threat.Threat{
		threat.BadReferrer,
		threat.BadCrawler,
	},
	Whitelists: []string{
		`(curl|Go-http-client|okhttp)/*`,
		`^/wp-login\.php`,
		`(?i)Referer: https?:\/\/www\.facebook\.com`,
		`192\.168\.0\.1`,
	},
	Customs: []Rule{
		{
			Name:      "Log4j Attack",
			Condition: "or",
			Rules: []Condition{
				{
					Method: request.GET,
					// if Method is not set or invalid, defaulting to request.GET.
					Element: request.URI,
					// you can use request.Any: it useful when you want to
					// match against multiple elements of the request at once,
					// rather than just a single element.
					Pattern: `\$\{.*:\/\/.*\/?\w+?\}`,
				},
			},
		},
	},
	LogFile: "/tmp/teler.log",
})

app := telerMiddleware.Handler(myHandler)
go func() {
	_ = http.ListenAndServe("127.0.0.1:3000", app)
}()
Output:

Example (Default)
var myHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	_, _ = w.Write([]byte("hello world"))
})

telerMiddleware := New()

app := telerMiddleware.Handler(myHandler)
go func() {
	_ = http.ListenAndServe("127.0.0.1:3000", app)
}()
Output:

Example (SetHandler)
var forbidden = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	http.Error(w, "We're sorry, but your request has been denied for security reasons.", http.StatusForbidden)
})

var myHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	_, _ = w.Write([]byte("hello world"))
})

telerMiddleware := New()
telerMiddleware.SetHandler(forbidden)

app := telerMiddleware.Handler(myHandler)
go func() {
	_ = http.ListenAndServe("127.0.0.1:3000", app)
}()
Output:

func (*Teler) Analyze

func (t *Teler) Analyze(w http.ResponseWriter, r *http.Request) error

Analyze runs the actual checks.

func (*Teler) Handler

func (t *Teler) Handler(h http.Handler) http.Handler

Handler implements the http.HandlerFunc for integration with the standard net/http library.

func (*Teler) HandlerFuncWithNext

func (t *Teler) HandlerFuncWithNext(w http.ResponseWriter, r *http.Request, next http.HandlerFunc)

HandlerFuncWithNext is a special implementation for Negroni, but could be used elsewhere.

func (*Teler) SetHandler

func (t *Teler) SetHandler(handler http.Handler)

SetHandler sets the handler to call when the teler rejects a request.

type Threat

type Threat struct {
	// contains filtered or unexported fields
}

Threat defines what threat category should be excluded and what is the corresponding data.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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