-
-
Notifications
You must be signed in to change notification settings - Fork 3.8k
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
Able to inject arbitrary commands when using "Run external program on torrent completion" #10925
Comments
This exploit can be triggered without user interaction if we're receiving a feed from RSS. The user won't notice the fishy name until it's too late. |
Ping @Piccirello |
Thanks for pinging me, this is really interesting. Especially with the RSS feed attack vector. We currently take precautions to prevent things like XSS from torrent names, so I would consider this issue as credible. |
Some quick reading on Also pinging @glassez @sledgehammer999 in case they're interested |
Seeing the available runExternalProgram parameters, we only need to sanitize the torrent name parameter and the current tracker parameter. |
Hi @Piccirello thanks for looking at this issue. Other way of injecting a command could involve using an escape character like \ at the end of the name, so a parameter like "name" would become "name\". This means the last quote is ignored. Try the following example in bash: This will execute firefox. Greetings |
Another method, which will do the trick on Unix systems (/bin/sh is called from QProcess::startDetached on line 339). I haven't tested it but it will probably work:
More information: https://portswigger.net/web-security/os-command-injection Banned characters should at least be $, ", ', ` and newlines. This is independent of quoting the arguments, which should also be done. Greetings |
This is not the case when using single quotes, as I understand it. Executing
I agree with this, with one caveat- I think we may want to quote the category name. It's specified by the user, but could have side effects if the user uses special characters. Categories must match the regex
I'm really not sure we have to do any of this if we use single quotes. |
Ok, didn't really notice the comment about single quotes. :) |
@Piccirello Try with this one, only using single quotes gets you command execution: EDIT: Optimized to just one parameter |
There's command execution because the third single quote isn't escaped. For your optimized example, the string should end with an unescaped single quote. |
Sounds reasonable. |
Ok imagine the following example: I (the attacker) create a torrent with the following name: Then you add single quotes around my string and escape the quotes that were inside. The parameter sent to the system is this one: Firefox runs The escape character is very tricky and shouldn't be in a legit torrent name, it could be removed or replaced with a space. |
Good examples. Maybe this will be a little trickier than it first seemed.
I'm not sure if we can make this generalization. It would make things easier but may not be true. I wonder if we can get any security guarantees by passing the entire command, split on spaces, as an arguments list to |
Good afternoon, I contacted the CVE database so downstream Linux distributions acknowledge the vulnerability and backport and apply the patch. It's available at: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-13640 This is also their response, will come in handy to fix the quote escaping:
Greetings |
@micapucha Replace this line https://github.com/qbittorrent/qBittorrent/blob/master/src/app/application.cpp#L338 |
Hi @Chocobo1 I compiled qbittorrent with the patched line, and can no longer trigger the command execution. I have tested 10 rigged .torrents and swapping between ", ', and no quotes in the preferences and shellcode, and and also using $() in the shellcode. In any case, I think the absence of code execution is because you're no longer calling /bin/sh and passing the command as argument. Because of this, the shellcode is not being interpreted. However, the user must put the parameters themselves between quotes to work correctly (eg. a torrent named "Don Quixote" will pass "Don" as the first parameter and "Quixote" as the second one). I don't fully grasp the security implications on this, and if this could achieve execution in other platforms (eg. Windows) Tested on: Debian 10, Qbittorrent 4.1.5 from debian sources patched manually EDIT: Find attached the test files, if anybody wants to continue testing it. TestSuite.zip Greetings |
@micapucha Thanks for taking care of the CVE portion. I always love me a good CVE 😈 I’ll take another look at this tonight if time allows, or tomorrow at the latest. |
@Piccirello Thank you for your time and developing this amazing app :) Find attached the test suite, it's useful if anybody wants to continue further testing |
Hmm... sounds like good news!
Yes, that is correct. I thought it was convenience to be able to invoke shell env/commands but didn't consider from security viewpoint. Also that patch isn't new, it is actually the old form (df95efe).
That code path is only for non-windows system. |
@micapucha |
Thank you for fixing the issue :) |
Please provide the following information
qBittorrent version and Operating System
4.1.5 FreeBSD, but seeing the source code, probably all versions
What is the problem
The function Application::runExternalProgram() located in qBittorrent/src/app/application.cpp does not sanitize the name of the torrent and other parameters before passing them as a command line arguments. Right now it does a simple text substitution, which is vulnerable to command injection.
What is the expected behavior
The parameters are sanitized before being passed to the command line. This means something like PHP's escapeshellarg.
Steps to reproduce
Configure qBitTorrent to run an external script in Preferences - Downloads. Anything is valid. You can even quote the arguments. For example:
/home/user/notify.sh "%N" "%L" %C %Z
Create a new torrent with the following command:
mktorrent -n 'Name"; firefox ; "' -o exploit.torrent SourceDir
To test it locally with already created content, without needing to upload your torrent to a public tracker, create a directory named 'Name"; firefox ; "' (without the first and last quotes) that has the same values as the previous command's SourceDir. This will re-hash the content and mark it as completed, executing the script. You can use midnight commander to do this.
When the torrent download finishes, Firefox is opened
Greetings
The text was updated successfully, but these errors were encountered: