I'm trying to understand non-persistent XSS attack. I learnt that one of the non-persistent XSS form is adding executable along with js in the URL like below
http://www.myxsssite.com/default.aspx?requesturl=<script>alert(hello)</script>
I'm on IIS and if I try the above example, IIS itself throws-up exception saying "A potentially dangerous Request.Path value was detected from the client (<)."
But when I try the below URL I get to see an alert dialog with whatever I've added in that
http://www.myxsssite.com/default.aspx?requesturl=docs/help-files/main.htm'==alert(hello)=='
The second case occurs when an unauthenticated user tries to access the help files directly wherein the above URL gets constructed followed by redirecting to Login page. Once logged in the requesturl param will be used to redirect back to where the user started.
If the same process is replayed with a tab already having valid session it won't show the alert dialog.
The question I've here is what is the significance of '== ==', without which I don't see alert dialog
EDIT:
While redirecting to Login page this is the Response body
<html><head><script>window.top.location='http://www.myxsssite.com/default.aspx?requesturl=docs/help-files/main.htm'==alert(hello)=='';</script></head><body></body></html>
The key thing I've noticed is, If I take the URL from the response and paste it in the Browser it does not shows the alert dialog.
Now it boils down to why the alert in the URL gets fired when location is set through Javascript and why not when copied directly into the browser.
Related
I have a slightly strange question and I'm not sure if this could be achieved at all but anyway I'm curious to try.
I have 2 sites that are independent, lets say www.site1.com and www.site2.com.
site2 will be placed in a href in site1. The question is - is it possible site2 to be accessible only after the user is redirected to it from site1 and if the user tries to open site2 directly or thru an a href from another site different then site1 to not be able to access it?
Check for:
window.document.referrer
// Empty if User is directly loading page.
The value is an empty string if the user navigated to the page directly (not through a link, but, for example, by using a bookmark). Because this property returns only a string, it doesn't give you document object model (DOM) access to the referring page.
MDN Documentation: https://developer.mozilla.org/en-US/docs/Web/API/Document/referrer
Browser Support:
You can check for a post parameter that you set from the website 1 redirection (either through a form or plain javascript). And then set a local storage variable to check for when loading site 2.
Local storage doc
JavaScript post request like a form submit
But keep in mind this can be easily bypassed with enough html/js knowledge.
To ensure that only your website can make post parameter, you could maybe (not sure about me there): generate code (used as post parameter) on the go from webserver 1 and send them to webserver 2 at the same time (or a little before) to ensure the code received by the server 2 is really generated at server 1
Depending on the backend server you are using, you can use something called REFERRER details that will be there in the http header of the request ( for your www.site2.com page for example). This REFERRER will have the information on who referred the user to this site. You can add a condition something like if REFERRER is www.site1.com then render the page .
Here is a link to start with
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referer
I have been working on a mini-project for the last day.
It's a menu interface with 4 submenu sections.
Each submenu, when clicked, requests a separate HTTP authentication.
If the user submits the correct authentication, the submenu "unlocks". Otherwise the submenu remains locked.
I've got it to work, and I see why it works but - and this is my question - it looks a bit hacky and I suspect there may be a much more optimal solution.
TLDR; Go directly to Step Six (below)
Step One
When I first wrote the menu and the HTTP Authentication Menu popped up, there were three outcomes:
If the user gives an incorrect response, authentication is requested again
If the user gives a correct response, the submenu unlocks
If the user cancels... the browser displays a 401 Unauthorised Page (of course it does...)
Step Two
I wanted the menu to remain visible to the user, so I set up a custom 401 Unauthorised Page by adding:
ErrorDocument 401 /my-custom-401/
to my .htaccess file
And, since it's a PHP file, I added a Location header redirect:
header('Location: http://'.$_SERVER['HTTP_HOST'].'/my-menu/');
exit();
to the top of the file.
Nope. Do you know what that does? It prevents the Authentication Console from ever popping up. Why? Because, at the point where the console does pop up, the server is already visiting the custom 401 Unauthorised Page (even though it isn't displaying in the browser until you click on cancel). So if the first thing the server sees is a Location header, it leaves before it ever pops up the console.
Step Three
So, I wrote some html (<head>, <body> etc.), ditched the PHP Location Header and added a javascript redirect to the <head>:
<script>window.location.href = '/my-menu/';</script>
Definitely better, although now, given that I had already unlocked the submenu (this is the default behaviour behind the scenes - for all those users, who have already been through authentication and don't need to go through it again), what now happens is that just pressing cancel on the console, means I am returned to the menu and (of course) the submenu is now unlocked.
Step Four
So, I went back to my custom 401 Unauthorised Page I re-locked the submenu (which I'd unlocked for users who don't need authentication) prior to the redirect. I'm using PHP Sessions, so it looks like this:
$_SESSION['My_Submenu_Unlocked'] = FALSE;
Behaviour is now exactly as intended for those users who have already authenticated and those users who have not yet authenticated and who go to unlock a submenu and who then:
enter incorrect details; or
press cancel
But for those users who enter correct details, despite the fact that they are now authenticated, they are redirected back to the menu with a $_SESSION['My_Submenu_Unlocked'] = FALSE; flag which means that the submenu does not display as unlocked... even though if they click on it a second time (being authenticated), the menu will then unlock.
Step Five
It's not great user experience to click on something, have it do nothing and then react when you click on it a second time. I wanted the submenu to unlock when I clicked it the first time. For that to happen, I figured, the server (or the browser) would need to recognise that the user had just been redirected from the custom 401 Unauthorised Page and then auto-click itself on the respective submenu to deliver the intended behaviour.
The auto-clicking isn't a problem - I can do that with .click() in javascript. But it quickly became apparent, that if the browser fired the javascript after redirecting from the custom 401 Unauthorised Page without a further conditional check then anyone clicking cancel on the authentication console, would find themselves in an infinite loop of authentication requests, always being redirected to the menu, which then redirected to the custom 401 Unauthorised Page and so on...
Step Six
... it was then that I stumbled upon what may be a hack, or may be an elegant solution which takes advantage of standard server behaviour in which PHP is processed first, then the server waits for positive user authentication and only then does it deliver the HTML and CSS and Javascript to the browser.
Here it is. At the top of the head of the custom 401 Unauthorised Page I have the following PHP, HTML and Javascript:
<?php
session_start();
echo '<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My Custom 401 Unauthorised Page</title>
';
// CONFIRM THAT SERVER HAS VISITED "401 UNAUTHORISED" AUTHENTICATION PAGE
$_SESSION['Authorisation_Check'] = TRUE;
// AUTHORISATION INSTRUCTIONS
$_SESSION['Selected_Submenu_Unlocked'] = FALSE;
// JAVASCRIPT REDIRECT FOR WHEN AUTHENTICATIONS ARE CANCELLED BY THE USER
echo '<script>window.location.href = \'/my-menu/?locked\';</script>';
echo '
<link rel="stylesheet" href="/my-styles.css" />
</head>
';
The query string ?locked in the javascript redirect above is all I need to ensure that the auto-click never happens on returning to the menu if the user presses cancel. Why? Because, apparently, that javascript redirect (with the query string) is only ever processed if the user does click cancel.
If the user fills in the authentication details correctly, the server still parses through the <head>, paying attention to:
// CONFIRM THAT SERVER HAS VISITED "401 UNAUTHORISED" AUTHENTICATION PAGE
$_SESSION['Authorisation_Check'] = TRUE;
// AUTHORISATION INSTRUCTIONS
$_SESSION['Selected_Submenu_Unlocked'] = FALSE;
but then, after the user responds to the console correctly, it returns to the menu URL (without the query string) before the browser ever gets to process:
// JAVASCRIPT REDIRECT FOR WHEN AUTHENTICATIONS ARE CANCELLED BY THE USER
echo '<script>window.location.href = \'/my-menu/?locked\';</script>';
I can see why this works, but is this really reliable?
Or is this separation of PHP execution and Javascript execution (with HTTP Authentication in the middle) a robust enough approach to be used and reused in future?
Either way, is there a better, more optimal approach still using HTTP authentication and PHP Sessions but that doesn't involve this sort of tricky javascript?
I'm still unclear whether using a javascript redirect on a custom 401 page (for users who cancel the authentication console) is a legitimate approach or constitutes nothing more than a convenient hack, but I've come to terms with using it for now.
I'll call it the Authentication Sandwich.
Usefully, I've realised that, rather than the over-complex process of:
Re-locking the submenu on the custom 401 Unauthorised Page
Flagging the visit to the custom 401 Unauthorised Page
Redirecting via javascript back to the menu with a query string appended
Processing a conditional block on the menu page if there has just been a redirect from the custom 401 Unauthorised Page.
And if there has, checking if there is a query string appended to the URL.
And if there isn't, then using javascript to click again on the submenu.
(It was preposterously complex, wasn't it?)
I can replace all the above with a much simpler alternative:
A javascript redirect in the <head> of the custom 401 Unauthorised Page which accesses an intermediate page which i) re-locks the submenu; and ii) returns to the menu
That's it.
No need to flag the visit to the custom 401 Unauthorised Page
No need for any query strings
No need for a conditional block on the menu page
No need for an over-elaborate use of javascript to click again on the selected submenu
Much, much simpler and more straightforward.
My question is a follow-up to how to programmatically create an authentication/login window. One reply to that question suggested that I look at the example code in https://meta.stackexchange.com/a/293498/148310.
I implemented that code, and I am now able to get a login/authentication window. The problem now is that immediately after entering my login credentials, I am redirected to my specified redirect_uri URL address (localhost, see image), where the browser complains of "Problem loading page", "Unable to connect" error/warning (click for image), a situation that I think is terminating the execution of my code. Note that the desired access token number does appear to be attached to the end of the URL, as it should be, in spite of the browser's page-loading problems. The problem is that my code gets terminated by the browser-loading problem before it can read the token off of the redirected page.
The below snippet out of my code (also included in the example code given in link above) looks at the window's URL to determine if the browser has redirected (indicated by the presence of 'oauth/login_success' in the URL address). The code considers a redirected browser as indication of successful login/authentication of the user; the access token at the end of the URL address is ready for programmatic extraction and application. (In my case, I want the code to use the token in an API call to download a bibtex file from my Mendeley research group account). Otherwise, execution of the login/authentication process is triggered.
function getInfo()
{
if (location.pathname == "/oauth/login_success") {
processOauthPopup ();
}
else {
authorizeAndThenRunMain ();
}
}
In my code, at the end of the authorizeAndThenRunMain function, I have a call back to getInfo(), the expectation being that the code would then choose the processOathPopup function. On the contrary, the code seems to stop execution when the browser redirects to localhost. If I press the button on my ShareLatex page again to initiate another call to getInfo, I just get presented with the login / authentication screen again. The code never gets on with the business of extracting the access token (at the end of the redirected url shown in the image) and completing the desired tasks under the processOauthPopup () function.
To get to the point, my question is: how do I tell my code to ignore the fact that the redirect window has a loading error, and to just get on with extracting the token from the URL in that window and proceed executing the processOathPopup function?
To elaborate a bit more, I speculate there are 2 potential problems with my code that could be relevant to the problem of the code never selecting the processOathPopup option:
My GreaseMonkey script is run on www.sharelatex.com/projects/xxxxx, where xxxxx is specific to the user account and the document that is being edited in the account (think of Google Drive, where each document has a unique ID number). My code takes me to a api.mendeley.com/oauth/ site where I authenticate and log in, and then I am redirected to the localhost:5000/oauth/login_success link (see image). Is the fundamental problem that my redirect url points to localhost rather than back at sharelatex.com?
If so, would it matter that an "www.sharelatex.com/oauth/login_success" does not point to a real website?
If indeed "sharelatex" needs to be part of the redirect URL, does it need to be an identical URL address to the sharelatex page that I started from? Or can it be a truncated address, with the document-specific information redacted (e.g., the xxxxx stuff described above that links to a specific document in sharelatex). Having to go through the Mendeley userscript registration system to change the URL every time I wanted to use this code for a different sharelatex document would be not good. Even then, a "/oauth/login_success" tacked on to a legitimate URL will result in a redirected URL that points to a non-existent website, which I think is the problem with using the localhost redirect.
In order for location.pathname to ever equal "/oauth/login_success", wouldn't the redirect window need to load into/replace my sharelatex window from where I initially launched code execution (My GreaseMonkey code makes a button on my ShareLatex website that I use to initiate the execution of the above getInfo function).
Or is location.pathname smart enough to point to whatever tab in the browser was most recently opened (e.g, the api.mendeley.com followed by the redirected localhost URLS), rather than always pointing to the sharelatex.com window from which the javascript/userscript was launched?
If indeed location.pathname points to the most recent tab rather than the original sharelatex.com window, then how do I get the code to point back to the original ShareLatex window so that it can listen for future button-pushing events there?
I am so confused... Any assistance would be greatly appreciated!
Currently I have a page that when you fill out a text box and click a button, it redirects you to another page.
The page needs to be loaded, since it updates and shows xml. (I cannot currently change how this is)
However what I what to do is after page was redirected once, redirect it again or just load another page in general.
The thing to note about the xml link, is that part of it is created with the text box, so it will be dynamic.
I currently have something along the lines of this
//please note that username is a textbox, I've just left it out
<script runat = "server">
void Button_Click(Object sender, EventArgs e)
{
var url = "http://website.com/scripts/" + username.text "/value/0"
try
{
Response.Redirect(url, true);
}
catch(Exception ex)
{//From what I learnt, adding true to redirect throws an exception,
//which is how I tried executing another redirect, but it doesn't seem to
//to load the first direct, and skips straight to this, I also put this
//in finally, because it seemed more appropriate to no avail
Response.Redirect(someurl, true);
}
}
So I'm wondering if this is actually possible, I also wonder if I'm just looking up the wrong keywords to find a solution.
I've spent a bit of time on this, and have yet to come to some sort of solution, but I'm new to web development so I may just be missing some incredibly simple.
Also I only really understand how C# works in asp, but am willing to learn how to add in javascript or VB if necessary.
Thanks in advance for the help
Edit: Solution!
So I managed to use javascript to append the textbox value to the xml link, request it and without showing the user (showing the user, is not necessary in this case).
After which a popup confirms that it is successful then reloads the page.
it is very self explanatory but what I did was
url = "website";
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("GET", url, true);
window.alert("success");
return true;//this reloads the page, that or just window.location.reload();
For an added check, I will see if I can verify that the username is a valid username, and popup with failure text if not.
You seem to have a misunderstanding about what Response.Redirect(...) actually does. The method name is, in my opinion, a bit misleading. It suggests that somehow the Response to the currently executing request will be sent somewhere else than the requesting browser. This is not the case. The name could as well have been Response.SendRedirectResponseToBrowser, because that's what Response.Redirect does.
So when you do Response.Redirect(url) you are telling the server that is executing your page that is should send a response to the browser, telling the browser to do a GET request of the supplied url. The browser will then do that, at which point that page needs to include a separate Redirect in order to further tell the browser where to go next.
In this case then, the page at "http://website.com/scripts/" + username.text "/value/0" needs to be patched up so that after processing the request, it will also send a redirect response with the url you want to display next.
If you have no control over that page, then you must solve this some other way. Some options:
Use ajax to request the "http://website.com/scripts/" + username.text "/value/0" url. Then after completion set the page location to the url you want to show next.
Open the http://website.com/.... url in a _blank target, then set to location to the next page.
Use System.Net.Http.HttpClient in your code behind method to request the http://website.com/.... url, then do a redirect. This means that the server requests the url as part of processing the button click.
Notes:
If the http://website.com/.... url updates some state (like store some changes in a database or similar), then you should request it using a POST request, not a GET. GET requests can get a cached response which means that the server might never actually see the request, and therefore not do any processing.
Piecing together the url like this "http://website.com/scripts/" + username.text "/value/0" looks risky. You should at the very minimum url encode the username.text - HttpUtility.UrlEncode(username.text). Better yet would be the first validate that the entered username is actually a valid user name.
You can add a Refresh header (not a meta-refresh element) to the response that contains the XML. In the header, you can specify another URL and the number of seconds to wait before redirecting.
I guess it should be using JavaScript (front-end) instead of back-end error handling, because it goes to another page. Use promise to handle exception
I have a CGI script that does a lot things. I'm trying to keep the script very simple and portable. I just need some way for the user to send a message to the server without having to lose the current page. So far, I have the following process:
User loads a "status page" from a CGI script.
The status page has a javascript timer that will read data (not the entire page) from the server every two seconds and alter the status page accordingly.
User clicks a hyperlink element to launch a job on the server.
The CGI receives the parameters from the click and starts the job.
The CGI sends a response of \n
At this point Firefox asks the user if they want to download the CGI script and of course the script is just the \n that the CGI sent. Instead, I want the browser to ignore the response altogether. If my CGI script does not echo a \n apache gives an error. What could I do to tell the browser to ignore the response and stay on the current page? Note that I would rather not reload the current page. I'm thinking there must be some sort of "noop" HTTP response for such a case.
Send back a response with the 204 HTTP status code. From RFC 2616 aka Hypertext Transfer Protocol -- HTTP/1.1:
10.2.5 204 No Content
The server has fulfilled the request
but does not need to return an
entity-body, and might want to return
updated metainformation. The response
MAY include new or updated
metainformation in the form of
entity-headers, which if present
SHOULD be associated with the
requested variant.
If the client is a user agent, it
SHOULD NOT change its document view
from that which caused the request to
be sent. This response is primarily
intended to allow input for actions to
take place without causing a change to
the user agent's active document view,
although any new or updated
metainformation SHOULD be applied to
the document currently in the user
agent's active view.
The 204 response MUST NOT include a
message-body, and thus is always
terminated by the first empty line
after the header fields.
Instead of trying to solve this problem on the server side, you might want to investigate a client side solution. For example, using jQuery you can easily initiate an AJAX asynchronous request to the server on a button click. You don't have to load a new page on the browser at all.
Instead of having the hyperlink be a real <a> or <form> with default behavior, have it be some clickable element whose clicks are handled by your client-side code. The Javascript code should send the job requests with XMLHttpRequest objects, putting it in complete control of how the response is handled.