Skip to content

Instantly share code, notes, and snippets.

@bitnot
Created September 4, 2020 15:44
Show Gist options
  • Save bitnot/fa61cfde50cab3d2f807a01fc161a647 to your computer and use it in GitHub Desktop.
Save bitnot/fa61cfde50cab3d2f807a01fc161a647 to your computer and use it in GitHub Desktop.
Export passwords from "Pleasant Password Server" web API.
import requests, json
# Look for TODO's
YOUR_TREE_ID='<TODO: put your tree UUID from /WebClient/Main/GetTree request>'
YOUR_PPS_HOST='TODO.put.your.host.com'
BASE_URL = 'https://' + YOUR_PPS_HOST
GET_PASS='/WebClient/Main/CopyPasswordPopup?credentialId={}'
GET_GROUP='/WebClient/CredentialListGrid/Select?CredentialGroupId={}'
GET_TREE='/WebClient/Main/GetTree?id={}'
DEFAULT_DATA='sort=Name-asc&page=1&pageSize=100&group=&filter='
csv_header=','.join('url,type,username,password,hostname,extra,name,grouping'.split(','))
def default_headers():
cookie = get_cookies()
return {
'Cookie': cookie
,'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
,'Accept': '*/*'
,'Host': YOUR_PPS_HOST
,'Origin': 'https://' + YOUR_PPS_HOST
,'Referer': f'https://{YOUR_PPS_HOST}/WebClient/Main'
,'X-Requested-With': 'XMLHttpRequest'
}
def get_cookies():
# TODO: put the value of the "Cookie" header in "cookie.txt"
with open('cookie.txt', 'r') as cf:
return cf.readline()
def get_groups(tree_id, headers, data):
tree_url = BASE_URL + GET_TREE.format(tree_id)
return requests.get(tree_url, headers=headers, data=data).json()
def get_credentials(group_id, headers, data):
group_url = BASE_URL + GET_GROUP.format(group_id)
return requests.post(group_url, headers=headers, data=data).json()
def get_password(credential_id, headers, data):
password_url = BASE_URL + GET_PASS.format(credential_id)
return requests.get(password_url, headers=headers, data=data).json()
def to_csv(credential):
url = credential['Url']
type_ = ''
username = credential['Username']
password = credential['Password']
hostname = ''
extra = f"Notes: {credential['Notes']}; Tags: {credential['Tags']}" # TODO: Add missing data here
name = credential['Name']
grouping = credential['Path']
return ','.join([ f'"{part}"' for part in
[url, type_, username, password, hostname, extra, name, grouping]])
if __name__ == "__main__":
headers = default_headers()
groups = get_groups(YOUR_TREE_ID, headers, DEFAULT_DATA)
for group in groups:
group_name = group['name']
credentials = get_credentials(group['id'], headers, DEFAULT_DATA)
print(csv_header)
for credential in credentials['Data']:
credential_id = credential['Id']
password = get_password(credential_id, headers, DEFAULT_DATA)['response']
credential['Password'] = password
print(to_csv(credential))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment