Skip to main content

Insecure Processing of Data

This category covers the following issues:

Fixing Cross-Site Scripting

About XSS

What is Cross-Site Scripting?

Cross-site scripting (XSS) is a type of security vulnerability that allows attackers to inject malicious code into web pages viewed by other users. This occurs when an application fails to properly sanitize user input and injects untrusted data into a web page without validating or encoding it.

XSS attacks can occur in different forms, such as reflected, stored, or DOM-based, and can affect various types of web applications, including social media, e-commerce, and online banking sites.

Attackers can use various techniques, such as phishing emails, web forms, or malicious links, to trick users into visiting or interacting with web pages that contain malicious code.

Check out this video for a high-level explanation:

What is the impact of Cross-Site Scripting?

Cross-site scripting (XSS) can lead to various security threats and risks, such as:

  • Information theft: XSS attacks can steal sensitive information, such as login credentials, credit card details, or other personally identifiable information, by injecting malicious code that collects and transmits user data to attackers.
  • Account hijacking: XSS attacks can hijack user sessions by injecting malicious code that takes over user sessions, allowing attackers to perform unauthorized actions on the website or gain access to user accounts.
  • Data tampering: XSS attacks can modify or delete data on a website by injecting malicious code that alters the content of web pages, leading to data tampering, data corruption, or other types of malicious activities.
  • Malware distribution: XSS attacks can distribute malware by injecting malicious code that downloads and installs malicious software on the user's computer, leading to malware infections or other types of cyber attacks.

Overall, XSS attacks can compromise the confidentiality, integrity, and availability of data, leading to a range of security threats and risks.

How to prevent Cross-Site Scripting?

To prevent XSS vulnerabilities, you can take the following steps:

  • Input validation and sanitization: Ensure that all user input is validated and sanitized before being used to generate web pages or manipulate other data. Input validation should include validating the data type, length, and format, and filtering out any special characters that could be used to inject malicious code.
  • Output encoding: Encode all output to protect against XSS attacks. Use output encoding techniques such as HTML entity encoding, URL encoding, and JavaScript encoding to encode user input and output to the browser.
  • Use security headers: Implement security headers to protect against XSS attacks, such as Content-Security-Policy (CSP) and X-XSS-Protection. CSP can help prevent XSS attacks by allowing only trusted sources of content to be loaded on a page, while X-XSS-Protection can help prevent the browser from rendering pages that contain malicious scripts.
  • Session management: Implement secure session management mechanisms, such as session cookies, to protect against session hijacking and other attacks.
  • Secure coding practices: Use secure coding practices to prevent XSS vulnerabilities. This includes using libraries and frameworks that are designed to prevent XSS attacks, testing code for vulnerabilities, and using secure coding practices such as input validation and output encoding.
  • Regular security audits: Regularly audit your system for security vulnerabilities, including XSS vulnerabilities. Use automated tools and manual testing to identify potential issues and fix them before they can be exploited.

References

Taxonomies

Explanation & Prevention

Training

Cross-Site Scripting (XSS) via unescaped data in HTML Templates

Several built-in functions in the html/template library do not escape data. If user input is provided to those functions, XSS vulnerabilities can occur.

Rule-specific references:

Option A: Use template.HTMLEscapeString instead of template.HTML

template.HTMLEscapeString encodes HTML special characters to make sure that untrusted data is safe.

  1. Go through the issues that GuardRails identified in the PR/MR.

  2. Locate the vulnerable pattern (example below):

    const tpl = `
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>{{.Title}}</title>
    </head>
    <body>
    {{.Body}}
    </body>
    </html>
    `
    func renderer(w http.ResponseWriter, req *http.Request) {
    t := template.Must(template.New("ex").Parse(tpl))
    v := map[string]interface{}{
    "Title": "Test <b>World</b>",
    "Body": template.HTML("<h1>" + req.FormValue("title") + "</h1>"),
    }
    t.Execute(w, v)
    }
  3. Replace template.HTML with template.HTMLEscapeString

    func renderer(w http.ResponseWriter, req *http.Request) {
    t := template.Must(template.New("ex").Parse(tpl))
    v := map[string]interface{}{
    "Title": "Test <b>World</b>",
    "Body": template.HTMLEscapeString("<h1>" + req.FormValue("title") + "</h1>"),
    }
    t.Execute(w, v)
    }
  4. Test it

  5. Ship it 🚢 and relax 🌴

