Protect python code including a password, encrypt? - python

I am trying to run a python script on a remote server which i dont trust. The script contains a password that is kind of important.
What would be a good way to protect that code/password?
I would give it as an argument or i could prompt input on the terminal but that would be saved in history.

Store password with code on untrustworthy server, that definitely unsafe. You have to change the way like below if you can.
on the server you control, encrypt password with pub_key
general the different pub_key/private_key every request
the client you don't trust get id and encrypt_msg with auth
the password_required server get the id and private_key and decrypt encrypt_msg from client and compare the password.
delete the auth if the client is useless any more.

The ideal way to handle it would be using REST-Api calls from a trusted server.
On the untrusted server, you can store the encoded password.
EDIT 1: As #Luke has pointed out in the comments below, base64 owing to its simplicity can be easily decrypted. As suggested, we should implement a symmetric algorithm and then store the key on your trusted server.
You can explore the pycrypto library that has AES, DES etc.
The link for pypi .
import base64
encoded = base64.urlsafe_b64encode('MyPassword')
## returns 'TXlQYXNzd29yZA=='
Store this on the un-trusted server and then decode on the trusted server to generate the expiry-based password.
import base64
original = base64.urlsafe_b64decode(encoded)
# Returns MyPassword
Step-1 : Setup a password generation program on your trusted server
Step-2 : Define the get and post methods for your program
Step-3 : From the remote server, first do a GET Authorization token
command. If this token matches, generate a password with time-limit
expiry.
Step-4 : Handover this to the server. Reset it after the expired
time.
Sample post calls to get temporary passoword will be:
curl -L https://sandbox.trustedserver.com/v1.0/oauth/token/
-X post
-H 'Content-Type: application/json'
-H 'Authorization: Basic [Base64_Credentials]'
-d '{ "grant_type": "client_credentials" }
Sample response will be a access token that expires in 500 seconds:
{
"token_type": "bearer",
"access_token": "TXlQYXNzd29yZA==",
"expires_in": 500
}
Hope it helps.

Related

How to exchange authorization code for access token Twitter API?

I am developing an app that will read some tweets stats of my company. I want to let all the employees to connect with their twitter accounts.
I am facing the following problem: I am stuck at the "Exchange authorization code for access token".
The response url after Authorize is: https://example/v1/browser-callback?state=state&code=all0UTY5TVVMYmctNjZEQVpYYYYYYYYZZZZZXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
I suppose I have to change the code all0UTY5TVVMYmctNjZEQVpYYYYYYYYZZZZZXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX for access_token and access_token_secret, but I did not find how to do that on the documentation that twitter offers to us.
You need first to know the type of flow you are trying to implement
First you need to know what is the grant type of your client_id in the twitter side, i see in the callback there is code that means you are in normal authorization code or Authorization Code Flow with Proof Key for Code (PKCE), to know that check in your first call to twitter if you see in the params code_challenge and code_challenge_method if yes It's PKCE flow;
Second, I see that you have successfully done the first step of flow, then if you are in the PKCE, you need in your callback to send another request to get a final token like this:
client_id=your client_id&
code_verifier=the code generated by the application in the first step&
redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fcallback&
grant_type=authorization_code&
code=the code sent from twitter
I'm not sure what the docs looked like back in March, but to do this now you simply need to build the request headers with the code argument from the redirect URL. From the example url you gave (https://example/v1/browser-callback), your code is:
all0UTY5TVVMYmctNjZEQVpYYYYYYYYZZZZZXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
And the curl request you would make for a private client to retrieve the user's bearer and refresh token would be:
curl --location --request POST 'https://api.twitter.com/2/oauth2/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Basic YOUR_BASE64_ENCODED_ClientID:ClientSecret_HERE'\
--data-urlencode 'code=all0UTY5TVVMYmctNjZEQVpYYYYYYYYZZZZZXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' \
--data-urlencode 'grant_type=authorization_code' \
--data-urlencode 'redirect_uri=https://example/v1/browser-callback' \
--data-urlencode 'code_verifier=challenge'
where YOUR_BASE64_ENCODED_ClientID:ClientSecret_HERE is (per the docs):
To create the basic authorization header you will need to base64 encoding on your Client ID and Client Secret which can be obtained from your App’s “Keys and Tokens” page inside of the developer portal.
You'll need to make this request to get the initial bearer token/refresh token for private clients within 30 seconds of receiving the code at your callback URL after the user has authorized your app.

local API of a device

