I have cable internet which requires me to login though a web page. It's annoying how it resets every day at 8 and 12am. I wanted to write a python script which will automate the login process. I've read many StackOverflow solutions so far, nothing has worked. I have tried Requests, Twill, RoboBrowser etc.
Upon inspecting the page source I came across a doLogin() ajax script, which is triggered by login button. Here is the full page source.
following is one of my implementations which fails
import requests
# Fill in your details here to be posted to the login form.
payload = {
'action': 'http://10.10.0.1/login',
'actualusername': 'username',
'actualpassword': 'password'
}
# Use 'with' to ensure the session context is closed after use.
with requests.Session() as s:
p = s.post("http://103.251.83.134/captiveportal/Default.aspx", data=payload)
# print the html returned or something more intelligent to see if it's a successful login page.
print p.text
# An authorised request.
#r = s.get('http://www.google.com')
#print r.text
EDIT: Solution
I used Selenium WebDriver to fix this. Check answer.
Use Selenium :) Download ChromeDriver to the path, make a two-time variable and check the time every minute. If it's 'login time', your browser will pass through the authorization.
from selenium import webdriver
def Authorization_for_broadband():
driver = webdriver.Chrome("C:\YOURPATHTO\CHROMEDRIVER.EXE")
driver.get('http://10.10.0.1/login')
driver.find_element_by_xpath('//*[#id="username"]').send_keys('USERNAME')
driver.find_element_by_xpath('//*[#id="password"]').send_keys('PASSWORD')
driver.find_element_by_xpath('//*[#id="btnLogin"]').click()
driver.close
while(1):
if time=='your-login-period1' or time == 'your-login-period2':
Authorization_for_broadband()
Your URL may be wrong. Looking at the source code it looks like the HTML form is posting data to the http://10.10.0.1/login page and then the doLogin() function is submitting data to Register.aspx?CheckCustomerStatus=1.
Also your payload includes the variable action and you're using a Session object, which I don't think is necessary.
I can't test it since it's a local login page I can't access, but I would try modifying your code to submit the login info to both pages using a simpler POST request
Related
I am in the process of implementing a CSRFProtector (mebjas CSRF-Protector-PHP) referenced on the OWASP website.
I followed the instructions for this library. In all PHP files, I have included the csrfprotector.php file and and called csrfProtector::init(). For JavaScript, I have included the csrfprotector.js file once within the HTML of the page and called
window.addEventListener("DOMContentLoaded", function() {
csrfprotector_init();
}
When I submit a form, I have found that the csrfprotector fails to verify that the tokens are the same. I have modified the CSRF to print out the SESSION and POST variables at this point, so when I visit the page, the following is echoed by the PHP via init() -> authorisePost().
post: {"anticsrf":false, ...}
session: []
403 Access Forbidden by CSRFProtector!
I observe using developer tools no anticsrf token has been added to my cookies.
Since I was wondering why tokens weren't being created, I modified the script to not run authorisePost but instead run refreshToken() and I get tokens each time, but they are different.
post: {"anticsrf":"5ec0ae33dc", ...}
session: {"anticsrf":"cbf30a7d6b", ...}
403 Access Forbidden by CSRFProtector!
I observe using developer tools that the anticsrf token in Cookies is 14dd3db17f in this case.
Is there something that I can do to round down where my problem is coming from, or anything I have missed? Thanks.
Users of my web application are expected to provide bug reports as a GitHub issue, with a pregenerated title and body.
This works perfectly fine using GET for small bodies:
const title = getLastErrorTitle();
const body = getAllTheLogMessages();
window.open(`https://github.com/theuser/therepo/issues/new?title=${encodeURIComponent(title)}&body=${encodeURIComponent(body)}`);
If the user is logged in, GitHub presents the user with a new issue with the title and body already filled out, perfect. If not, GitHub prompts the user to log in and it works the next time.
However, if the body is too large, the GET request fails because the URL becomes too long.
After consulting the manual I tried doing the same with POST but I get a 404 from GitHub with the following test request (jQuery for brevity):
$.ajax({
type: "POST",
url: "https://api.github.com/repos/theuser/therepo/issues",
data: data = {title: "Test", body: "Test Body"},
});
My suspicion is, that the GitHub API was not designed with my use case in mind, but that POST always requires authentication and creates the full issue in one go, without letting the user change it beforehand like it is possible with GET.
How can I transfer the functionality of the GET method over to the POST method? I just want GitHub to present the user, that is currently logged in inside the browser, with a prefilled issue, without needing a token.
You can't. Otherwise, it would be a major CSRF exploit.
However, you can use OAuth authentication that will allow your application to use some features : https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/
Or simply, redirect the user to a new issue page (for exemple with a simple HTML link <a>) with some automatic content, using this pattern :
https://github.com/{theUser}/{theRepo}/issues/new?body={theContentYouWhant}&title={theTitleYouWhant}
Example : https://github.com/CristalTeam/php-api-wrapper/issues/new?body=Hi,%20this%20is%20the%20body%20you%20want&title=Hello,%20this%20is%20a%20prefill%20issue
What I would suggest here is to generate a personal_auth_token at gihub and pass this token in the headers under Authorization field.
To generate personal_auth_token, login to github.com, go to settings -> developers settings -> Personal access tokens and generate one.
Pass this token in headers under Auhtorization: token. So in your AJAX request, it could look something like this:
$.ajax({
url: *yourUrl*
...
beforeSend: function (xhr) {
xhr.setRequestHeader('Authorization', *token*));
},
});
One thing to note here is each of the developers POSTing to the repo will be requiring to generate their access token and you can't push this token on to a public Github repository because of obvious security breach. If you accidentally do so, the token is revoked immediately and you'll be required to create a new one.
I have more than 140 id and password of different web site. I want to open each web site dynamically set set id password and login.
I had try lots of thing ex. iframe, frameset, parent window access, url scripts passed.
but its not working for security. Please help me.
Thank you
You could use Selenium IDE plugin (Firefox only) from Selenium project.
Selenium IDE plugin lets you record your actions on any page and it will generate a script, something like (pseudocode):
openPage('http://google.com');
click("#signinElement");
click("#usernameInputElement")
enter("username");
click("#passwordInputElement")
enter("password");
click("#submitButton")
// ...
openPage('http://amazon.com');
// ...
Then you can edit it, add a loop around the whole script and iterate over your list of credentials.
assuming you want to do it locally and not to create a website
Cross origin issues will indeed occur if you try to change input values on a login provider's web page. To get closer to automation, I suggest opening the browser console after the login page has loaded.
Console, as you probably know, is not just for log, it allows you to write Javascript commands to the page.
If you prepare the following code in advance, all is left to do is just to copy and paste in the console, to control the page elements.
Collect the names of the input and submit elements of each of your account providers.
Something like the following:
var logins = {
yahoo: {
url:'https://login.yahoo.com',
usernameInputName: 'username',
usernameInputValue: 'YOUR_USER_ID_HERE',
usernameStep: true,
usernameStepSubmit: 'signin',
passwordInputName: 'passwd',
passwordInputValue: 'YOUR_PASSWORD_HERE',
submit: 'signin'
},
//google: {...
};
Open your account login page, in this example - https://login.yahoo.com.
Yahoo has two steps of signing in, first - you put your username, submit, then put your password and then submit again. In such case, logins["yahoo"].usernameStep is set to true
If usernameStep is false you submit only once by "clicking" dynamically on logins[LOGIN_NAME].submit:
{
document.getElementsByName(login.usernameInputName)[0].value = login.usernameInputValue;
document.getElementsByName(login.passwordInputName)[0].value = login.passwordInputValue;
document.getElementsByName(login.submit)[0].click();
}
If usernameStep is true you use document.getElementsByName(login.usernameStepSubmit)[0].click(); after putting the username, and then proceed to password and submit.
Hope this helps.
I know there are other similar questions, but none of the answers helped me.
I have an ASP.NET web application hosted in IIS on a server.
The server has a windows operating system with a windows user name, suppose: ServerDomain/ServerUserName.
I have a Main.aspx page. The page has a link tag:
Resend
The page has a script tag and there I have a Java Script function:
function resendHandle(el) {
var clientWindowsName = ?
alert(clientWindowsName );
setCurrentUser(clientWindowsName));
submit();
}
Now suppose a client, who also has a windows operating system with a Windows user name: ClientXDomain/ClientXUserName is browsing my site.
Once he clicks the Resend link, the control flows to resendHandle Java Script function and after "submit" to the Resend method in Main.aspx.cs (behind code file). In this method, I want to retrieve the client windows user name, which is: ClientXDomain/ClientXUserName. Obviously, the aspx.cs is a server code, so if I check there for user identity in this method, I will get: ServerDomain/ServerUserName. But as I've mentioned, I want to get the: ClientXDomain/ClientXUserName in this method.
The clientWindowsName is accessed from the server method with the help of setCurrentUser, so there is no problem for me to transfer the clientWindowsName variable value (within the resendHandle java script function) to the server size.
The problem is that
alert(clientWindowsName );
always returns NULL for me for:
var clientWindowsName = '<%=Page.User.Identity.Name%>';
and for other options I've tried.
Only for:
var clientWindowsName = '<%=Request.LogonUserIdentity.Name.ToString()%>';
it alerts NT AUTHORITYIUSR.
but none of the options gives me the desired user name: ClientXDomain/ClientXUserName.
So, how do I get it? Note that I'm trying to get the value within a Java Script function, maybe I should try to do outside the script tag. Thanks!
EDIT 01: My web config contains:
<authentication mode="Windows"/>
Enable impersonation which will help you to get loggined user identity .
in web.config or it can be set on IIS server please check how to set it .But this is what you are missing .
<identity impersonate="true" />
Hi you need to set impersonation as well this way if user is in active directory then his identity can be passed to code otherwise you will get the identity on account under which it is hosted under IIS.
https://msdn.microsoft.com/en-us/library/aa292118(v=vs.71).aspx
I think you need to configure your website using WIndows Authentication instead of Form authentication, like this https://www.codeproject.com/Articles/94612/Windows-Authentication
I had to disable Anonymous Authentication.
I'm getting conflicting results between the facebook javascript SDK and the python requesthandler variables. The Javascript SDK says my user is not logged in, which is correct, while my template variable that comes from the base request handler says that my user is logged in and displays the name of the user. Is there enough info to tell what is wrong or should I paste the code I think is relevant here? A link to the login page that has the error is here. The example I used is called the runwithfriends demo app from facebook and everything with that app worked except using the logic from the app just from a website without requiring the user to be in the iframe of the app.
Plus I can't seem to get the real-time API working. I can only save userID and not refresh user data - why? I have the code but I'm not sure what's most relevant but here's some of the request handler, the relevant code is basically exactly the same as the one from the demo app:
def render(self, name, **data):
logging.debug('render')
"""Render a template"""
if not data:
logging.debug('no data')
data = {}
data[u'js_conf'] = json.dumps({
u'appId': facebookconf.FACEBOOK_APP_ID,
u'canvasName': facebookconf.FACEBOOK_CANVAS_NAME,
u'userIdOnServer': self.user.id if self.user else None,
})
data[u'logged_in_user'] = self.user #variable that is the problem
data[u'message'] = self.get_message()
data[u'csrf_token'] = self.csrf_token
data[u'canvas_name'] = facebookconf.FACEBOOK_CANVAS_NAME
self.response.out.write(template.render(
os.path.join(
os.path.dirname(__file__), 'templates', name + '.html'),
data))
And even more strange, I can also get the application in a state where the javascript SDK says the user is logged in and the template variable logged_in_user says otherwise. Why are the variables conflicting?
Update: Here are screenshots from the strange login flow. I can go to my page and my name from facebook appears:
Then when I go to next page it also looks alright and has my name
But if I log out then I gets in impossible state: my name + logged out
How can I resolve this strange conflict between js and back-end?
Update: Since I only have this problem for one of my apps I can take what works from my other app and integrate. This page seems to work from my other app: http://cyberfaze.appspot.com/file/20985
Your 'user' is probably referring to the Django user not the Facebook user. Make sure you synchronize the two accounts correctly using a custom authentication backend. It's possible that the accounts get out of sync i.e. if the user switches browsers.
Keep in mind that the Facebook Python SDK will stop working after October 1st unless they update it to Oauth2.0 which is unlikely.
I just updated django-facebook-graph to work with the new authentication flow.