Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 316 Vote(s) - 3.49 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Force Content-Type or expose request.data in Flask for known content-type

#1
I am recreating a service in Python/Flask and am running into an issue with the way the existing clients authenticate. I have to match the existing clients scheme for compatibility reasons.

The existing clients take the username, password and base64 encode it. This is not HTTP Basic Authentication, despite sounding similar. Below is some sample code that would create this login request.

credentials = {
'username': '[email protected]',
'password': 'password'
}
data = b64encode(urlencode(credentials))
request = urllib2.Request(loginURL)
request.add_data(data)
# request.add_header('Content-Type', 'application/gooblygop')
# 'application/x-www-form-urlencoded' seems to be a default Content-Type
login = urllib2.urlopen(request)

On the server side, I take the POST data and base64 decode it to get the username and password information again.

flask server:
@app.route('/login', methods=['POST'])
def login():
error = None
if request.method == 'POST':
# post data: cGFzc3dvcmQ9ZGVmYXVsdCZlbWFpbD10ZXN0JTQwZXhhbXBsZS5jb20=
data = b64decode(request.data)
# decoded data: password=default&email=test%40example.com
return('ok')


The problem is the Content Type. If I specify an unknown Content-Type in the client (application/gooblygop), Flask exposes the POST data to request.data and I can decode the base64 string. If I leave the Content-Type as default (application/x-www-form-urlencoded), the raw data is not exposed to request.data and I don't know how to retrieve the base64 encoded string and make use of it.

The existing client software all pretty much defaults to x-www-form-urlencoded, but I can't rely on that always being the case.

Essentially, I need a reliable, server-side method for accessing that encoded string no matter what Content-Type the client program states.

Other notes: I am very new to Python, coming from a PHP background. So I am very open to suggestions. Also, this project is primarily for personal use.
Reply

#2
You want to look at the `request.form` object when dealing with urlencoded posts with normal mimetypes. In this case you have an unusual form, but here is a way to do it:

# mkreq.py
from urllib import urlencode
import urllib2
from base64 import b64encode

credentials = {
'username': '[email protected]',
'password': 'password'
}
data = b64encode(urlencode(credentials))
request = urllib2.Request("http://localhost:5000/login")
request.add_data(data)
request.add_header('Content-Type', 'application/gooblygop')
# 'application/x-www-form-urlencoded' seems to be a default Content-Type
login1 = urllib2.urlopen(request).read()
print(login1)
request2 = urllib2.Request("http://localhost:5000/login")
request2.add_data(data)
login2 = urllib2.urlopen(request2).read()
print(login2)

You probably want to modify the login bit to check the mimetype, here is a version with minimal changes to your current setup:

@app.route('/login', methods=['POST'])
def login():
error = None
if request.method == 'POST':
# post data: cGFzc3dvcmQ9ZGVmYXVsdCZlbWFpbD10ZXN0JTQwZXhhbXBsZS5jb20=
data = b64decode(request.data)
# decoded data: password=default&email=test%40example.com
if not data:
data = b64decode(request.form.keys()[0])
special_mimetype = request.mimetype
return(special_mimetype + '\n' + data)

This is the output of the first code sample, with two requests:

bvm$ python mkreq.py
application/gooblygop
username=test%40example.com&password=password
application/x-www-form-urlencoded
username=test%40example.com&password=password
Reply

#3
Have you thought about using json to pass your data in the POST? Flask has built in support for passing json data. In addition, if you set the Content-Type in the headers to application/json then flask will automatically dejson the POST data for you and put it in request.json

Here is the requesting application

import urllib2
import json

if __name__ == "__main__":
headers = {'Content-Type':'application/json'}
post_data = {"user":"test_user"}
print "Posting request"
req = urllib2.Request("http://localhost:5000/login", json.dumps(post_data), headers)
resp = urllib2.urlopen(req)
print "Response was %s" % resp.read()

This is the Flask view

from flask import request

@app.route('/login', methods=['POST'])
def login():

user = request.json['user']
return user


I suggest you test using curl as well if you are using the linux terminal. Here is an example

curl -X POST -H "Content-Type:application/json" -s -d '{"user":"This is the username"}' 'localhost:5000/login'

This is the username




Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through