Wednesday, November 30, 2016

django HttpResponse() issue when literal template characters are part of query string

TL;DR:

Under certain conditions providing literal "{{ %" as the value of a query string parameter caused the HTTP Response to my browser to be un-renderable.

Request Modified via Burp: http://django/charts/?q={{ blahblah %
or
Request Modified via Burp: http://django/charts/?q={{ xxxxxxx &

This results in the response to the browser being treated as plaintext. Firefox generates the following error message:

"The character encoding of the plain text document was not declared. The document will render with garbled text in some browser configurations if the document contains characters from outside the US-ASCII range. The character encoding of the file needs to be declared in the transfer protocol or file needs to use a byte order mark as an encoding signature."


It seems as though django is expecting all query string content to be encoded but obviously with a proxy we can alter this.

Does the HttpResponse() function handle literal templating characters properly when they are part of the request variable that is passed to it?

Additional Information:

In this particular app request.Get.get("variable") is not used.

Based on my limited understanding of django it looks like our programmers have implemented a flow that is something like this:

-Project settings.py:
TEMPLATES = [
   
{
       
'BACKEND': 'django.template.backends.django.DjangoTemplates',
       
'DIRS': [],
       
'APP_DIRS': True,
       
'OPTIONS': {
           
'context_processors': [
               
'django.template.context_processors.debug',
               
'django.template.context_processors.request',                     <------Request Processor

-Frontend urls.py:
from django.conf.urls import patterns, url, include
from blah.contrib.project.frontend import views

urlpatterns
= patterns('',
    url
(r'^$', views.index),
    url
(r'^charts/', views.charts),

-Frontend views.py:
from django.shortcuts import render, HttpResponse, render_to_response, RequestContext
from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import user_passes_test

@user_passes_test(is_user)
def charts(request):
   
return render(request, 'main_html/charts.html')

-charts.html:
{% extends "base_html/base.html" %}

-base.html: (Where ?q= is defined finally. Is this considered a global django var?)
    <!-- Left side column. contains the logo and sidebar -->
   
<aside class="main-sidebar">
       
<!-- sidebar: style can be found in sidebar.less -->
       
<section class="sidebar">

           
<!-- search form -->
           
<form action="#" method="get" class="sidebar-form">
               
<div class="input-group">
                   
<input type="text" name="q" class="form-control" placeholder="Search...">
             
<span class="input-group-btn">
               
<button type="submit" name="search" id="search-btn" class="btn btn-flat"><i class="fa fa-search"></i>
               
</button>
             
</span>
               
</div>
           
</form>
           
<!-- /.search form -->

-Rendering:
So the built-in request is being passed to the shortcut function render():
  • render(request, 'main_html/charts.html')
https://docs.djangoproject.com/en/1.10/_modules/django/template/loader/#render_to_string
  • render() under the hood calls render_to_string()
  • render_to_string() returns a string to render()
  • render() finally calls HttpResponse() with the string-ified content
-Finally:
So is HttpResponse() having an issue because the unparsed request contains the literal templating characters and the result of HttpResponse() is now corrupted?

Or is the problem on our developers side because they did not explicitly define the response parameters when they called render()-->HttpResponse()?



Screenshot: (Modify via proxy to ensure no encoded characters)