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
Prevent xss #2620
Prevent xss #2620
Conversation
a1fd590
to
8e9834c
Compare
8e9834c
to
53dbd30
Compare
Codecov Report
@@ Coverage Diff @@
## master #2620 +/- ##
==========================================
- Coverage 80.21% 80.20% -0.01%
==========================================
Files 87 87
Lines 9335 9342 +7
Branches 1988 1989 +1
==========================================
+ Hits 7488 7493 +5
- Misses 1564 1565 +1
- Partials 283 284 +1
Continue to review full report at Codecov.
|
Cool! Thanks a lot, @StephenDsouza90 , for fixing this. |
The problem isn't in the dashboard save per-se, it is caused by the dashboard name being displayed in an unsafe manner. Stripping potential "bad" sequences from the dashboard name isn't a bad idea, but to properly fix the XSS we'll also need to make sure that we html-escape the name everywhere it's displayed. |
Hi @DanCech thanks for the quick feedback! I'm still a bit unclear on what more needs fixing, if you can point me in the right direction and guide me. I understand the problem isn't in the dashboard save functionality, but rather the "name" that's being rendered that allows for an XSS attack, but this is exactly what i've tried to tackle - I strip out potential "bad" sequences in the name and in the dashboard's state before it gets saved to the database. This should render the name everywhere correctly since the name will be fetched from the database which is the source of truth and it's saved in a safe manner. For an attacker trying to inject XSS into the name will be the only person who will be affected by XSS for that current state and session, unless he/she refreshes the page - for other end-users/clients, it shouldn't affect them as what gets saved into the database will be "safe" and that's what will be rendered to them. So still wondering if this solution is good enough? Or maybe if you could give me a scenario where this attack can still be exploited, I could try to work around that. |
Hi, I'm still awaiting feedback and next steps on how to move forward with this PR based on my last comment. Would be great if one of you could point me in the right direction. |
Basically whenever we display the name it should be html-encoded so that any "special" characters are encoded as html entities rather than interpreted as html. The docs for the strip_tags function explicitly state that it does not produce strings that are html-safe https://docs.djangoproject.com/en/3.0/ref/utils/#django.utils.html.strip_tags, and that html entities should be escaped when displaying the string. |
Hi @DanCech Thanks again for the feedback, you're right, my bad! I just checked there are two ways to solve this. We can go with Mozilla Bleach that does it in a clean way: >>> import bleach
>>> bleach.clean('an <script>evil()</script> example')
u'an <script>evil()</script> example' Or we can go with Django's escape() function:
>>> from django.utils.html import escape
>>> escape('an <script>evil()</script> example')
'an <script>evil()</script> example' With bleach, the only disadvantage is that we'll be adding yet another library, which might not be a good thing. I'll go ahead with the escape() for now unless there is any objection. |
The escaping needs to be done when we're actually inserting the name into the html on the client side, so you'd want to use the |
a possibly helpful example of escaping in the wrong place vs escaping in the right place: #2587 |
If I understand @DanCech correctly, would the following be a good enough solution? i.e. to function saveDashboard() {
<...>
<...>
if (button == 'ok') {
// html-encode dashboard name from input
text = htmlEncode(text);
// hmtl-encode dashboard name
setDashboardName(text);
// save html-encoded dashboard name
sendSaveRequest(text);
}
<...>
<...>
} graphite-web/webapp/content/js/dashboard.js Lines 2723 to 2737 in 0ed7dd7
|
You don't want to store the html-encoded dashboard name in the database, because then when you load it and html-encode it again you'll mangle it. eg if you have a dashboard name like |
Co-authored-by: Dan Cech <dan@aussiedan.com>
This PR is in reference to the issue #2520 for preventing an Cross-site scripting (XSS) attack when saving the dashboard.
It uses the Django's
django.utils.html.strip_tags()
function to sanitize html input elements, in this case, the name of the dashboard, to prevent the XSS attack.Currently my approach is to apply the sanitization on the fields that are inputted from the html template and rendered on the graphite web page compared to doing it via a middleware that would inspect
HttpRequest
objects - this IMO would mostly likely be a little inefficient. Sanitizing on the fields that require it is more faster.The Dashboard save functionality has a possible security issue allowing for an XSS attack, this PR fixes it. In the future, the sanitize utility function can be used for other input fields that require it.