Option B: Use template.JSEscapeString instead of template.JS

template.JSEscapeString encodes special ASCII characters to escaped Unicode sequences

  1. Go through the issues that GuardRails identified in the PR/MR.

  2. Locate the vulnerable pattern (example below):

    func renderer(w http.ResponseWriter, req *http.Request) {
    t := template.Must(template.New("ex").Parse(tpl))
    v := map[string]interface{}{
    "Title": "Test <b>World</b>",
    "Body": fmt.Sprintf(`<script>alert("%s")</script>`, template.JS(req.FormValue("message"))),
    }
    t.Execute(w, v)
    }
  3. Replace template.JS with template.JSEscapeString

    func renderer(w http.ResponseWriter, req *http.Request) {
    t := template.Must(template.New("ex").Parse(tpl))
    v := map[string]interface{}{
    "Title": "Test <b>World</b>",
    "Body": fmt.Sprintf(`<script>alert("%s")</script>`, template.JSEscapeString(req.FormValue("message"))),
    }
    t.Execute(w, v)
    }
  4. Test it

  5. Ship it 🚢 and relax 🌴

Preventing DoS via decompression bomb

About Data Amplification

What is Data Amplification?

In applications, a common data amplification attack is called zip bomb, also known as a zip of death, is a type of denial-of-service (DoS) attack in which an attacker creates a compressed file (usually a ZIP file) that is designed to be extremely small in size, but when uncompressed, it "explodes" into an extremely large amount of data. The result is a file that appears to contain a massive amount of data, but is actually mostly made up of repeated patterns of the same small amount of data. The goal of a zip bomb is to overwhelm and crash the system or application that attempts to decompress or open the file, effectively causing a denial-of-service attack.

What is the impact of Data Amplification?

Some of the potential impacts of a data amplification attack are:

  • Service disruption: A successful data amplification attack can result in a DoS attack, which can cause the targeted system or network to become unavailable or unusable.
  • Network congestion: A data amplification attack can flood a network with a large volume of traffic, which can cause network congestion and slow down the performance of other applications and services.
  • Increased costs: A successful data amplification attack can result in increased costs for an organization, such as increased bandwidth and infrastructure costs to handle the large volume of traffic.

How to prevent Data Amplification?

To prevent data amplification attacks, such as zip bomb attacks, you can take the following steps:

  • Limit file size: Configure systems and applications to limit the size of files that can be decompressed. This can prevent large files from being decompressed and overwhelming the system.
  • Use sandboxing: Use sandboxing to isolate the decompression process from the rest of the system. This can limit the impact of a zip bomb attack and prevent it from affecting the rest of the system.
  • Use antivirus software: Use antivirus software that can detect and block compressed files that are known to be associated with zip bombs.

References

Taxonomies

Explanation & Prevention

This rule detects the usage of archive files could lead to crashes or DoS in the system reading it.

Rule-specific references:

Option A: Limit the size of the buffer while reading

The function io.Copy copies from src to dst until EOF is reached so we have to prevent this behavior by using io.CopyN with buffer size limitation.

  1. Go through the issues that GuardRails identified in the Pull Request

  2. Locate the following vulnerable pattern:

    func decompress(w http.ResponseWriter, req *http.Request) {
    file, _, err := req.FormFile("file")
    if err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
    }
    src, err := zlib.NewReader(file)
    if err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
    }
    dest := os.Open("/tmp/decompression")
    _, err = io.Copy(dest, src)
    if err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
    }
    dest.Close()
    r.Close()
    }
  3. Replace io.Copy with io.CopyN

    func decompress(w http.ResponseWriter, req *http.Request) {
    src, _, err := req.FormFile("file")
    if err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
    }
    r, err := zlib.NewReader(src)
    if err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
    }
    dest, err := os.Open("/tmp/decompression")
    if err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
    }
    written, err := io.CopyN(dest, r, 2*1024*1024)
    if err != nil {
    if written == 2*1024*1024 && err != io.EOF {
    http.Error(w, "Exceed 2MB archive file size limitation!", http.StatusInternalServerError)
    } else {
    http.Error(w, err.Error(), http.StatusInternalServerError)
    }
    }
    dest.Close()
    r.Close()
    }
  4. Test it

  5. Ship it 🚢 and relax 🌴

