POSTing to AWS S3 Signature Mismatch Error - python

This is my form
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<form action="http://mybucket.s3.amazonaws.com/" method="post" enctype="multipart/form-data">
Key to upload: <input type="input" name="key" value="user/eric/" /><br />
<input type="hidden" name="acl" value="public-read" />
<input type="hidden" name="AWSAccessKeyId" value="myAWSId" />
<input type="hidden" name="Policy" value="Base64EncodingOfPolicy"/>
<input type="hidden" name="Signature" value="Signature Calculated as urlencode(base64(HMAC-SHA1(secret, policy base64 encoded string same as utf-8 encoded)))" />
File: <input type="file" name="file" /> <br />
<!-- The elements after this will be ignored -->
<input type="submit" name="submit" value="Upload to Amazon S3" />
</form>
</html>
This is my policy
{ "expiration": "2014-12-01T12:00:00.000Z",
"conditions": [
{"acl": "public-read" },
{"bucket": "mybucket" },
["starts-with", "$key", "user/eric/"],
]
}
This is the base64 encoded policy
eyAiZXhwaXJhdGlvbiI6ICIyMDE0LTEyLTAxVDEyOjAwOjAwLjAwMFoiLA0KDQogICJjb25kaXRp
b25zIjogWw0KDQogICAgeyJhY2wiOiAicHVibGljLXJlYWQiIH0sDQoNCiAgICB7ImJ1Y2tldCI6
ICJoYWJpdHN1c2VybWVkaWEiIH0sDQoNCiAgICBbInN0YXJ0cy13aXRoIiwgIiRrZXkiLCAidXNl
ci9lcmljLyJdLA0KDQogIF0NCg0KfQ==
I have tried using the base64 encoded string with and without the newlines. Should I keep something specific in mind when using the above encoding and newlines?
I keep getting the SignatureDoesNotMatch error even after several attempts to account for all possible permutations.
I also used the signature verification tool and checked what AWS accepts and it matches. http://aws.amazon.com/code/199
How do I go about debugging this? If you have successfully POSTed using the REST API to S3 can you share the snippet?

Ok I was able to solve this after a while.
This is my python code to generate the signature
import base64
import hmac
from hashlib import sha1
import urllib
input = open("policy.txt", "rb")
policy = input.read()
policy_encoded = base64.b64encode(policy).encode("UTF-8")
secret = "<my_aws_secret>"
print 'Encoded Policy %s' %(policy_encoded)
hashed = hmac.new(secret,policy_encoded, sha1)
#This is the required value
signature = base64.b64encode(hashed.digest())
#This is not required for a HTTP POST form based request, only when it has to be passed in urlencoded format
signature_urlencoded = urllib.quote_plus(base64.b64encode(hashed.digest()))
print 'Signature urlencoded %s' %(signature)
My policy.txt is
{ "expiration": "2014-12-01T12:00:00.000Z",
"conditions": [
{"acl": "public-read" },
{"bucket": "<mybucket>" },
{"success_action_status" : "201"},
["starts-with", "$key", "uploads/"],
]
}
And my form looks like
<form action="http://habitsusermedia.s3.amazonaws.com/" method="post" enctype="multipart/form-data">
<input type="hidden" name="acl" value="public-read" />
<input type="input" name="key" value="uploads/${filename}" />
<input type="hidden" name="success_action_status" value="201" />
<input type="hidden" name="AWSAccessKeyId" value="<aws_access_key>" />
<input type="hidden" name="Policy" value="<policy_encoded_as_base64>"/>
<input type="hidden" name="Signature" value="<signature>" />
File: <input type="file" name="file" /> <br />
<!-- The elements after this will be ignored -->
<input type="submit" name="submit" value="Upload to Amazon S3" />
</form>
Make sure your AWS bucket is configured to accept POSTS, PUT from any domain. Use the policy generating tool for that.
There is a helpful article explaining these concepts on AWS

Related

How would I translate this html POST request into python

