|
|
@@ -28,22 +28,825 @@ |
|
|
""" |
|
|
|
|
|
from __future__ import print_function |
|
|
import os |
|
|
import getpass |
|
|
import xmltodict |
|
|
import uuid |
|
|
import json |
|
|
import subprocess |
|
|
import base64 |
|
|
import tempfile |
|
|
import contextlib |
|
|
import shutil |
|
|
import errno |
|
|
import sys |
|
|
|
|
|
found = [] |
|
|
banned = ['02U', |
|
|
'02W', |
|
|
'02Y', |
|
|
'030', |
|
|
'0_cart_quantity_select', |
|
|
'1_cart_quantity_select', |
|
|
'2_cart_quantity_select', |
|
|
'2b54dd7995c52288df0bc7c36e7f1725840e3122', |
|
|
'3_cart_quantity_select', |
|
|
'4_cart_quantity_select', |
|
|
'5_cart_quantity_select', |
|
|
'6035d4db3b4cbb3e34acc605977169d7cefb1d52', |
|
|
'_fmu.un._0.e', |
|
|
'_fmu.uni-._0.l', |
|
|
'_fmu.uni-regi._0.c', |
|
|
'_fmu.uni-register-a._0.a', |
|
|
'_fmu.uni-register-aut._0.a', |
|
|
'_fmu.uni-register-auth._0.a', |
|
|
'_fmu.uni-register-authcom._0.a', |
|
|
'_fmu.uni-register-me._0.m', |
|
|
'_fmu.uni-register-mem._0.m', |
|
|
'_fmu.uni-register-memb._0.m', |
|
|
'_fmu.uni-register-p._0.p', |
|
|
'_fmu.uni-register-pa._0.pa', |
|
|
'_fmu.uni-register-ph._0.p', |
|
|
'_fmu.uni-register-pho._0.p', |
|
|
'_fmu.uni-register._0.t', |
|
|
'_fmu.uni._0.f', |
|
|
'accept_terms', |
|
|
'accept_terms_use', |
|
|
'AcceptPrivacyPolicy', |
|
|
'account.Password2', |
|
|
'aceptado', |
|
|
'acepto', |
|
|
'acepto1', |
|
|
'acepto2', |
|
|
'aceptoCond', |
|
|
'aceptocookies', |
|
|
'acpo', |
|
|
'action', |
|
|
'address1', |
|
|
'address[city]', |
|
|
'address[country]', |
|
|
'address[name]', |
|
|
'address[postal_code]', |
|
|
'address[province]', |
|
|
'address[street]', |
|
|
'address[surname]', |
|
|
'admin_color', |
|
|
'age', |
|
|
'agree', |
|
|
'agree_tos', |
|
|
'allow_email', |
|
|
'anno', |
|
|
'answer1', |
|
|
'apellido1', |
|
|
'apellido2', |
|
|
'approve_terms', |
|
|
'authCompanyStateInput', |
|
|
'AuthenticationRequestDto.EmailAddress', |
|
|
'AuthenticationRequestDto.Password', |
|
|
'ayoNac', |
|
|
'b-entrar', |
|
|
'B1', |
|
|
'bbsbbstopics', |
|
|
'billing[address]', |
|
|
'billing[city]', |
|
|
'billing[name]', |
|
|
'billing[phone]', |
|
|
'billing[state]', |
|
|
'billing[zip]', |
|
|
'billing_zip', |
|
|
'BirthDay', |
|
|
'birthday.day', |
|
|
'birthday.month', |
|
|
'birthday.year', |
|
|
'BirthYear', |
|
|
'blog_public', |
|
|
'borrower_address', |
|
|
'borrower_city', |
|
|
'borrower_country', |
|
|
'borrower_dateofbirth', |
|
|
'borrower_email_repeat', |
|
|
'borrower_firstname', |
|
|
'borrower_nif', |
|
|
'borrower_phone', |
|
|
'borrower_sex', |
|
|
'borrower_state', |
|
|
'borrower_streetnumber', |
|
|
'borrower_surname', |
|
|
'borrower_zipcode', |
|
|
'boton', |
|
|
'btn_continue', |
|
|
'btnChangpassword', |
|
|
'btnLogin', |
|
|
'business', |
|
|
'button', |
|
|
'callingCode', |
|
|
'cancelbutton', |
|
|
'candidate[address]', |
|
|
'candidate[name]', |
|
|
'candidate[time_zone]', |
|
|
'Captcha', |
|
|
'captchaAnswer', |
|
|
'cargo_password2', |
|
|
'carpeta', |
|
|
'cart_quantity[]', |
|
|
'CestaForm[aceptar]', |
|
|
'CestaForm[apellidos]', |
|
|
'CestaForm[codigo_postal_empresa]', |
|
|
'CestaForm[confirmar_contrasena]', |
|
|
'CestaForm[direccion_empresa]', |
|
|
'CestaForm[nombre]', |
|
|
'CestaForm[poblacion_empresa]', |
|
|
'CestaForm[provincia_empresa]', |
|
|
'CestaForm[telefono]', |
|
|
'cgv', |
|
|
'changepassword', |
|
|
'check_password', |
|
|
'china_payment_selection', |
|
|
'City', |
|
|
'city', |
|
|
'clave', |
|
|
'clicked_element', |
|
|
'co', |
|
|
'cod_pos_cas', |
|
|
'commentshours', |
|
|
'commercialInfo', |
|
|
'commit', |
|
|
'company name', |
|
|
'company', |
|
|
'company-name', |
|
|
'company_size', |
|
|
'companyCountry', |
|
|
'condiciones', |
|
|
'condiciones1step', |
|
|
'conditions', |
|
|
'confirm', |
|
|
'confirm-password', |
|
|
'confirm_email_address', |
|
|
'confirmaEmail', |
|
|
'confirmaPass', |
|
|
'confirmation', |
|
|
'confirmationemail', |
|
|
'ConfirmEmail', |
|
|
'ConfirmPassword', |
|
|
'confirmpassword', |
|
|
'confirmPassword', |
|
|
'contrasenha_repeat', |
|
|
'cookielength', |
|
|
'cookieuser', |
|
|
'country', |
|
|
'Country', |
|
|
'country_code', |
|
|
'country_id', |
|
|
'country_key', |
|
|
'country_name', |
|
|
'country_prefix_phone_1', |
|
|
'countryId', |
|
|
'CountryID', |
|
|
'cp', |
|
|
'createuser', |
|
|
'Credentials.UsernameRepeat', |
|
|
'credit limit', |
|
|
'csdb', |
|
|
'ctl00$bCPH$tabContainer$loginPanel$loginControl$LoginButton', |
|
|
'ctl00$bCPH$tabContainer$loginPanel$loginControl$Password', |
|
|
'ctl00$bCPH$tabContainer$newUserPanel$createUserWizard$__CustomNav0$StepNextButtonButton', |
|
|
'ctl00$bCPH$tabContainer$newUserPanel$createUserWizard$CreateUserStepContainer$ConfirmEmail', |
|
|
'ctl00$bCPH$tabContainer$newUserPanel$createUserWizard$CreateUserStepContainer$ConfirmPassword', |
|
|
'ctl00$bCPH$tabContainer$newUserPanel$createUserWizard$CreateUserStepContainer$Email', |
|
|
'ctl00$ContentPlaceHolder1$uc_RegisterForm$', |
|
|
'ctl00$ContentPlaceHolder1$uc_RegisterForm$btn_login', |
|
|
'ctl00$ContentPlaceHolder1$uc_RegisterForm$btn_register', |
|
|
'ctl00$ContentPlaceHolder1$uc_RegisterForm$frm_remember_me', |
|
|
'ctl00$ContentPlaceHolder1$uc_RegisterForm$frm_remember_me_new_user', |
|
|
'ctl00$ContentPlaceHolderOficinaVirtual$btCancelar', |
|
|
'ctl00$ContentPlaceHolderOficinaVirtual$btEnviar', |
|
|
'ctl00$ctl00$ctl00$ctl00$base_content$web_base_content$home_content$page_content_left$ctl01$CreateUserButton', |
|
|
'ctl00$ctl00$ctl00$ctl00$base_content$web_base_content$home_content$page_content_left$ctl01$Email', |
|
|
'ctl00$ctl00$ctl00$ctl00$base_content$web_base_content$home_content$page_content_left$ctl01$FirstName', |
|
|
'ctl00$ctl00$ctl00$ctl00$base_content$web_base_content$home_content$page_content_left$ctl01$LastName', |
|
|
'ctl00$ctl00$ctl00$ctl00$base_content$web_base_content$home_content$page_content_left$ctl01$SignupPWord', |
|
|
'ctl00$PagePlaceHolder$btnPreRegistro', |
|
|
'ctl00$PagePlaceHolder$btnReturn', |
|
|
'currency', |
|
|
'custom_fields[custom2]', |
|
|
'customer_firstname', |
|
|
'customer_lastname', |
|
|
'customer_privacy', |
|
|
'customerName', |
|
|
'CustomerType', |
|
|
'data.Password2', |
|
|
'DataPrivacyAcceptedCheckBox', |
|
|
'dataProtectionSpecific', |
|
|
'days', |
|
|
'default_newsletters', |
|
|
'delivery_option[0]', |
|
|
'department', |
|
|
'departureAirportName', |
|
|
'description', |
|
|
'diaNac', |
|
|
'direccion', |
|
|
'DistributionID', |
|
|
'DNI', |
|
|
'dni', |
|
|
'dob', |
|
|
'dob_Day', |
|
|
'dob_Month', |
|
|
'dob_Year', |
|
|
'doLogin', |
|
|
'donde', |
|
|
'doOrder', |
|
|
'doRegister', |
|
|
'doReset', |
|
|
'dst', |
|
|
'email1', |
|
|
'email2', |
|
|
'email_confirm', |
|
|
'email_newsletter3', |
|
|
'email_repeat', |
|
|
'email_verify', |
|
|
'emailAsAliasBuff', |
|
|
'EmailB', |
|
|
'emailConfirm', |
|
|
'emailconfirm', |
|
|
'emailConfirmation', |
|
|
'emailok', |
|
|
'EMAILTYPE', |
|
|
'enterprise-size', |
|
|
'entra', |
|
|
'Enviar', |
|
|
'enviar', |
|
|
'event_address', |
|
|
'event_city', |
|
|
'event_name', |
|
|
'event_start_date_time', |
|
|
'event_start_date_time_date', |
|
|
'event_start_date_time_time', |
|
|
'event_url', |
|
|
'event_venue_capacity', |
|
|
'event_venue_name', |
|
|
'f-a94e32ce9d2f414b4c3b-email', |
|
|
'f__camp-llocs_poi', |
|
|
'f__camp-llocs_poi1', |
|
|
'f__camp-llocs_poi2', |
|
|
'f__camp-llocs_poi_d', |
|
|
'f__checkbox__1', |
|
|
'f__checkbox__3', |
|
|
'f__checkbox__4', |
|
|
'f__checkbox__5', |
|
|
'f__checkbox__8', |
|
|
'f_submit_login', |
|
|
'facebookLink', |
|
|
'fechaNac', |
|
|
'first name', |
|
|
'first', |
|
|
'first-name', |
|
|
'first_name', |
|
|
'first_name-4', |
|
|
'firstName', |
|
|
'FirstName', |
|
|
'firstname', |
|
|
'FiscalCode', |
|
|
'flight-search-type-option', |
|
|
'fname', |
|
|
'form1:ape1PER', |
|
|
'form1:ape2PER', |
|
|
'form1:confirmacionEmail', |
|
|
'form1:confirmPass', |
|
|
'form1:documentoPER', |
|
|
'form1:email', |
|
|
'form1:idioma', |
|
|
'form1:j_id_jsp_1264618786_582pc5', |
|
|
'form1:nombrePER', |
|
|
'form1:nombreUsr', |
|
|
'form1:nombreViaPER', |
|
|
'form1:numeroViaPER', |
|
|
'form1:pisoPER', |
|
|
'form1:portalPER', |
|
|
'form1:preguntaRecordatorio', |
|
|
'form1:puertaPER', |
|
|
'form1:respuestaRecordatorio', |
|
|
'form1:tipoViaFacturaPER', |
|
|
'form1:tipoViaPER', |
|
|
'form1:usoCuenta', |
|
|
'form_address_key', |
|
|
'free', |
|
|
'fsurname', |
|
|
'fttkhcjf', |
|
|
'full_name', |
|
|
'fullname', |
|
|
'gamer_account', |
|
|
'gender', |
|
|
'Github', |
|
|
'GmailAddress', |
|
|
'Go', |
|
|
'googleLink', |
|
|
'group1', |
|
|
'group[10469][1]', |
|
|
'hide_password', |
|
|
'hide_register[password][second]', |
|
|
'http_passwd', |
|
|
'http_passwdConfirm', |
|
|
'i_agree_check', |
|
|
'iagree', |
|
|
'iagreebutton', |
|
|
'id_country', |
|
|
'id_country_invoice', |
|
|
'id_gender', |
|
|
'id_state', |
|
|
'id_state_invoice', |
|
|
'idioma', |
|
|
'ignoreEmailDup', |
|
|
'im_id', |
|
|
'image_type', |
|
|
'image_verify_code', |
|
|
'indexbbstopics', |
|
|
'indexlatestadded', |
|
|
'indexlatestcomments', |
|
|
'indexlatestparties', |
|
|
'indexlatestreleased', |
|
|
'indexojnews', |
|
|
'indexoneliner', |
|
|
'indextopglops', |
|
|
'indextopkeops', |
|
|
'indextopprods', |
|
|
'indexwatchlist', |
|
|
'india_payment_selection', |
|
|
'inf_field_City', |
|
|
'inf_field_Email', |
|
|
'inf_field_FirstName', |
|
|
'inf_field_LastName', |
|
|
'input_10', |
|
|
'input_12', |
|
|
'input_14', |
|
|
'input_16.1', |
|
|
'input_1_2', |
|
|
'input_2.3', |
|
|
'input_2.6', |
|
|
'input_6.6', |
|
|
'input_9.1', |
|
|
'inputEmail', |
|
|
'inputLanguage', |
|
|
'inputLocation', |
|
|
'inputPass2', |
|
|
'interval', |
|
|
'is_subscribed', |
|
|
'itemsPerPageInTable', |
|
|
'j_id105:checkboxAceptarCondiciones', |
|
|
'j_id105:checkboxAceptarLOPD', |
|
|
'j_id105:j_id253', |
|
|
'j_id105:pais', |
|
|
'j_id105:resPartnerAddresscif', |
|
|
'j_id105:resPartnerAddressCity', |
|
|
'j_id105:resPartnerAddresspasswordConfirma', |
|
|
'j_id105:resPartnerAddressphone', |
|
|
'j_id105:resPartnerAddressProvincia', |
|
|
'j_id105:resPartnerAddressstreet', |
|
|
'j_id105:resPartnerAddresszip', |
|
|
'j_id105:resPartnerEmail', |
|
|
'j_id105:resPartnername', |
|
|
'j_id105:resPartnersurname', |
|
|
'j_id105:resPartnersurname2', |
|
|
'jabber', |
|
|
'job_title_level', |
|
|
'jobTitle', |
|
|
'jrlsolej', |
|
|
'keep_logged_in', |
|
|
'keepMeSignInOption', |
|
|
'keyval', |
|
|
'keywords', |
|
|
'lang', |
|
|
'lang-chooser', |
|
|
'language', |
|
|
'language-selector', |
|
|
'LanguageSelect', |
|
|
'last name', |
|
|
'last', |
|
|
'last-name', |
|
|
'last_name', |
|
|
'last_name-4', |
|
|
'lastname', |
|
|
'LastName', |
|
|
'lastName', |
|
|
'LinkedIn', |
|
|
'lname', |
|
|
'lnshdven', |
|
|
'locale', |
|
|
'localidad', |
|
|
'location', |
|
|
'location_check_1', |
|
|
'location_check_2', |
|
|
'log_nombre', |
|
|
'log_persistent', |
|
|
'log_pwd', |
|
|
'login', |
|
|
'Login', |
|
|
'LOGIN', |
|
|
'login_submit_dummy', |
|
|
'login_threadless', |
|
|
'loginButton', |
|
|
'loginForm.remember', |
|
|
'LoginForm[email]', |
|
|
'LoginForm[password]', |
|
|
'logonId', |
|
|
'logonPasswordVerify', |
|
|
'lugar', |
|
|
'lugar_instalacion', |
|
|
'mail', |
|
|
'mailinglist', |
|
|
'member ID (additional)', |
|
|
'member name', |
|
|
'member since', |
|
|
'member[password_confirmation]', |
|
|
'membernext', |
|
|
'mesNac', |
|
|
'mobile', |
|
|
'mobile_country', |
|
|
'mobile_intl', |
|
|
'mobilePhone', |
|
|
'months', |
|
|
'móvil', |
|
|
'n_pass2', |
|
|
'nationalId', |
|
|
'nationalIdentificationNumber', |
|
|
'nationality', |
|
|
'new_password', |
|
|
'new_password1', |
|
|
'new_password2', |
|
|
'NewPasswordConfirm', |
|
|
'newPinCheck', |
|
|
'newsletter', |
|
|
'newsletters[317]', |
|
|
'NewUserContactDetails.ConfirmPassword', |
|
|
'NewUserContactDetails.Email', |
|
|
'NewUserContactDetails.FirstName', |
|
|
'NewUserContactDetails.LastName', |
|
|
'NewUserLogin.NewEmail', |
|
|
'nick_name', |
|
|
'nickname', |
|
|
'no_name', |
|
|
'nombre', |
|
|
'NOMBRE', |
|
|
'nombreVia', |
|
|
'numDoc', |
|
|
'objecttype', |
|
|
'op', |
|
|
'options', |
|
|
'options[adminemail]', |
|
|
'original email', |
|
|
'original mail', |
|
|
'p2', |
|
|
'pais', |
|
|
'pApellido', |
|
|
'pasPassw_2', |
|
|
'pass', |
|
|
'pass1-text', |
|
|
'PASS2', |
|
|
'pass2', |
|
|
'pass[pass2]', |
|
|
'passwd2', |
|
|
'PasswdAgain', |
|
|
'password-confirm', |
|
|
'Password2', |
|
|
'password2', |
|
|
'password_2', |
|
|
'password_again', |
|
|
'password_answer', |
|
|
'password_confirm', |
|
|
'password_confirmar', |
|
|
'password_confirmation', |
|
|
'password_confirmation_again', |
|
|
'password_question', |
|
|
'password_repeat', |
|
|
'password_two', |
|
|
'password_verify', |
|
|
'passwordAgain', |
|
|
'passwordCheck', |
|
|
'PasswordConf', |
|
|
'passwordconfirm', |
|
|
'passwordConfirm', |
|
|
'passwordConfirmation', |
|
|
'passwordResetRequest[password][second]', |
|
|
'passwrd', |
|
|
'passwrd1', |
|
|
'passwrd2', |
|
|
'payment_type', |
|
|
'PC759$AddressCtl$tb_AddressLine', |
|
|
'PC759$AddressCtl$tb_CityUK', |
|
|
'PC759$AddressCtl$tb_ZipUK', |
|
|
'PC759$btnRegRequest', |
|
|
'PC759$dpBirthDate', |
|
|
'PC759$txtConfirmPwdR', |
|
|
'PC759$txtEmailRR', |
|
|
'PC759$txtFirstName', |
|
|
'PC759$txtLastName', |
|
|
'PC759$txtPhone', |
|
|
'persistent', |
|
|
'PersistentCookie', |
|
|
'personTitle', |
|
|
'phone', |
|
|
'Phone', |
|
|
'phone1', |
|
|
'phone_1', |
|
|
'phone_intl', |
|
|
'phone_mobile', |
|
|
'phone_number', |
|
|
'phoneNumber', |
|
|
'phpcan_action', |
|
|
'piso', |
|
|
'poblacion', |
|
|
'policies', |
|
|
'policy', |
|
|
'portal', |
|
|
'postal_code', |
|
|
'postcode', |
|
|
'prefix_phone_1', |
|
|
'primaryRole', |
|
|
'primaryUse', |
|
|
'privacy', |
|
|
'prodlistprods', |
|
|
'profile.contactme', |
|
|
'Profile.FirstName', |
|
|
'profile.gender', |
|
|
'Profile.Gender', |
|
|
'Profile.LastName', |
|
|
'profile_perfil_p[field_primer_apellido][und][0][value]', |
|
|
'profile_perfil_p[field_usuario_nombre][und][0][value]', |
|
|
'profileFirstName', |
|
|
'profileLastName', |
|
|
'profilephone_number', |
|
|
'promotion_code', |
|
|
'provideProducts', |
|
|
'provider', |
|
|
'province', |
|
|
'provincia', |
|
|
'pt[]', |
|
|
'puerta', |
|
|
'pw1', |
|
|
'pw2', |
|
|
'pwd', |
|
|
'qa_answer', |
|
|
'qs', |
|
|
'quantity_1142_0_0_0', |
|
|
'quantity_2668_609_0_0', |
|
|
'quantity_3800_0_0_0', |
|
|
'quantity_3804_979_0_0', |
|
|
'quantity_5081_0_0_0', |
|
|
'quantity_744_0_0_0', |
|
|
'query', |
|
|
'QuestionCode1', |
|
|
'r_address/1.company_name', |
|
|
'radioReConsider', |
|
|
'recaptcha_response_field', |
|
|
'recognize', |
|
|
'RecoveryPhoneNumber', |
|
|
'reenter_email', |
|
|
'reenter_password', |
|
|
'regenerar', |
|
|
'region_id', |
|
|
'register', |
|
|
'register.birth.day', |
|
|
'register.birth.month', |
|
|
'register.birth.year', |
|
|
'register_vv[code]', |
|
|
'register_vv[q][1]', |
|
|
'register_vv[q][337]', |
|
|
'register_vv[q][358]', |
|
|
'registerambit', |
|
|
'registercarrera', |
|
|
'registercheck', |
|
|
'registercognoms', |
|
|
'registerform.deliverycountry', |
|
|
'registerform.deliverytitle', |
|
|
'registerform.paymentaddress1', |
|
|
'registerform.paymentcountry', |
|
|
'registerform.paymentdayphone', |
|
|
'registerform.paymentfirstname', |
|
|
'registerform.paymentmobilephone', |
|
|
'registerform.paymentsurname', |
|
|
'registerform.paymenttitle', |
|
|
'registerform.paymenttown', |
|
|
'registerform.paymentzip', |
|
|
'registerform.repeat', |
|
|
'registerform.selectasdelivery', |
|
|
'registernom', |
|
|
'registerpass', |
|
|
'registeruser', |
|
|
'registrarse', |
|
|
'regSubmit', |
|
|
'remember', |
|
|
'remember_me', |
|
|
'rememberme', |
|
|
'rememberMe', |
|
|
'rememberMe:checkbox', |
|
|
'rememberPassword', |
|
|
'reminder answer', |
|
|
'reminder question', |
|
|
'repassword', |
|
|
'repeat_user_password', |
|
|
'repeatEmail', |
|
|
'repeatPassword', |
|
|
'RetypePassword', |
|
|
'ringkosk', |
|
|
'rNewPassword', |
|
|
'role', |
|
|
'rsa', |
|
|
'sa', |
|
|
'sApellido', |
|
|
'savePassword', |
|
|
'search', |
|
|
'searcharea', |
|
|
'searchGranularity', |
|
|
'searchin', |
|
|
'searchprods', |
|
|
'searchType', |
|
|
'searchwords', |
|
|
'secretQuestion', |
|
|
'Security questions', |
|
|
'segments_select[]', |
|
|
'select-type', |
|
|
'select_language', |
|
|
'selector-currency', |
|
|
'selIsClass', |
|
|
'selIsWantFace', |
|
|
'selIsWantTextChat', |
|
|
'selX3', |
|
|
'selX3a', |
|
|
'selX4', |
|
|
'selX6', |
|
|
'selX6a', |
|
|
'selX6b', |
|
|
'send', |
|
|
'send_user_notification', |
|
|
'sex', |
|
|
'sexo', |
|
|
'sgnBt', |
|
|
'ShippingCountryID', |
|
|
'signIn', |
|
|
'signin', |
|
|
'SignUp', |
|
|
'signup-name', |
|
|
'signup[terms_of_service]', |
|
|
'signup[username]', |
|
|
'signup_email_mask', |
|
|
'signup_name', |
|
|
'signup_password_mask', |
|
|
'SignupForm[firstName]', |
|
|
'SignupForm[lastName]', |
|
|
'skype', |
|
|
'slengpung', |
|
|
'spareEmail', |
|
|
'spree_user[password_confirmation]', |
|
|
'sq', |
|
|
'ssh.Password2', |
|
|
'state', |
|
|
'state_tf', |
|
|
'street', |
|
|
'Street', |
|
|
'street_address', |
|
|
'styleid', |
|
|
'subdomain', |
|
|
'Submit', |
|
|
'submit', |
|
|
'submit-30887', |
|
|
'submit-button', |
|
|
'submit1', |
|
|
'submit_button', |
|
|
'submit_search', |
|
|
'submitAccount', |
|
|
'submitAddDiscount', |
|
|
'submitbutton', |
|
|
'submitContext', |
|
|
'SubmitLogin', |
|
|
'submitNewsletter', |
|
|
'subscribe', |
|
|
'subscribe[]', |
|
|
'subscribe_to_email_communication', |
|
|
'subscribed_to_newsletter', |
|
|
'surname', |
|
|
'surnames', |
|
|
'swapSize', |
|
|
'telefono', |
|
|
'telefono2', |
|
|
'telekom_sitereportbundle_user[password][Repeat]', |
|
|
'telekom_sitereportbundle_user[whoWill]', |
|
|
'Template$FormControl$Button1', |
|
|
'Template$FormControl$txtCodigoActual', |
|
|
'Template$FormControl$txtNuevoCodigo', |
|
|
'term', |
|
|
'terms', |
|
|
'terms[term]', |
|
|
'terms_of_use', |
|
|
'termsAgree', |
|
|
'termsChecked', |
|
|
'TermsOfService', |
|
|
'TestForApplications', |
|
|
'time_zone', |
|
|
'timezone', |
|
|
'timezoneoffset', |
|
|
'tip_doc', |
|
|
'tipoDoc', |
|
|
'tipoVia', |
|
|
'title_key', |
|
|
'titulo', |
|
|
'topicposts', |
|
|
'tos', |
|
|
'tos_agree', |
|
|
'tosPrivacy', |
|
|
'toua_consent', |
|
|
'Twitter', |
|
|
'txtEmail2', |
|
|
'type_account', |
|
|
'unlimited', |
|
|
'up_email', |
|
|
'up_password', |
|
|
'up_password_', |
|
|
'up_user', |
|
|
'updates', |
|
|
'usage-type', |
|
|
'user-type', |
|
|
'user[account_type]', |
|
|
'user[country]', |
|
|
'user[country_code]', |
|
|
'user[email]', |
|
|
'user[email_confirmation]', |
|
|
'user[email_volume]', |
|
|
'user[first_name]', |
|
|
'user[firstname]', |
|
|
'user[full_name]', |
|
|
'user[last_name]', |
|
|
'user[lastname]', |
|
|
'user[location]', |
|
|
'user[name]', |
|
|
'user[organisation][name]', |
|
|
'user[over_13_and_accept_terms_and_conditions]', |
|
|
'user[password]', |
|
|
'user[password_confirm]', |
|
|
'user[password_confirmation]', |
|
|
'user[registration_company]', |
|
|
'user[registration_role]', |
|
|
'user[role]', |
|
|
'user[terms_of_service]', |
|
|
'user[time_zone]', |
|
|
'user[weekly_newsletter]', |
|
|
'user_email', |
|
|
'user_email2', |
|
|
'user_login', |
|
|
'user_login-4', |
|
|
'user_name', |
|
|
'user_pass2', |
|
|
'user_password-4', |
|
|
'user_password_confirmation', |
|
|
'user_registered', |
|
|
'userAcceptsTermsOfService', |
|
|
'usercomments', |
|
|
'UserDto.UserCredential.ChallengeAnswer', |
|
|
'UserDto.UserCredential.ChallengeQuestionId', |
|
|
'UserDto.UserCredential.ConfirmPassword', |
|
|
'usergroups', |
|
|
'userlistusers', |
|
|
'userlogos', |
|
|
'usernfos', |
|
|
'userparties', |
|
|
'userPrincipal##alias', |
|
|
'userPrincipal##confirmEmail', |
|
|
'userPrincipal##confirmPassword', |
|
|
'userPrincipal##secretAnswer', |
|
|
'userPrincipal##secretQuestion', |
|
|
'userPrincipal##spamBlocker', |
|
|
'userprods', |
|
|
'userrulez', |
|
|
'userscreenshots', |
|
|
'usersucks', |
|
|
'usuarios[apodo]', |
|
|
'usuarios[nombre]', |
|
|
'usuarios[sexo]', |
|
|
'vb_login_password', |
|
|
'Vencemento', |
|
|
'verify', |
|
|
'vp', |
|
|
'web_user[password_confirmation]', |
|
|
'weblog_title', |
|
|
'wp-submit', |
|
|
'wpLoginattempt', |
|
|
'wpLoginAttempt', |
|
|
'wpMailmypassword', |
|
|
'wpRemember', |
|
|
'wt-msisdn', |
|
|
'years', |
|
|
'yt0', |
|
|
'yt1', |
|
|
'za-signup-btn', |
|
|
'zero', |
|
|
'zip', |
|
|
'zipcode', |
|
|
'Zipcode', |
|
|
'zone_id', |
|
|
'zxdemo', 'mes', 'card_expiration_year', 'card_expiration_month', 'num', 'card_number', 'mes', 'birth', 'birth date', 'birth_date', 'card_code', 'password', 'user_password', 'passwd', 'contrasena', 'login_passwd', 'cpassword', 'login_password', 'admin_password', 'username', 'usuario', 'Passwd'] |
|
|
|
|
|
|
|
|
def eprint(*args, **kwargs): |
|
|
print(*args, file=sys.stderr, **kwargs) |
|
|
|
|
|
import os |
|
|
import errno |
|
|
import shutil |
|
|
import contextlib |
|
|
import tempfile |
|
|
import base64 |
|
|
import subprocess |
|
|
import json |
|
|
import uuid |
|
|
import xmltodict |
|
|
import getpass |
|
|
|
|
|
def is_tool(name): |
|
|
"""Check whether `name` is on PATH and marked as executable.""" |
|
|
@@ -53,6 +856,7 @@ def is_tool(name): |
|
|
|
|
|
return which(name) is not None |
|
|
|
|
|
|
|
|
def static_vars(**kwargs): |
|
|
""" |
|
|
Decorates a function with static variables and initializes them. |
|
|
@@ -66,6 +870,7 @@ def decorate(func): |
|
|
return func |
|
|
return decorate |
|
|
|
|
|
|
|
|
@contextlib.contextmanager |
|
|
def write_open(filename=None): |
|
|
if filename and filename != '-': |
|
|
@@ -82,6 +887,7 @@ def write_open(filename=None): |
|
|
fh.close() |
|
|
shutil.move(tempPath, filename) |
|
|
|
|
|
|
|
|
def safe_move(src, dst): |
|
|
"""Rename a file from ``src`` to ``dst``. |
|
|
|
|
|
@@ -118,14 +924,14 @@ def safe_move(src, dst): |
|
|
else: |
|
|
raise |
|
|
|
|
|
|
|
|
def get_uuid(name): |
|
|
""" |
|
|
Computes the UUID of the given string as required by KeePass XML standard |
|
|
https://github.com/keepassxreboot/keepassxc-specs/blob/master/kdbx-xml/rfc.txt |
|
|
""" |
|
|
#name = name.encode('ascii', 'ignore') |
|
|
uid = uuid.uuid5(uuid.NAMESPACE_DNS, name) |
|
|
return base64.b64encode(uid.bytes).decode("utf-8") |
|
|
return base64.b64encode(uid.bytes).decode("utf-8") |
|
|
|
|
|
|
|
|
def get_folder(f): |
|
|
@@ -134,7 +940,7 @@ def get_folder(f): |
|
|
""" |
|
|
return dict(UUID=get_uuid(f['name']), |
|
|
Name=f['name']) |
|
|
|
|
|
|
|
|
|
|
|
def get_protected_value(v): |
|
|
""" |
|
|
@@ -152,32 +958,72 @@ def get_fields(subitem, protected=[]): |
|
|
fields = [] |
|
|
|
|
|
for k, v in subitem.items(): |
|
|
# check if it's protected |
|
|
if k in protected: |
|
|
v = get_protected_value(v) |
|
|
fields.append(dict(Key=k, Value=v)) |
|
|
if v is not None: |
|
|
# check if it's protected |
|
|
k = get_correct_name(k) |
|
|
if k in protected: |
|
|
v = get_protected_value(v) |
|
|
fields.append(dict(Key=k, Value=v)) |
|
|
|
|
|
return fields |
|
|
|
|
|
|
|
|
def get_correct_name(name): |
|
|
lower = name.lower() |
|
|
if lower in ['username', 'usuario', 'alias']: |
|
|
name = 'Alias' |
|
|
if lower in ['name', 'accountname']: |
|
|
name = 'Name' |
|
|
elif lower in ['email', 'user_email', 'email_address', 'login_email']: |
|
|
name = 'Email' |
|
|
elif lower in ['address']: |
|
|
name = 'Address' |
|
|
elif lower in ['numero', 'number', ]: |
|
|
name = 'Number' |
|
|
elif lower in ['bank name', ]: |
|
|
name = 'BankName' |
|
|
elif lower in ['name on account', ]: |
|
|
name = 'NameOnAccount' |
|
|
elif lower in ['cardholder name', 'cardholderName']: |
|
|
name = 'CardholderName' |
|
|
elif lower in ['verification number', ]: |
|
|
name = 'VerificationNumber' |
|
|
elif lower in ['website', 'url']: |
|
|
name = 'Website' |
|
|
elif lower in ['type', 'brand']: |
|
|
name = 'Brand' |
|
|
elif lower == 'pubilc key' or lower == 'public key': |
|
|
name = 'PublicKey' |
|
|
elif lower == 'pirvate key' or lower == 'private key': |
|
|
name = 'PrivateKey' |
|
|
return name |
|
|
|
|
|
|
|
|
@static_vars(binary_id=0, binaries=[]) |
|
|
def get_entry(e): |
|
|
""" |
|
|
Returns a dict of the input entry (item from Bitwarden) |
|
|
Parses the title, username, password, urls, notes, and custom fields. |
|
|
""" |
|
|
# Parse custom fields, protecting as necessary |
|
|
fields = [] |
|
|
done = [] |
|
|
# Parse custom fields, protecting as necessary |
|
|
if 'fields' in e: |
|
|
for f in e['fields']: |
|
|
if f['name'] is not None: |
|
|
if f['name'] not in banned and f['value'] is not None: |
|
|
# get value |
|
|
value = f['value'] |
|
|
# if protected? |
|
|
if f['type'] == 1: |
|
|
value = get_protected_value(value) |
|
|
# put together |
|
|
fields.append(dict(Key=f['name'], Value=value)) |
|
|
|
|
|
# get key |
|
|
key = get_correct_name(f['name']) |
|
|
if key not in done: |
|
|
done.append(key) |
|
|
found.append(key) |
|
|
# if protected? |
|
|
if f['type'] == 1 or key in ['PrivateKey', 'VerificationNumber', 'storePassword', 'PIN']: |
|
|
value = get_protected_value(value) |
|
|
# put together |
|
|
fields.append(dict(Key=key, Value=value)) |
|
|
|
|
|
# default values |
|
|
urls = '' |
|
|
username, password = '', '' |
|
|
@@ -189,19 +1035,20 @@ def get_entry(e): |
|
|
if 'uris' in login: |
|
|
urls = [u['uri'] for u in login['uris']] |
|
|
urls = ','.join(urls) |
|
|
|
|
|
|
|
|
# get username and password |
|
|
username = login['username'] |
|
|
password = login['password'] |
|
|
username = login['username'] |
|
|
password = login['password'] |
|
|
|
|
|
# add totop to fields as protected |
|
|
fields.append(dict(Key='totp', |
|
|
fields.append(dict(Key='totp', |
|
|
Value=get_protected_value(login['totp']))) |
|
|
|
|
|
# Parse Card items |
|
|
if 'card' in e: |
|
|
# Make number a protected field |
|
|
fields.extend(get_fields(e['card'], protected=['number'])) |
|
|
fields.extend(get_fields(e['card'], protected=[ |
|
|
'number', 'Number', 'VerificationNumber', 'verification number', 'PIN', 'code', 'Code'])) |
|
|
|
|
|
# Parse Identity items |
|
|
if 'identity' in e: |
|
|
@@ -211,35 +1058,36 @@ def get_entry(e): |
|
|
attachments = [] |
|
|
if 'attachments' in e: |
|
|
for a in e['attachments']: |
|
|
if a['id'] is not None: |
|
|
#append attachment reference |
|
|
if a['id'] is not None: |
|
|
# append attachment reference |
|
|
attachments.append( |
|
|
dict( |
|
|
Key=a['fileName'], |
|
|
Value={'@Ref': get_entry.binary_id } |
|
|
Value={'@Ref': get_entry.binary_id} |
|
|
) |
|
|
) |
|
|
|
|
|
#add binary data to function static list and update static counter |
|
|
att = get_bw_attachment(a['id'],e['id']) |
|
|
# add binary data to function static list and update static counter |
|
|
att = get_bw_attachment(a['id'], e['id']) |
|
|
get_entry.binaries.append( |
|
|
dict({'@ID': get_entry.binary_id, '@Compressed': 'False', '#text': att}) |
|
|
dict({'@ID': get_entry.binary_id, |
|
|
'@Compressed': 'False', '#text': att}) |
|
|
) |
|
|
get_entry.binary_id += 1 |
|
|
|
|
|
|
|
|
# Check it's not None |
|
|
username = username or '' |
|
|
password = password or '' |
|
|
|
|
|
# assemble the entry into a dict with a UUID |
|
|
entry = dict(UUID=get_uuid(e['name']), |
|
|
String=[dict(Key='Title', Value=e['name']), |
|
|
dict(Key='UserName', Value=username), |
|
|
dict(Key='Password', Value=get_protected_value(password)), |
|
|
dict(Key='URL', Value=urls), |
|
|
dict(Key='Notes', Value=notes) |
|
|
] + fields) |
|
|
|
|
|
String=[dict(Key='Title', Value=e['name']), |
|
|
dict(Key='UserName', Value=username), |
|
|
dict(Key='Password', Value=get_protected_value(password)), |
|
|
dict(Key='URL', Value=urls), |
|
|
dict(Key='Notes', Value=notes) |
|
|
] + fields) |
|
|
|
|
|
if (attachments): |
|
|
entry.update(dict(Binary=attachments)) |
|
|
|
|
|
@@ -257,13 +1105,15 @@ def get_cmd_output(cmd): |
|
|
|
|
|
return output |
|
|
|
|
|
|
|
|
def bw_logout(): |
|
|
""" |
|
|
Bitwarden logout |
|
|
""" |
|
|
cmd = 'bw logout --raw' |
|
|
subprocess.run(cmd, shell=True, capture_output=True) |
|
|
|
|
|
|
|
|
def get_bw_data(): |
|
|
""" |
|
|
Gets the folders and items from Bitwarden CLI |
|
|
@@ -278,6 +1128,7 @@ def get_bw_data(): |
|
|
|
|
|
return folders, items |
|
|
|
|
|
|
|
|
def secure_delete(path, passes=1): |
|
|
""" |
|
|
Safely delete a file by overwriting it with random data |
|
|
@@ -289,14 +1140,16 @@ def secure_delete(path, passes=1): |
|
|
delfile.write(os.urandom(length)) |
|
|
os.remove(path) |
|
|
|
|
|
|
|
|
def get_bw_attachment(id, itemid): |
|
|
""" |
|
|
Gets an attachment from Bitwarden CLI |
|
|
""" |
|
|
with tempfile.TemporaryDirectory() as tmpdir: |
|
|
cmd = 'bw get attachment --itemid '+itemid+' '+id+' --output '+tmpdir+'/ --raw --session '+main.bw_session |
|
|
cmd = 'bw get attachment --itemid '+itemid+' '+id + \ |
|
|
' --output '+tmpdir+'/ --raw --session '+main.bw_session |
|
|
path = get_cmd_output(cmd) |
|
|
|
|
|
|
|
|
if not os.path.isfile(path): |
|
|
eprint("Error downloading attachment:", id) |
|
|
raise Exception |
|
|
@@ -310,12 +1163,13 @@ def get_bw_attachment(id, itemid): |
|
|
|
|
|
|
|
|
@static_vars(bw_session='') |
|
|
def main(bw_user, output_file, |
|
|
xml_output: ('saves an UNENCRYPTED KeePass 2 XML file', 'flag', 'x'), |
|
|
diff_pass: ('different passwords for Bitwarden and KeePass file', 'flag', 'd'), |
|
|
bw_password: ('Bitwarden password (prompted if not provided)', 'option')=None, |
|
|
kee_password: ('KeePass password (prompted if not provided)', 'option')=None |
|
|
): |
|
|
def main(bw_user, output_file, |
|
|
xml_output: ('saves an UNENCRYPTED KeePass 2 XML file', 'flag', 'x'), |
|
|
diff_pass: ('different passwords for Bitwarden and KeePass file', 'flag', 'd'), |
|
|
bw_password: ('Bitwarden password (prompted if not provided)', 'option') = None, |
|
|
kee_password: ( |
|
|
'KeePass password (prompted if not provided)', 'option') = None |
|
|
): |
|
|
""" |
|
|
Main function |
|
|
""" |
|
|
@@ -324,23 +1178,24 @@ def main(bw_user, output_file, |
|
|
eprint("Bitwarden cli not found") |
|
|
raise Exception |
|
|
|
|
|
#Log out any existing session |
|
|
# Log out any existing session |
|
|
bw_logout() |
|
|
|
|
|
# Bitwarden login |
|
|
if bw_password is None: |
|
|
bw_password = getpass.getpass(prompt='Bitwarden password: ') |
|
|
|
|
|
cmd = 'bw --raw login '+str(bw_user) |
|
|
res = subprocess.run(cmd, input=bytearray(bw_password, 'utf-8'), shell=True, capture_output=True) |
|
|
res = subprocess.run(cmd, input=bytearray( |
|
|
bw_password, 'utf-8'), shell=True, capture_output=True) |
|
|
if res.returncode != 0: |
|
|
eprint("Wrong password") |
|
|
raise SystemExit |
|
|
|
|
|
main.bw_session = res.stdout.decode() |
|
|
del res #delete result object which has the password as a cmd argument |
|
|
del res # delete result object which has the password as a cmd argument |
|
|
|
|
|
#set keepass password |
|
|
# set keepass password |
|
|
if kee_password is None: |
|
|
if diff_pass: |
|
|
kee_password = getpass.getpass(prompt='KeePass password: ') |
|
|
@@ -350,11 +1205,10 @@ def main(bw_user, output_file, |
|
|
|
|
|
# get data from bw |
|
|
bw_folders, bw_items = get_bw_data() |
|
|
|
|
|
|
|
|
# parse all entries |
|
|
entries = [get_entry(e) for e in bw_items] |
|
|
|
|
|
|
|
|
|
|
|
# loop over folders |
|
|
# bw_folders = d['folders'] |
|
|
folders = [] |
|
|
@@ -363,45 +1217,49 @@ def main(bw_user, output_file, |
|
|
# parse the folder |
|
|
folder = get_folder(f) |
|
|
folder_id = f['id'] |
|
|
|
|
|
|
|
|
# loop on entries in this folder |
|
|
folder_entries = [] |
|
|
for entry, item in zip(entries, bw_items): |
|
|
if item['folderId'] == folder_id: |
|
|
folder_entries.append(entry) |
|
|
|
|
|
|
|
|
# NoFolder (with None id) |
|
|
if folder_id is None: |
|
|
root_entries = folder_entries |
|
|
# Normal folder |
|
|
else: |
|
|
if len(folder_entries) > 0: |
|
|
folder['Entry'] = folder_entries |
|
|
|
|
|
folder['Entry'] = folder_entries |
|
|
|
|
|
# add to output folder |
|
|
folders.append(folder) |
|
|
|
|
|
|
|
|
# Root group |
|
|
root_group = get_folder(dict(name='Root')) |
|
|
root_group['Group'] = folders |
|
|
|
|
|
# add items to root folder |
|
|
if len(root_entries) > 0: |
|
|
root_group['Entry'] = root_entries |
|
|
|
|
|
|
|
|
# Root element |
|
|
root=dict(Group=root_group) |
|
|
root = dict(Group=root_group) |
|
|
|
|
|
# Meta element |
|
|
meta = dict(Generator='bitwarden export', MasterKeyChangeForce=-1, MasterKeyChangeRec=-1) |
|
|
meta = dict(Generator='bitwarden export', |
|
|
MasterKeyChangeForce=-1, MasterKeyChangeRec=-1) |
|
|
|
|
|
# add binary files from attachments |
|
|
if (get_entry.binaries): |
|
|
meta.update(dict(Binaries=dict(Binary=get_entry.binaries))) |
|
|
|
|
|
|
|
|
# xml document contents |
|
|
xml = dict(KeePassFile=dict(Meta=meta, Root=root)) |
|
|
|
|
|
found.sort() |
|
|
print(found) |
|
|
|
|
|
if xml_output: |
|
|
# export unencrypted XML |
|
|
with write_open(output_file) as out: |
|
|
@@ -413,28 +1271,29 @@ def main(bw_user, output_file, |
|
|
eprint("keepassxc-cli not found") |
|
|
raise Exception |
|
|
|
|
|
#write XML and export to keepass |
|
|
# write XML and export to keepass |
|
|
with tempfile.NamedTemporaryFile() as xml_out: |
|
|
xml_out.write(bytearray(xmltodict.unparse(xml, pretty=True), 'utf-8')) |
|
|
xml_out.flush() |
|
|
with tempfile.TemporaryDirectory() as tmpdir: |
|
|
output_tempfile = tmpdir + '/tmp' |
|
|
cmd = 'keepassxc-cli import '+xml_out.name+' '+output_tempfile |
|
|
res = subprocess.run(cmd, input=bytearray(kee_password, 'utf-8'), shell=True, capture_output=True) |
|
|
res = subprocess.run(cmd, input=bytearray( |
|
|
kee_password, 'utf-8'), shell=True, capture_output=True) |
|
|
if res.returncode != 0: |
|
|
eprint("Error exporting KeePass file") |
|
|
raise SystemExit |
|
|
del res |
|
|
safe_move(output_tempfile, output_file) |
|
|
|
|
|
#cleanup and exit |
|
|
# cleanup and exit |
|
|
del kee_password |
|
|
bw_logout() |
|
|
sys.exit(0) |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
import plac; |
|
|
import plac |
|
|
try: |
|
|
plac.call(main) |
|
|
except SystemExit: |
|
|
|