Mitmproxy tampering with GET and POST request/ response in one script - python

A POST request sent to a certain URL (http://test.com) looks like this:
{
"messageType": "OK",
"city": {
"Name": "Paris",
"Views": {
"1231": {
"id": 4234,
"enableView": false
},
},
"Views": [5447, 8457],
"messages": [{
"id": "message_6443",
"eTag": 756754338
}]
},
"client": {
"Id": 53,
"email": "test#test.us",
"firstName": "test",
"lastName": "test",
"id": 52352352,
"uuid": "5631f-grdeh4",
"isAdmin": false
}
}
I need to intercept the request and change isAdmin to true.
And a GET request to a certain URL (https://test.com/profiles/{Random_Numbers}/{id}) has a (encoded) response like this:
{
"id": 0,
"Code": "Admin",
"display": "RRRR"
}
I need to change id to 5.
So basically I need to write one script that will do both of these actions.
So far I have tried to take advantage of some examples on GitHub, but I haven't gotten it so far:
from libmproxy.protocol.http import decoded
def start(context, argv):
if len(argv) != 3:
raise ValueError('Usage: -s "modify-response-body.py old new"')
context.old, context.new = argv[1], argv[2]
def response(context, flow):
with decoded(flow.response): # automatically decode gzipped responses.
flow.response.content = flow.response.content.replace(context.old, context.new)`
How do I implement this for my scenario?
Probably using the libmproxy to get http-request and response would be a better idea, maybe.

The script you posted and Python's JSON module should get you pretty far:
def response(context, flow):
if flow.request.url == "...": # optionally filter based on some criteria...
with decoded(flow.response): # automatically decode gzipped responses.
data = json.loads(flow.response.content)
data["foo"] = "bar"
flow.response.content = json.dumps(data)

Related

How does one pass a json file or object in a POST request using Python module 'requests'

I am using a site's REST API's and have been primarily using Python's 'requests' module to GET json responses. The goal of the GET requests are to ultimately pull a user's form response which ends up being a complex json document. To deal with this:
user_form_submission = requests.get('https://www.url/doc.json',
auth = (api_key, secret),
params = params)
python_obj = json.loads(user_form_submission.text)
trimmed_dict = python_obj['key'][0]['keys']
For context, this is what trimmed_dict would look like formatted as .json:
{
"Date": { "value": "2020-04-26", "type": "date" },
"Location": {
"value": "Test ",
"type": "text",
"geostamp": "lat=34.00000, long=-77.00000, alt=17.986118, hAccuracy=65.000000, vAccuracy=10.000000, timestamp=2020-04-26T23:39:56Z"
},
"form": {
"value": [
{
"form_Details": {
"value": [
{
"code": {
"value": "0000000000",
"type": "barcode"
},
"Name": { "value": "bob", "type": "text" }
}
],
"type": "group"
},
"Subtotal": { "value": "4", "type": "decimal" },
"form_detail2": {
"value": [
{
"name": {
"value": "billy",
"type": "text"
},
"code": {
"value": "00101001",
"type": "barcode"
},
"Classification": {
"value": "person",
"type": "select1"
},
"Start_Time": { "value": "19:43:00", "type": "time" },
"time": { "value": "4", "type": "decimal" }
}
],
"type": "subform"}
}
]
}
}
Now I have a portion of the json that contains both the useful and useless. From this point, can I pass this obj in a POST? I've tried every way that I can think of approaching it, and have been shut down.
Understanding how I want to go about this, this is how I thought it would go:
json_post = requests.post(' https://url/api/doc.json',
auth = (api_key, secret),
json = {
"form_id" : 'https://url.form.com/formid',
'payload':{
json.dumps(trimmed_dict)
}})
But, when I do this, I get the following error --
TypeError: Object of type set is not JSON serializable
How can I push this dict through this POST? If there's a more effective way of going about it, I am very open to suggestion.
Try removing the curly braces around json.dumps(trimmed_dict). json.dumps turns your trimmed_dict into a string, which becomes a python set when surrounded with braces.
Additionally you could remove json.dumps and plug the trimmed_dict into the structure directly as the value associated with payload.
Remove the extra {} from the payload. payload itself is a key and json.dumps(trimmed_dict) as a value is enough
json_post = requests.post(' https://url/api/doc.json',
auth = (api_key, secret),
json = {
"form_id" : 'https://url.form.com/formid',
"payload": json.dumps(trimmed_dict)
})

error with signature token when filling a typeform

I'm learning Python and I'm trying to fill a type form using Python requests, however I get this error response:
{"code":"VALIDATION_ERROR","description":"The provided body is malformed.","details":[{"code":"INVALID_PAYLOAD","description":"signature mismatch","in":"BODY","field":".signature"}]}
However, when I put the token.text value manually in data it works. I can't get it working when adding the token programmatically to the payload, even tried with str() and it's not working.
Here is the code:
import requests
import time
epochTime = int(time.time())
token = requests.get("https://mehdikhireddine.typeform.com/app/form/result/token/OcotDC/default")
final = token.text
print(token.text)
data = { "signature": final,
"form_id": "OcotDC",
"landed_at": epochTime,""
"answers": [
{
"field": {
"id": "nDoisfzMsrBP",
"type": "short_text"
},
"type": "text",
"text": "mehdilemoi"
},
{
"field": {
"id": "iCW4s6Fc37OL",
"type": "legal"
},
"type": "boolean",
"boolean": True
}
]
}
r = requests.post("https://mehdikhireddine.typeform.com/app/form/submit/OcotDC", json=data)
print(r.text)
This issue arises if you store the epochTime before getting the token from the HTTPS response, presumably because the server then fails to match the signature and time, resulting in "signature mismatch".
You can fix this by taking the current time after the token response has been received, i.e.:
token = requests.get("https://mehdikhireddine.typeform.com/app/form/result/token/OcotDC/default")
epochTime = int(time.time())
Output:
{"message":"success"}
Note that this may still intermittently fail if too much time elapses between getting the response and getting the epochTime.

Python post request, problem with posting

I'm trying to write a typeform bot but I am a totally beginner so I have problems with request.post
I am trying to fill this typeform: https://typeformtutorial.typeform.com/to/aA7Vx9
by this code
import requests
token = requests.get("https://typeformtutorial.typeform.com/app/form/result/token/aA7Vx9/default")
data = {"42758279": "true",
"42758410": "text",
"token": token}
r = requests.post("https://typeformtutorial.typeform.com/app/form/submit/aA7Vx9", data)
print(r)
I think that something is wrong with "data" and I am not sure if I use token in a good way. Could you help me?
So, first of all, you need to get another field with the token. To do that, you should pass the header 'accept': 'application/json' in your first request. In the response, you'll get the json object with the token and landed_at parameters. You should use them in the next step.
Then, the post data shoud be different from what you're passing. See the network tab in the browser's developer tools to find out the actual template. It has a structure like that:
{
"signature": <YOUR_SIGNATURE>,
"form_id": "aA7Vx9",
"landed_at": <YOUR_LANDED_AT_TIME>,
"answers": [
{
"field": {
"id": "42758279",
"type": "yes_no"
},
"type": "boolean",
"boolean": True
},
{
"field": {
"id": "42758410",
"type": "short_text"
},
"type": "text",
"text": "1"
}
]
}
And finally, you should convert that json to text so the server would successfully parse it.
Working example:
import requests
import json
token = json.loads(requests.post(
"https://typeformtutorial.typeform.com/app/form/result/token/aA7Vx9/default",
headers={'accept': 'application/json'}
).text)
signature = token['token']
landed_at = int(token['landed_at'])
data = {
"signature": signature,
"form_id": "aA7Vx9",
"landed_at": landed_at,
"answers": [
{
"field": {
"id": "42758279",
"type": "yes_no"
},
"type": "boolean",
"boolean": True
},
{
"field": {
"id": "42758410",
"type": "short_text"
},
"type": "text",
"text": "1"
}
]
}
json_data = json.dumps(data)
r = requests.post("https://typeformtutorial.typeform.com/app/form/submit/aA7Vx9", data=json_data)
print(r.text)
Output:
{"message":"success"}

requests.exceptions.HTTPError: 400 Client Error: Bad Request for url

I am trying to create an object in a database using Python requests. I am able to do this with other URLs, but for this particular one I am getting errors. I am not sure if there is a problem with the actual request or the URL. Four items are required for creation, so I will just focus on those for now.
Below you will find an example of the request payload according to the documentation:
def create_opportunity(self, data):
try:
r = requests.post(
self.URL + 'sales/opportunities', data=data,
headers=self.Header)
r.raise_for_status()
except:
raise
return r.json()
create_opp = '{"name": "My Opportunity", "primarySalesRep": {"name": "John Doe"}, "company": {"name": "My Company"}, "contact": {"name": "Jane Doe"}}'
opportunity = objCW.create_opportunity(create_opp)
payload example
{
"name": "string",
"primarySalesRep": {},
"company": {},
"contact": {}
}
primarsySalesRep
"primarySalesRep": {
"id": 0,
"identifier": "string",
"name": "string",
"_info": { }
},
company
"company": {
"id": 0,
"identifier": "string",
"name": "string",
"_info": { }
},
contact
"contact": {
"id": 0,
"name": "string",
"_info": { }
},
In your code create_opp is a string. You shouldn't pass a string in data= keyword of post() function of requests.
Given that server returns a JSON (return r.json()), I can guess that it receives JSON as well. Try to do something like this:
def create_opportunity(self, data):
r = requests.post(self.URL + 'sales/opportunities', json=data, headers=self.Header)
r.raise_for_status()
return r.json()
create_opp = {
"name": "My Opportunity",
"primarySalesRep": {"name": "John Doe"}, # maybe "id" or "identifier" is required?
"company": {"name": "My Company"}, # maybe "id" or "identifier" is required?
"contact": {"name": "Jane Doe"},
}
opportunity = objCW.create_opportunity(create_opp)

Dealing with JSON in Python

I have a JSON response as such:
{
"SiteInfo": [
{
"'LOB03023D'": {
"errorText": "Success",
"status": "1",
"parameterList": {
"aloha_mask": "255.255.255.0",
"beta_mask": "255.255.255.224",
"omega_mask": "0",
}
}
}
],
"Error Text": null,
"API RequestID": "11",
"Status": 1,
"Username": "NMS#internal.com",
"TransactionID": "1467626",
"Error Code": null,
"GetSiteInfoTimeStamp": "2017-02-23 21:32:42"
}
In my script after loading the response as such:
ubdataset = json.loads(response.text)
How can I access only the 'aloha_mask' field?
The following did not work for me:
aloha = ubdataset['SiteInfo']['LOB03023D']['parameterList'][0]['aloha_mask']
Thanks everyone in advance!
Try changing it to this:
aloha = ubdataset['SiteInfo'][0]["'LOB03023D'"]['parameterList']['aloha_mask']
Parameter list is not a list, your statement should be:
aloha = ubdataset['SiteInfo'][0]["'LOB03023D'"]['parameterList']['aloha_mask']
Although the request is not valid json the last element in parameterList has a comma that should not be there.

Categories

Resources