I am having difficulty translating this specific HTML POST request into Python - I am attempting to exploit a security vulnerability on a test server.
director=
<form action="http://127.0.0.1:8000/card/0" method="POST">
<input type="hidden" name="amount" value="8000" />
<input type="hidden" name="username" value="hacker" />
<input type="submit" value="View my photos" />
</form>
Before you run the code below. Run pip install requests.
import requests
response = requests.get("http://api.open-notify.org/astros.json")
print(response)
>>>> Response<200>
See more details in the URL below.
https://www.nylas.com/blog/use-python-requests-module-rest-apis/

How to solve "AttributeError: 'unicode' object has no attribute 'file'" once and for all in python webapp2 at file upload?

I already saw similar questions here describing same problem, peoples gives there answers and someones even respond it helped, but nothing from it totally works for me.
This is my code:
<html>
<body>
<form action = "/anomalydetector" enctype = "multipart-form-data" method = "post">
File: <input name = "attachment" type = "file" /><br />
Analyzer sensitivity in percents: <input type = "text" name = "sensitivity" value = "10" /><br />
<input type = "submit" value = "Analyze" />
</form>
</body>
</html>
and the handler:
class AnomalyDetectorPage(webapp2.RequestHandler):
def post(self):
uploaded_file = self.request.POST.get("attachment");
file_data = uploaded_file.file.read();
I always getting error of this kind:
File "/base/data/home/apps/s~test-ml/1.398533980585659886/main.py", line 207, in post
file_data = uploaded_file.file.read();
AttributeError: 'unicode' object has no attribute 'file'
I understand that python thinks that files are strings, but what I can do with it???
I tried self.request.POST.get("attachment").file.read(), self.request.POST["attachment"].file.read(), self.request.get("attachment").file.read() and self.request.POST.multi["attachment"].file.read() and maybe something else, but I always getting this error.
What I can do to read content of this file?
The enctype attribute value you are using is wrong. The form should be sent over:
multipart/form-data
<html>
<body>
<form action="/anomalydetector" enctype="multipart/form-data" method="post">
File: <input name="attachment" type="file" />
<br />
Analyzer sensitivity in percents: <input type="text" name="sensitivity" value="10" />
<br />
<input type="submit" value="Analyze" />
</form>
</body>
</html>

Post form values not showing up

This is my HTML form
<form method="post">{% csrf_token %}
<strong>Start</strong><br />
Lng: <input type="text" id="start_lng"><br />
Lat: <input type="text" id="start_lat"><br />
<strong>Destination</strong><br />
Lng: <input type="text" id="dest_lng"><br />
Lat: <input type="text" id="dest_lat"><br />
<input type="submit" value="Go" />
</form>
But when i look at my Request information the only POST values i get is the "csrfmiddlewaretoken" and not any of the start_lng, start_lat and so on.
Your HTML <input> elements do not have name attribute and therefore are not considered "successful controls" for submission as defined in the HTML spec: http://www.w3.org/TR/html401/interact/forms.html#h-17.13.2
A successful control is "valid" for submission. Every successful control has its control name paired with its current value as part of the submitted form data set. A successful control must be defined within a FORM element and must have a control name.

Python 3.2.3 to log into secure website