Fixing Integer Overflows

About Integer Overflows

What is an Integer Overflow?

Integer overflows are a type of vulnerability that occurs when the result of an arithmetic operation exceeds the range of values that can be represented by a particular data type, such as an integer.

In other words, an integer overflow occurs when the result of an operation is too large to be represented by the data type that stores it.

For example, if an integer data type is defined with a range of -128 to 127 and a program attempts to add 130 to a value of 127, an integer overflow will occur, and the value will "wrap around" to become -127. This can lead to unexpected and potentially dangerous behavior, such as crashes, incorrect calculation results, or security vulnerabilities.

Check out this video for a high-level explanation:

What is the impact of Integer Overflows?

Integer overflow vulnerabilities can be exploited by attackers to perform a variety of attacks, such as:

  • Buffer overflows: An integer overflow can be used to overwrite memory outside the bounds of an array, which can result in a buffer overflow vulnerability. This can allow an attacker to execute arbitrary code, modify data, or crash the program.
  • Denial-of-service (DoS) attacks: An integer overflow can be used to cause a program to consume excessive resources or crash, resulting in a DoS attack.
  • Logic bypasses: An integer overflow can be used to bypass security checks, such as input validation, authentication, or access control. This can allow an attacker to access unauthorized resources or perform actions that they are not authorized to perform.

How to prevent Integer Overflows?

To prevent integer overflow vulnerabilities, here are some best practices to follow:

  • Use appropriate data types: Use appropriate data types that can represent the range of values that are expected to be processed. For example, use a larger integer data type, such as a "long" instead of an "int", to avoid overflowing the range of values.
  • Bounds checking: Implement bounds checking to prevent arithmetic operations from exceeding the range of values that can be represented by a data type. This can involve checking the range of values before performing arithmetic operations or using libraries or tools that provide built-in checks.
  • Input validation: Validate all user input to ensure that it is of the expected data type and within the acceptable range of values. This can prevent attackers from manipulating input values to cause integer overflows.

References

Taxonomies

Training

Integer overflow via the misuse of strconv.Atoi

The size of the int type is dependent on the architecture that the program is compiled for. For a 32-bit architecture, an int will be the same size as an int32, and for a 64-bit architecture, an int will be the same size as an int64.

This presents a problem for strconv.Atoi. Its return type is int, which means on 64-bit systems it will return a 64-bit integer. However, this means we cannot cast the result into a 32-bit integer as casting an int to an int32 could result in an integer overflow.

Rule-specific references:

Option A: Use strconv.ParseInt or strconv.ParseUint instead

strconv.ParseInt or strconv.ParseUint parse strings into an integer, just like strconv.Atoi. However, these functions also ask for the bit size of the result as a function parameter. This allows smaller ints to be parsed and cast safely.

  1. Go through the issues that GuardRails identified in the PR/MR.

  2. Locate the vulnerable pattern (example below):

    func transfer(w http.Response, req *http.Request) {
    amount, err := strconv.Atoi(req.FormValue("amount"))
    if err != nil {
    panic(err)
    }
    value := int32(amount)
    account.transfer_money(value)
    }
  3. Replace vulnerable pattern with strconv.ParseInt or strconv.ParseUint

    func transfer(w http.Response, req *http.Request) {
    amount, err := strconv.ParseInt(req.FormValue("amount"), 10, 32)
    if err != nil {
    panic(err)
    }
    value := int32(amount)
    account.transfer_money(value)
    }
  4. Test it

  5. Ship it 🚢 and relax 🌴

