I have a html page with some buttons, one of my buttons is as following:
<input class="contentLink" type="button" value="Questionnaire" onclick="validate(<?php urlencode('/my-site/Tools/Learning_Strategies/Questionnaire.php'); ?>)"/>
Essentially when this button is clicked, it passes the urlencoded-string literal '/my-site/Tools/Learning_Strategies/Questionnaire.php' into the javascript method validate:
function validate(url){
alert(url);
location.href="/my-site/Session/redirectMe.php?loc="+url;
}
What I am trying to do is get '/my-site/Session/Questionnaire.php' from the html page accessible from the redirectMe.php. This is being setup in the
location.href="/my-site/Session/redirectMe.php?loc="+url;
which leads to my redirectMe.php file:
<?php
require "SessionAuthenticator.php";
Session_start();
if(validateSession()===true){//validateSession() is defined inside SessionAuthenticator.php
echo $_GET["loc"];
//header("Location: ".$_GET["loc"]);
}else{
header("Location: /my-site/LoginPage/index.php");
}
?>
The issue is during both of the alert and echo, the encoded string literal came out as "undefined", which means the following line:
header("Location: ".$_GET["loc"]);
will really look like this:
header("Location: undefined");
And therefore look for 'undefined' in the current directory and break the website.
This all works perfectly if there is no encoding as following:
<input class="contentLink" type="button" value="Questionnaire" onclick="validate('/my-site/Tools/Learning_Strategies/Questionnaire.php')"/>
But... No encoding is bad right?
If you are wondering why you don't see a decode method being used...
The webserver will arrange for $_GET to have been urldecoded once already by the time it reaches you! - Matt Johnson ¶ # http://php.net/manual/en/function.urldecode.php#48481
Require and include will not work, as redirectMe.php would be executed before the user even sees the page. This should only happen when the user clicks the button. That is why I am using a javascript function to start redirectMe.php.
I've tried ajax, however this didn't work. After talking with an experienced programmer who I know personally, I've been told that ajax can't help me here. This because Ajax would be redirected to '/my-site/Tools/Learning_Strategies/Questionnaire.php', but not the client (User).
To clearly state my question:
Why is the urlencoded coming up as 'undefined' when echo-ed/alert-ed? How do I fix this?
As for programs/web servers/etc I am using...
Sublime 3 (text editor)
Wamp (64BIT)(all-in-one package) # http://www.wampserver.com/en/
Apache 2.4.17
PHP 7
MySQL 5.7.9
I am open to other means of getting what I am trying to do done.
However, I am not open to changing web servers/programs etc (except sublime 3 since it is just a text editor.... but why would that need to be required?).
Furthermore, whatever means of getting this done needs to support the browsers/platforms as stated below.
The website must support:
(Browsers)
IE 8 and up, and latest versions of Microsoft Edge, Firefox, Chrome and Safari.
Cross-Platform:
Windows 7 and up, and the latest versions of Mac OS, IOS and Android
Why is the urlencoded coming up as 'undefined' when echo-ed/alert-ed?
Because the PHP doesn't output anything.
<input class="contentLink" type="button" value="Questionnaire" onclick="validate(<?php urlencode('/my-site/Tools/Learning_Strategies/Questionnaire.php'); ?>)"/>
Gives you:
<input class="contentLink" type="button" value="Questionnaire" onclick="validate()"/>
… once you run it through a PHP parser.
You need to:
echo the result so something appears there
wrap it in quotes (with json_encode so any escaping needed is also taken care of) so that it will be treated as a string and not a variable name.
Related
I am creating a commenting system where users can post comments that can also consist of basic HTML including code. Like this:
<pre><code class="language-php"><?php
echo 'Test';
?></code></pre>
The problem is that I can't sanitize this one server side because the PHP code in the comment will actually run on my server. I tried using JavaScript like this before submitting the form:
$("#comment").val() = $("#comment").val().replace("<?", "<?").replace("?>", "?>");
However, this results in Syntax error.
Is there any way for me to safely post user comments that consist of PHP?
to set a new value of input element using jquery, you need to use this syntax
$("#yourElement").val(newValue);
so change your javascript code to:
$("#comment").val($("#comment").val().replace("<?", "<?").replace("?>", "?>"));
read: http://api.jquery.com/val/
Background:
I am making a simple game in PHP, JavaScript and HTML for the web. A player control movements of a box on the screen, and see others fly around with their boxes.
I have the following files, that I upload to my domain via a hosting company:
index.html: a file with some buttons (eg. to start the game) and frames (for putting boxes in).
server.php: PHP script that receives messages from client, performs reads/writes to a database, echoes (using echo) boxes from database to the client. Does not echo the box of the player the message came from.
database.txt: a JSON text file containing data of players and the next free ID number. When empty it looks like this: {"players":[], "id": 1}. players contain objects with values such as ID, position and rotation.
script.js: JavaScript file with script to send/receive messages, display data from messages etc. Linked to index.html. Moves your box.
A screenshot, two players in movement:
Problem: The game crashes, always. Sooner or later. This is what happens:
Client recevies player data from server.php, everything is fine. This could be for 10 seconds or up to some minutes.
The data starts to falter, the message sometimes is null instead of actual data.
The data recevied is always null. The database file is now {"players":null,"id":5}. (The "id" could be any number, does not have to be 5).
Picture of data flow, printing of players from database. Two players. Before this screenshot lots of rows with valid data. Then as seen two null messages. Then after a while null forever.
I am not completely sure where the problem is, but I am guessing it has to do with my read/write in server.php. I feels like a lot of player movement makes the program more likely to crash. Also how often the program sends data affetcs.
Code Piece 1: This is code from server.php, that writes to the database. I have some sort of semaphore (the flock( ... ) ) to prevent clients from reading/writing at the same time (causing errors). I have an other function, read, which is very similar to this. Possible problems here:
The semaphore is incorrect.
The mode for fopen() is incorrect. See PHP docs. The mode w is for write. The tag b is for "If you do not specify the 'b' flag when working with binary files, you may experience strange problems with your data ...".
Something weird happening because I use read() in my writing function?
Code:
// Write $val to $obj in database JSON
function write($obj,$val){
$content = read();
$json = json_decode($content);
$json->{$obj} = $val; // eg. $json->{'id'} = 5;
$myfile = fopen("database.txt", "wb") or die("Unable to open file!");
if(flock($myfile, LOCK_EX|LOCK_NB)) {
fwrite($myfile,json_encode($json));
flock($myfile, LOCK_UN);
}
fclose($myfile);
}
Code Piece 2: This is my code to send data. It is called via a setInterval(). In script.js:
// Send message to server.php, call callback with answer
function communicate(messageFunc,callback){
var message = messageFunc();
if (window.XMLHttpRequest) {
var xmlhttp=new XMLHttpRequest();
}
xmlhttp.onreadystatechange= function() {
if (this.readyState==4 && this.status==200) {
callback(this.responseText);
}
}
xmlhttp.open("GET","server.php?msg="+message,true);
xmlhttp.send();
}
This is my code to receive data, in server.php: $receive = $_GET["msg"].
My current work of solving
This is what I have done so far, but nothing has changed:
Added mode b to fopen().
Added flock() to read/write functions in server.php.
Much reworking on script.js, I would say it looks/works very clean.
Check memory_get_peak_usage(), and check with the hosting company for memory limits. Should be no problem at all.
Looked at PHP garbage collecting and gc_enable() (I don't know why that would change anything).
Lots of testing, looking at the data flow.
Crying.
Conclusion: Is this type of application what PHP is for? What do you think is wrong? If you want more code/info I provide. Thank you very much.
Here is the root of your problem:
$myfile = fopen("database.txt", "wb") or die("Unable to open file!");
Note the behavior of the w open mode (emphasis mine):
Open for writing only; place the file pointer at the beginning of the file and truncate the file to zero length. If the file does not exist, attempt to create it.
This happens before you lock the file. What's happening is that between this fopen() call and the following flock() call, the file's content is zero length, and a reader is coming along during that time and reading the empty file.
Why doesn't this cause an error in PHP when you parse the empty string as JSON? Because json_decode() is defective, and returns null when the input is not valid JSON rather than throwing an exception. Nevermind that the string "null" is valid JSON -- json_decode() gives you no way to differentiate between the cases of valid input representing the null value and invalid input. If json_decode() actually threw an exception or triggered a PHP error (don't ask me why two error-signalling mechanisms are necessary in PHP), you would have a fantastic point to start debugging to figure out why the file is empty, and you might have solved this problem by now!
... sigh ...
PHP's "design" gives me headaches. But I digress.
To fix this whole problem, change the open mode to "cb" and ftruncate($myfile, 0) after you successfully acquire the lock.
Note the behavior of the c mode, which actually specifically mentions the approach you are using (emphasis mine):
Open the file for writing only. If the file does not exist, it is created. If it exists, it is neither truncated (as opposed to 'w'), nor the call to this function fails (as is the case with 'x'). The file pointer is positioned on the beginning of the file. This may be useful if it's desired to get an advisory lock (see flock()) before attempting to modify the file, as using 'w' could truncate the file before the lock was obtained (if truncation is desired, ftruncate() can be used after the lock is requested).
All:
I have an issue with a project I am working on using C# MVC4
In the project, I am accepting a URL and other parameters from a user, then do some processing and send the result of the processing to the URL provided by the user.
The result is being sent using the following code:
var context = HttpContext.Current;
context.Response.Write("<html><head>");
context.Response.Write("</head><body>");
context.Response.Write(string.Format("<form name=\"myform\" method=\"post\" action=\"{0}\" >", postUrl));
context.Response.Write("</form>");
context.Response.Write("<script type=\"text/javascript\">document.myform.submit();</script></body></html>");
context.Response.Write("</body>");
context.Response.Flush();
context.Response.Clear();
context.ApplicationInstance.CompleteRequest();
Whenever a user attempts an XSS like passing a url value of javascript%3aalert('xss')%2f%2f, the JavaScript runs and the pop up shows up.
I've tried Antixss.HtmlEncode() to encode the URL before passing it into string.Format but still doesn't work. I've tried Antixss.UrlEncode() also, but this gives error as the form doesn't submit to the URL.
Please help me out, Is there something I am missing? What else can I do?
Thanks in advance.
You will need a three pronged approach to solve this issue.
Preventing XSS injection:
Note that if a user injected the url value
" /> <script>alert('xss')</script>
this would also leave you vulnerable:
<form name="myform" method="post" action="" /> <script>alert('xss')</script>" >
Therefore you should use the HttpUtility.HtmlAttributeEncode function to solve this one.
However, don't stop there. As noted, you should project against javascript: style URLs. For this I would ensure that the URL begins with http:// or https://. If not, throw a SecurityException which you should be logging and handling server-side, and showing the user a custom error page.
Finally, you want to protect against Open Redirect Vulnerabilities. This is to stop phishing attacks by redirecting users to other domains. Again, use a whitelist approach and ensure that the domain redirected to is one of your own. Be careful on the parsing here, as it is easy to get it wrong - a URL of http://example.org?http://example.com will pass the validation filter for example.com on many badly written validation routines. I recommend using the Uri object in .NET and retrieving the domain through that rather than rolling your own string functions.
You could also check if the URL is a relative URL, and allow it if acceptable. Use something like this function which uses a built in .NET library to ensure that it is relative or not.
Just a thought - try putting this script in rather than just document.myform.submit (and remove the form's action property):
if("{0}".indexOf('http') !== 0) {
//this is some sort of injection, or it's pointing at something on your server. Should cover http and https.
//Specifically, it makes sure that the url starts with 'http' - so a 'javascript' url isn't going to work.
} else {
document.myform.action="{0}"
document.myform.submit();
}
There is more you could do, but this should help.
Since you are adding the postUrl as an attribute "action" of the form tag, you can try using HtmlAttributeEncode method in the HttpUtility
[ValidateInput(false)]
public ActionResult Test(string url)
{
var context = System.Web.HttpContext.Current;
context.Response.Write("<html><head>");
context.Response.Write("</head><body>");
context.Response.Write(string.Format("<form name=\"myform\" method=\"post\" action=\"{0}\" >", HttpUtility.HtmlAttributeEncode(url)));
context.Response.Write("</form>");
context.Response.Write("<script type=\"text/javascript\">document.myform.submit();</script></body></html>");
context.Response.Write("</body>");
context.Response.Flush();
context.Response.Clear();
context.ApplicationInstance.CompleteRequest();
return null;
}
http://localhost:39200/home/test?url=https%3A%2F%2Fwww.google.com - Worked
http://localhost:39200/home/test?url=%3Cscript%3Ealert(%27test%27)%3C%2Fscript%3E - Worked(Did not show alert)
It is always good practice to Validate the user input against a white list of inputs, to prevent XSS exploits.
try using HttpUtility.UrlEncode
something like Response.Write(HttpUtility.UrlEncode(urlString));
see How To: Prevent Cross-Site Scripting in ASP.NET for more steps =)
Here's the break down: My problem is two fold, i want to use a button to call to my php script, which in turn calls to my nodejs script running on my little internal test server (this is all done local for now).
Here is my html + script pull:
<input type="submit" value="Save Sketch" id= "run_system">
</body>
<script>
$('#run_system').on('click', function(){
$.ajax({
url : 'exec.php',
type : "GET"
}).done(function(data){
console.log(data);
});
});
</script>
and here is my php script:
<?php exec('node screenshot.js //place holder url that gets dumped into js file// "); ?>
so my problem is that the previous call to this php is not executing this. Everything i've googled says that this exec("") should run my nodejs script. What am i missing?
I am guessing the type : GET is incorrect, tried not having that line, putting POST in there, nothing seems to work though
Oh one more addition, so when i run the above all it does is print what was in the php file to the console, doesn't actually run the script
One of the issues is that the exec is executing the command, but you're not capturing / returning the output of that command. You can probably add an echo or print before exec to return the output to the AJAX request.
You might also want to bind to the submit event to handle form submissions as well as submit button clicks, but that would be bound to the form itself.
Ultimately though, I would recommend that you contemplate handling this exec by adding a simple HTTP server to your screenshots.js node script (or something that wraps it) and handle the AJAX request with that. Will likely need to add a Access-Control-Allow-Origin exemption.
I've been trying to fix this for two hours straight and I can't figure it out.
onclick = "location='exceltest.asp?vanjaar=<%=vanjaar%>&vanmaand=<%=vanmaand%>&vandag=<%=vandag%>&totjaar=<%=totjaar%>&totmaand=<%=totmaand%>&totdag=<%=totdag%>'"
That line of code is in an < input type="button" /> attribute. The button links to a page where an Excel download should be triggered. The values in the URL are from- and to-date-parts. (year, month, day)
this:
onclick = "location='exceltest.asp?fromdate=<%=fromdate%>&todate=<%=todate%>'" />
does not work, because somehow IE7 reads the date (eg. 2008/1/1) wrong. Something to do with the slashes I think.
But when I try to click the button in IE and thus download the generated file, Internet explorer tries do download the file
exceltest.asp?vanjaar=2008vanmaand=1vandag=1totjaar=2008totmaand=2totdag=1
instead of the excel file I want.
FF offers to download the excelfile, but gives (in that excelfile) an overview of an htmlpage with an errormessage telling me my query is wrong (Item cannot be found in the collection corresponding to the requested name or ordinal.) But that CAN'T be, I'm using that exact same query elsewhere, using the same (but restarted) connection.
This is the bit of code I use to instantiate the download of the file:
Response.Buffer = TRUE
Response.ContentType = "application/vnd.ms-excel"
Response.AddHeader "content-disposition", "attachment; filename=overicht.xls"
There might actually being to things going on here, but I am most insterested in why IE wants to download the asp page and FF offers the right download.
The & inside onclick="" should be html-encoded to &
If fromdate contains slashes you're probably safest to url-encode that as well (though you seem to contradict that with your example URL).
Something that might help: Server.URLEncode
fromdate=<%=Server.URLEncode(fromdate)%>
But, your Excel file error -- Item cannot be found in the collection corresponding to the requested name or ordinal. -- is from Recordset.Fields(). You're trying to grab a field that isn't available -- either a column name that isn't in your query or an index that's beyond your column count.