I am trying to interact with an energy meter that hosts its own local API to get data. I am far from having a lot of HTTP requests knowledge and this maybe asking a lot from Stackoverflow, but how do I interact with this device on a local area network?
The directions state the HTTP request needs to consist of the following:
<headers> are a variable number of HTTP headers; each header is on its own line.
The following items must be included in the headers:
o Content-type: text/xml
o Content-Length: xx where “xx” is the number of characters in the body of the POST
o Authorization: Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx where the 32-character Basic Authentication credential is formed using the EAGLE Cloud ID as the username, and the EAGLE Install Code as the password.
Ultimately I am trying to do this listed below (get meter data):
To get data from the meter, you must first discover its Hardware Address. This can be done by issuing a “device_list” command to the EAGLE through the Local API, which is done by sending a POST with the following text in the body:
<Command>
<Name>device_list</Name>
</Command>
Could anyone give me a tip on how to do this with Python requests? The code below returns a 401 as I know it doesnt incorporate the body & required header information.
import requests
url = "http://10.100.100.27/"
print(requests.post(url).text)
This is an example of what the POST request should look like from the docs.
Try the following
import requests
url = "http://10.100.100.27/cgi-bin/post_manager"
headers = {
'Content-Type': 'text/xml',
'Authorization' : 'Basic ' + '<your api key>',
}
command = 'device_list'
payload = '<Command><Name>{}</Name></Command>'.format(command)
print(requests.post(url, headers=headers, payload=payload).text)

send authenticated request while calling github api to have greater limit

I was calling github api from my python scripts. if run successfully, it would have made around 3000 calls. However, after 50-60 successful calls, it shows the below message-
{'message': "API rate limit exceeded for 108.169.151.47. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)", 'documentation_url': 'https://developer.github.com/v3/#rate-limiting'}
I have read the documentation. I don't have any application to register with to get a client id and client secret.
From my github account, I generated a token. I'm wondering if I can use that to send authenticated requests.
I tried some curl command to log in through my github profile in the git bash, and then run the python script, but it still shows the same message.
Can you suggest a way how can I make use of the good news in the message?
You might want to consider just using basic authentication with your GitHub username and password. The response received should be converted to JSON.
req = requests.get(url, auth=(USERNAME, PASSWORD))
req_json = req.json()

Getting tokens with Django REST framework

I am using JWT token authentication with Django REST
$ curl -X POST -d "username=admin&password=abc123" http://localhost:8000/api-token-auth/
and then
$ curl -H "Authorization: JWT <your_token>" http://localhost:8000/protected-url/
My points is if someone has to enter username / password in curl to get token and then use that token to get url in 2 steps. Then why not use username / password with basic authentication . as that will be with one request only.
What advantage will token give us . we have to type username / password anyway in token AUTH as well
You are right, if that would be the normal workflow there would be not much advantage. Expect that token auth has slightly better performance, because you don't have to hash the password.
But normally the token is stored on the client side. Imagine a mobile app. There you login once to obtain and store the token. Now you can do authenticated API requests without username/password.

How can I target a specific application server using the HTTP "Host" header (using GoLang)

The question:
Why can't I target a server using it's IP address in the request URL and the hostname as the "Host" header using GoLang?
Why does the same thing work using python? (2.7.6 - urllib2)
Background:
I'm writing a systems test that will send HTTP requests to several specific application servers that I'm testing and inspect the results for correctness. Each application server has the same function and should return the same response data. These servers are grouped behind load balancers. These load balancers are then resolved by DNS and the traffic is forwarded to the backend servers as appropriate. In order to target each server independently (for the tests) I am using each server's IP address in the URL instead of the usual hostname and I'm setting the "Host" HTTP header to be the hostname that usually goes in the url. This is to make sure the SSL cert
can decode the secure (HTTPS) request.
Current status:
I already have a python script that sends these test requests. Here's the basic idea of that script:
headers = {"Host": "<hostname>"} # this <hostname> is usually what would go in the URL on the next line
request = urllib2.Request('https://<ip-address>/path?query=123', headers=headers)
response = urllib2.urlopen(request)
# etc...
This code has been working fine for several months now. I've verified that it is indeed targeting the correct servers, based on IP address.
Goal:
I want to replicate this script in golang to make use of the concurrent capabilities of go. The reason I'm using go is that I'd like to send lots more requests at a time (using goroutines).
Problem:
Using the same technique as shown above (but in Go) I get the following error:
Get https://<ip-address>/path?query=123: x509: cannot validate certificate for <ip-address> because it doesn't contain any IP SANs
Here's an example of the kind of code I have written:
request, _ := http.NewRequest("GET", "https://<ip-address>/path?query=123", nil)
request.Header.Set("Host", "<hostname>")
client := &http.Client{}
response, err := client.Do(request)
// etc...
Again, why does the python code work while the GoLang code returns an error?
As per the python documentation:
Warning: HTTPS requests do not do any verification of the server’s certificate.
To replicate this behavior in Go see: https://stackoverflow.com/a/12122718/216488

Categories

Resources