Using python 3.2.3 I am trying to log into some websites and save the source from a hidden page to a file. I am stuck on how to log in. I have figured out how to log into a specific website but can't seem to get it working on others. The source of the webpage I am trying to log into is:
<form id="login_form" name="login_form" action="https://www.o2online.ie/amserver/UI/Login?org=o2ext&goto=%2F%2Fwww.o2online.ie%2Fo2%2Fmy-o2%2F" method="post">
<p id="form_header">My Account login</p>
<input value="Go" type="hidden" name="IDButton" id="IDButton"/>
<input value="o2ext" type="hidden" name="org" id="org"/>
<input value="TRUE" type="hidden" name="CONNECTFORMGET"/>
<label for="IDToken1">Username</label><br />
<input tabindex=1 type="text" id="IDToken1" name="IDToken1" value="Username/mobile" onclick="javascript: this.value='';" maxlength="60" onfocus="this.value='';" tabindex=1 /><br />
<br />
<label for="IDToken2">Password</label><br />
<input tabindex=2 type="password" id="IDToken2" name="IDToken2" value="" maxlength="30" onfocus="this.value='';" tabindex=2 />
<input tabindex=3 type="image" src="../images/my-o2/Login-button.png" id="submit_button" />
</form>
On the other pages that I have logged into sucessfully have had a submit button with a certain value but this webpage has an image for the submit button which has no value.
The code I have been using is:
import urllib.request
import urllib.parse
import http.client
import sys
url = 'http://www.o2online.ie/o2/login/'
login_data = {
'IDToken1': 'xxxx',
'IDToken2': 'xxxx',
#'submitbutton': 'submit'
}
# creating an opener object that will handle the cookies
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor)
r = opener.open(url, urllib.parse.urlencode(login_data).encode())
# logged in
#Opening and saving source to a file
f = opener.open('http://www.o2online.ie/o2/my-o2/')
sys.stdout = open('file.html', 'w')
print (f.read(999999))
I have commented out the submit button.
Can this code be modified to log into this website?
How would you submit this form in python?

Creation of StringToSign

I am reading the documentation of passing a querystring to Amazon's S3 for authentication, and can't seem to grok how exactly the StringToSign is created and used. I am looking for a concrete example to illustrate (1) how to construct the StringToSign, and (2) once I have the signature, how to call the form.
For example's sake, let's say the following is my information:
Content-type='image/jpeg'
Bucket='test-bucket'
Key = 'filename'
ACL = 'public-read'
Expiration = '(never expires)'
Access Key = '12345'
Secret Password = '1a2b3c'
File = <file the user uploads>
How would I get the StringToSign value from this? And once I have that, how would I create the following form:
<form action="??" method="post" enctype='multipart/form-data' class="upload-form">
<input name="file" type="file">
</form>
And for reference: http://docs.amazonwebservices.com/AmazonS3/latest/dev/index.html?RESTAuthentication.html#RESTAuthenticationQueryStringAuth. Thank you.
Based on what you described, it seems like you want to support browser-based uploads using POST. There is a section of the AWS documentation which talks about this.
As an overview keep in mind you'll either have to make your bucket publically writeable or include a policy document. I'll assume you'll be including a policy document (check the docs if you don't want to):
A policy document is just a fragment of JSON that is used to authenticate the request, and gives a bunch of conditions that must be met before data is uploaded. E.g:
"expiration": "2020-12-01T12:00:00.000Z",
"conditions": [
{"acl": "public-read" },
{"bucket": "test-bucket" },
["eq", "$key", "filename"],
]
}
This says the action to upload will be allowed until 2020, given that the bucket is only publically readable, the bucket name is 'test-bucket' and the key is exactly equal to 'filename'.
Now, to construct your signature you take the above JSON doc, UTF-8 encode it and then base64 that and then sign the whole thing using your secret access key (using hmac sha1) and finally base64 that whole thing
policy_data = ... # stuff above
enc_policy = base64.b64_encode(policy_data.encode('utf8'))
signed = base64.b64_encode(hmac.new(AWS_SECRET, enc_policy, hashlib.sha1))
Then finally, your form would look something like this:
<form action="http://test-bucket.s3.amazonaws.com/" method="post" enctype="multipart/form-data">
Key to upload: <input type="input" name="key" value="filename" /><br />
<input type="hidden" name="acl" value="public-read" />
<input type="hidden" name="success_action_redirect" value="http://test-bucket.s3.amazonaws.com/successful_upload.html" />
Content-Type: <input type="input" name="Content-Type" value="image/jpeg" /><br />
<input type="hidden" name="AWSAccessKeyId" value="YOUR_ACCESS_KEY_ID" />
<input type="hidden" name="Policy" value="<enc_policy from above>" />
<input type="hidden" name="Signature" value="<signed from above>" />
File: <input type="file" name="file" /> <br />
<!-- The elements after this will be ignored -->
<input type="submit" name="submit" value="Upload to Amazon S3" />
</form>

Categories