-
Notifications
You must be signed in to change notification settings - Fork 2
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Splitting
the target
which is a user supplied
input doesn't prevent the usage of some commands, which can still be injected and lead to different issues like DOS
or unexpected
behaviors.
More information have been provided specifically for the lines of code interested and a video had been attached to confirm this (sorry for the low quality of the video ... GIF converter lowers it).
Looking forward for seeing other countermeasures in place to prevent these issue 😄
Regards,
Mik
@@ -466,7 +466,7 @@ def install(self): | |||
def run(self): | |||
clearScr() | |||
print(self.nmapLogo) | |||
target = raw_input(self.targetPrompt) | |||
target = raw_input(self.targetPrompt).split(' ')[0] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Splitting the hostname
or the url
, which are user-supplied
inputs doesn't prevent malicious attackers from injecting successfully other commands like ls
or shutdown
, which could provoke anyway a DOS issue or unexpected behaviors.
The target
should be sanitized properly 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -558,7 +558,7 @@ def __init__(self): | |||
self.install() | |||
clearScr() | |||
print(self.wpscanLogo) | |||
target = raw_input(" Enter a Target: ") | |||
target = raw_input(" Enter a Target: ").split(' ')[0] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Splitting != sanitizing inputs
@@ -618,7 +618,7 @@ def __init__(self): | |||
self.install() | |||
clearScr() | |||
print(self.CMSmapLogo) | |||
target = raw_input(" Enter a Target: ") | |||
target = raw_input(" Enter a Target: ").split(' ')[0] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Splitting != sanitizing
Hi @d3m0n-r00t 😄 , os.system('command %s' % (user_supplied_input))) which should be fixed, like these ones:
I wanted also point out your attention on the fact the fix could break in certain cases the functionality of That said, I really appreciate your quick fix and the fact you didn't include any new library, which is an important thing in my opinion since doesn't introduce eventual issues/vulnerabilities coming from modules/libraries outside the ones the original author of the code wanted to include in ❤️ . Regards, |
Hi, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks again for your help 😄 ,
however I'm still able to bypass the checks in the wpscan/cmsmap
functionalities through a special crafted url
(more info on the comments).
Regarding the permalinks
, I should have linked all of them through the disclosure process
as you said, but part of them were still untested by me, so I didn't add them at the begin. That said, the same working solution you'll find for these 3 options will probably fix also the other options as well, so it shouldn't require additional checks or solutions 👍
Regards,
Mik
fsociety.py
Outdated
else: | ||
test_target = 'http://'+target | ||
try: | ||
urllib2.urlopen(test_target) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi 😄,
thanks again for the changes 👍
The characters used inside a valid url are also evaluated as valid bash
directives, which leads anyway to arbitrary command execution
in minor cases.
The example below is made using the http://evil.com?||nslookup
PoC payload, and can bypass the protections applied through urllib2.urlopen()
.
(please excuse the upper case
when typing ... I hadn't clicked the right key)
I understand it's difficult fixing this type of issue, so I think it's ok using also an external library to validate the inputs
obtained and avoid arbitrary command injection
👍
Regards,
Mik
fsociety.py
Outdated
else: | ||
test_target = 'http://'+target | ||
try: | ||
urllib2.urlopen(test_target) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same above: the urllib2.urlopen
checks if the url is valid, but a specially crafted input can still be dangerous and lead to arbitrary command injection
.
Mik
Hi, For IP/domainI have made used of the For URLSome of the tools require url as an input as their documentation says. Like
NB: Fortunately for my luck and since the script is huge For file inputsSome tools require a file as an input that contains various IPs. So I just added code to check if the file exists or not. The code exists only if the file exists.
For android hashI checked the documentation of the tool to crack the pin of android device and its takes a hash and salt as input. But this hashes/salt does not contain any symbol. So added a filter to avoid any symbols.
For tool for ftp authentication bypassFor the ftp authentication bypass tool, it takes in 2 inputs with space. First one is the host/IP which is verified by
I guess that is every occurrences and I guess I have fixed each of them. I have tested the fix and its and the tool did not break till now. Please verify this as it is huge script and I may have missed many. Also verifiy the fix for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @d3m0n-r00t 😄
this is awesome!!!!
I found only one thing you should change (the type of URL a tool was set to) and a error in the syntax which prevented from checking (I put a probably fix for that, but lemme know if you have better ideas on that). You'll find more informations in the specific commits.
That said, I think we're close to the final solution, so thanks a lot again ❤️
Regards,
Mik
fsociety.py
Outdated
(target, logDir, strftime("%Y-%m-%d_%H:%M:%S", gmtime()))) | ||
target = raw_input("Enter Target Hostname: ").split(' ')[0] | ||
try: | ||
socket.gethostbyname(target) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Arachni
accepts the url
like http://example.com
as per doc: https://github.com/Arachni/arachni/wiki/Command-line-user-interface#examples.
The socket.gethostbyname()
function will raise a exception in case the user provides a url
like that.
fsociety.py
Outdated
key = raw_input("Enter the android hash: ").split(' ')[0] | ||
salt = raw_input("Enter the android salt: ").split(' ')[0] | ||
symbols = ['!','@','#','$','%','^','&','*','(',')','-','=','+','|','||','&&','/','//','+'] | ||
if symbols not in key and symbols not in salt: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The line
arises a exception
which prevents the user to make working correctly the tool:
. I would suggest to add something like the following line of code:
key = raw_input("Enter the android hash: ")
salt = raw_input("Enter the android salt: ")
symbols = ['!','@','#','$','%','^','&','*','(',')','-','=','+','|','||','&&','/','//','+', ' '] #Added ' ' to avoid split(' ') which turns `key` and `salt` in a `list`
[symbol for symbol in symbols if symbol not in key and symbol not in salt] == symbols # if True --> the `key` and `salt` strings are correct (don't match any of the `blacklisted` chars)
This makes a list comprehension
which therefore checks if the string contains one of the characters blacklisted returning the list resulting and then checks if it's equal to the one predefined before ( symbols
).
Hi,
And I guess that is all. Thanks again. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @d3m0n-r00t 😄
I think we fixed massively the repo and I can confirm the tool seems work correctly and all the instances of os.system()
are taking properly sanitized inputs.
Regarding the solution of the symbols list
, I know it's not really good, but it's the only way I found which simply resolves the issue (and I ❤️ list comprehension).
So, I'm approving
this fix and in the meanwhile I ask @mufeedvh or @toufik-airane to check if the code seems fixed for you also 👍 .
Thanks again for your help and the amazing collaboration, we ❤️ this!!!
Looking forward to see other fixes/disclosure by you on the https://www.huntr.dev website 😄 🎉
Regards,
Mik
Thank you @Mik317, I too enjoyed this collaborative fix with you. Thanks. I liked your approach on the |
My pleasure @d3m0n-r00t 😄 Cheers, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Woah, Awesome fix! 👏🎉
No new dependencies, just pure code! 💯
Loved the back and forth collaboration between you and @Mik317 ❤️
Keep your fixes coming! 🔥
Great work all! We will be featuring this PR on our Twitter today as a great example of security in the open! 🍰 |
Congratulations d3m0n-r00t - your fix has been selected! 🎉 Thanks for being part of the community & helping secure the world's open source code. |
📊 Metadata *
Remote Code Execution vulnerability
Bounty URL: https://www.huntr.dev/app/bounties/open/1-python-fsociety
⚙️ Description *
Fixed code execution vulnerability by sanitizing the input. Previously the input was raw_input(). Fixed this by splitting the input at spaces (' ').
💻 Technical Description *
Fsociety had many instances where the input was executed as it is by the os.system code. The user input was the target variable which must be an IP address or a domain. But the user was able to execute arbitrary code by adding command line operators such as && or || etc. I splitted this input and made it a way that proper nmap script runs only when an Ip or domain is given as input. It ignores every other inputs.
🐛 Proof of Concept (PoC) *
Vulnerable code:
Steps to reproduce the bug:
🔥 Proof of Fix (PoF) *
Fix:
👍 User Acceptance Testing (UAT)
Just splited the input so that only the first parameter of the input is taken. Since IP or domain is considered as a single string it is passed through and the rest is splited out. If any thing other than an Ip or domain is supplied it shows an error showing 'unknown host'. So it doesn't break the code.