Fixing server-side request forgery (SSRF)

About SSRF

What is Server-Side Request Forgery (SSRF)?

Server-Side Request Forgery (SSRF) is a type of web application vulnerability that occurs when an attacker can manipulate the server-side code to make it perform unauthorized HTTP requests to other web applications. SSRF attacks can allow an attacker to send requests from the vulnerable server to internal or external network resources, which can result in data leaks, access to sensitive data or even compromise the entire network.

An SSRF attack typically involves an attacker tricking a server into making a request to a specific URL that the attacker controls. The attacker may do this by manipulating the parameters of a URL or by using other techniques to inject malicious code into the server-side code.

What is the impact of Server-Side Request Forgery (SSRF)?

Attackers can use this vulnerability to perform a variety of attacks, such as:

  • Information disclosure: The attacker can use an SSRF attack to access sensitive data, such as configuration files, internal documentation or even credentials, which can be used to compromise the entire network.
  • Port scanning: The attacker can use an SSRF attack to scan the network for open ports, which can be used to identify potential vulnerabilities in the system.
  • Bypassing authentication and authorization: An SSRF attack can be used to bypass authentication and authorization controls by sending requests to internal services that do not enforce these controls.
  • Exploiting internal APIs: An SSRF attack can be used to exploit unprotected internal APIs, which can result in unauthorized access to sensitive information or actions that the user is not authorized to perform.
  • Denial-of-service (DoS): The attacker can use an SSRF attack to flood the targeted web application with requests or to perform a request to a resource that is not available, causing the application to crash or slow down.

How to prevent Server-Side Request Forgery (SSRF)?

Here are some best practices to prevent SSRF attacks:

  • Use secure APIs: Use secure APIs that do not allow arbitrary URLs to be passed as parameters. This can prevent attackers from manipulating the server-side code to perform unauthorized HTTP requests.
  • Input validation and sanitization: Validate and sanitize all user input, especially for URLs, to ensure that they are valid and safe. This can prevent attackers from injecting malicious URLs into the server-side code.
  • Access controls: Implement access controls to limit access to only authorized users. This can prevent attackers from exploiting unprotected internal APIs or cloud infrastructure.
  • Server hardening: Harden servers by removing unnecessary software and services, and limiting access to administrative interfaces. This can prevent attackers from exploiting vulnerabilities in the server-side code or gaining access to sensitive information.
  • Network segmentation: Use network segmentation to prevent web applications from accessing internal resources or those that they do not need to access. This can limit the impact of an SSRF attack by preventing the attacker from accessing sensitive resources.

References

Taxonomies

Explanation & Prevention

Training

This rule detects user-controlled data being passed into an HTTP request URL in a way that leads to Server-side request forgery (SSRF).

Rule-specific references:

Option A: Use safeurl package

safeurl implements a safeurl.Client wrapper around Go's native net/http.Client and performs validation on the incoming request against the configured allow and block lists.

  1. Go through the issues that GuardRails has identified

  2. Locate the vulnerable pattern (example below):

    func handler(w http.ResponseWriter, req *http.Request) {
    u := req.FormValue("url")
    client := &http.Client{}
    resp, err := client.Get(u)
    if err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
    return
    }
    defer resp.Body.Close()
    body, err = ioutil.ReadAll(resp.Body)
    if err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
    return
    }
    }
  3. Implement a secure version using the safeurl package:

    import (
    "github.com/doyensec/safeurl"
    )

    func handler(w http.ResponseWriter, req *http.Request) {
    u := req.FormValue("url")
    config := safeurl.GetConfigBuilder().
    SetAllowedHosts("example.com").
    Build()
    client := safeurl.Client(config)
    resp, err := client.Get(u)
    if err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
    return
    }
    defer resp.Body.Close()
    body, err = ioutil.ReadAll(resp.Body)
    if err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
    return
    }
    }
  4. Test it

  5. Ship it 🚢 and relax 🌴