I was trying to simulate the browser (and simulate XSS). Someone recommended me PhantomJS, however, I had some problems with executing simple JS commands.
I've created simple php website: xss.php
<form id = "myform" action="xss.php" method="POST">
<input id="x" name='x' type="text" />
<input type="submit" value="ok" />
</form>
<?php
echo $_POST['x'];
$fp = fopen("logs.txt", "a");
fwrite($fp, $_POST['x']);
fclose($fp);
?>
<script>document.getElementById('x').value='payload';
document.getElementById('myform').submit();</script>
When I run it from my browser, the form is sent (and its results its put into logs.txt. However, there is a problem, while trying to run that website via PhantomJS:
run.js:
var page = require('webpage').create();
var url = 'http://127.0.0.1/xss/xss.php';
page.open(url, function (status) {
if (status !== 'success') console.log('Network error');
else
{
var p = page.evaluate(function () {
});
console.log('DONE');
}
phantom.exit();
});
I run it via command line: ./phantomjs run.js
As far as I understand, this script should simulate the browser behavior and send the above form. However, there is nothing in logs.txt, which means, that phantomjs didn't run that script. Could you please tell me what I did wrong?
Your script puts the browser into an eternal loop, reloading the page xss.php. This will put the word 'payload' into logs.txt, until you stop javascript execution.
If you want to simulate form submition, you must explicitly send POST data to php script:
var page = require('webpage').create();
var url = 'http://127.0.0.1/xss/xss.php';
var data = 'x=phantom';
page.open(url, 'post', data, function (status) {
if (status !== 'success') console.log('Network error');
else
{
console.log('DONE');
}
phantom.exit();
});
This will feed POST data to xss.php, appending the word 'phantom' to logs.txt. But mind, that, unlike the browser, PhantomJS won't go into eternal loop and will send the request only once.
Related
So I have been working on this for hours now, I have read a bunch of StackOverflow posts and I am still having no luck.
I have a page that has 2 sections to it, depending on the int in the database will depend on which section is being displayed at which time.
My goal is to have the page look to see if the database status has changed from the current one and if it has then refresh the page, if not then do nothing but re-run every 10 seconds.
I run PHP at the top of my page that gets the int from the database
$online_status = Online_status::find_by_id(1);
I then use HTML to load the status into something that jquery can access
<input type="hidden" id="statusID" value="<?php echo $online_status->status; ?>">
<span id="result"></span>
So at the bottom of my page, I added some jquery and ajax
$(document).ready(function(){
$(function liveCheck(){
var search = $('#statusID').val();
$.ajax({
url:'check_live.php',
data:{search:search},
type:'POST',
success:function(data){
if(!data.error){
$newResult = $('#result').html(data);
window.setInterval(function(){
liveCheck();
}, 10000);
}
}
});
});
liveCheck();
});
this then goes to another PHP page that runs the following code
if(isset($_POST['search'])){
$current_status = $_POST['search'];
$online_status = Online_status::find_by_id(1);
if($current_status != $online_status->status){
echo "<script>location.reload();</script>";
}else{
}
}
the jquery then loads into the HTML section with the id of "result" as shown earlier. I know this is a very bad way to do this, and as a result, it will work at the beginning but the longer you leave it on the page the slower the page gets, till it just freezes.
If anyone is able to point me towards a proper method I would be very grateful.
Thank you!!
js:
(function(){
function liveCheck(){
var search = $('#statusID').val();
$.ajax({
url:'check_live.php',
data:{search:search},
type:'POST',
success:function(data){
if(data.trim() == ''){
location.reload();
}else{
$('#result').html(data);
window.setTimeout(function(){
liveCheck();
}, 10000);
}
}
});
}
$(function(){
liveCheck();
});
})(jQuery)
php:
<?php
if(isset($_POST['search'])){
$current_status = $_POST['search'];
$online_status = Online_status::find_by_id(1);
if($current_status != $online_status->status){
$data = '';
}else{
$data = 'some html';
}
echo $data;
}
Your page is slowing down because you are creating a new interval every time you call the liveCheck function. Over time, you have many intervals running and sending requests to your PHP file concurrently. You can verify this behavior by opening the developer console in your browser and monitoring the Network tab.
What you should do instead is set the interval once, and perform the $.ajax call inside that interval. Additionally, it's good practice to not send a new request if a current request is pending, by implementing a boolean state variable that is true while an request is pending and false when that request completes.
It looks like the intended behavior of your function is to just reload the page when the $online_status->status changes, is that correct? If so, change your PHP to just echo true or 1 (anything really) and rewrite your JS as:
function liveCheck() {
if (liveCheckPending == true)
return;
liveCheckPending = true;
var search = $('#statusID').val();
$.ajax({
url:'check_live.php',
data:{search:search},
type:'POST'
}).done(function(data){
if (!data.error)
location.reload();
}).always(function(data){
liveCheckPending = false;
});
}
var liveCheckPending = false;
setInterval(liveCheck, 10000);
How can I call functions on different pages?
For example if I click on the start button, it will run the code necessary to start the tomcat server.
Here is the code for the main page:
<input name="submit" class= "green" id ="start" type="submit" value=" Start ">
<input name="submit" id = "stop" class='red' type="submit" value=" Stop ">
Here's the second page that executes the program.
function (tomcatstart){
$ssh->exec('service tomcat start');}
There are a couple of different approaches you can take to accomplish this sort of task. Here's how I would do it:
Firstly, I'd replace the <input> tags with <button> tags. This is more personal preference than a real change in functionality, but since you're sending the request via AJAX, you don't need a form or inputs.
Secondly, I'd create the JS functions to make the AJAX request, something like this:
function start() {
$.post('urlToStart.php', {
data : 'Some data'
}, function(returnedData) {
//Optionally do something with the returned data, like alert 'Success' or 'Failed'
alert(returnedData);
});
}
Finally, you need a php page to handle the request. You can either have one page that handles both the start and stop requests, or you can have different pages for each one.
Example urlToStart.php:
<?php
$data = $_POST['data'];
if($data !== null) {
tomcatstart();
echo "Success";
}
else {
echo "Failed: " . print_r(error_get_last()); //Get the error message so you know what happened
}
function tomcatstart(){
$ssh->exec('service tomcat start');
}
And that should set you on your way
What you can do is
Add data-task attribute, so we can write single ajax to for
all
Add an additional class, trigger-ajax
change inputs to button or change the input type to button
make a jquery call on click event, using class we added
jQuery(".trigger-ajax").on('click', function(){
var _context = jQuery(this);
jQuery.ajax({
url: 'ajaxrequest.php',
type: "post",
data:{
task: _context.attr('data-task')
},
success:function(response){
console.log(response)
}
})
});
handle it in php
if(!empty($_POST['task'])){
switch(trim(strtotlower($_POST['task']))){
case "start-tomcat":
$ssh->exec('service tomcat start');
break;
case "stop-tomcat":
$ssh->exec('service tomcat stop');
break;
}
}
My code works fine when I run the php script without ajax as a GET request. I get prompted to download the rendered pdf and all is well. However, I need to use ajax because I need to send more info from an html page to the php script than can be handled in a GET request.
What do I need to put into my ajax to make this work?
Thanks
js
function makePDF()
{
var x;
if(window.event) // IE8 and earlier
{
x=event.keyCode;
}
else if(event.which) // IE9/Firefox/Chrome/Opera/Safari
{
x=event.which;
}
keychar=String.fromCharCode(x);
alert(keychar);
if (keychar == 'p' || keychar == 'P')
{
var charSheetHTML = characterSheet.innerHTML;
$.ajax({
url: 'pdf.php',
data: {'charactersheet': charSheetHTML,},
type: 'post',
success: function (data) {**WHAT_DO_I_PUT_HERE??**},
error: function (data) { alert("error\n" + data.toString()); }
});
}
}
pdf.php
<?php
include_once( "bxcharacter/PDFChar.php.inc" );
PDFChar();
?>
PDFChar.hph.inc
<?php
require_once('./tcpdf/tcpdf.php');
function PDFChar(){
$pdf = new TCPDF();
$pdf->AddPage('P');
$pdf->writeHTML($_POST['charactersheet']);
$pdf->Output("character.pdf", 'D');
}
?>
This is not an ajax solution, but you can send your data with this way and if no error occurs, your page will not change.
Create a form element with inputs hidden which contains your data you want to send:
example format:
<form id="myForm" method="GET" action="pdf.php">
<input type="hidden" name="data1" type="hidden" value="your JSON.stringify() data">
</form>
js code (call these where your ajax request is):
var myForm = '<form id="myForm" method="GET" action="pdf.php">';
myForm += '<input type="hidden" name="data1" type="hidden" value="JSON.stringify() data">';
myForm += '</form>';
$("body").append(myForm); // temporarily appending
$("#myData-form").submit(); // submitting form with data
$("#myData-form").remove(); // remove form after submit
And as you said, force download will force file to download and page will remain same. However, if an error occurs, your page will change of course.
I don't know whether this is an effective way or not but in my case, this does the trick.
Old question, but I was trying to do something similar with Laravel PDF extension, and stumbled across this question. I did successfully do this asynchronously with the help of a nice blog post
https://nehalist.io/downloading-files-from-post-requests/
https://github.com/nehalist/download-post-requests
The using the form method, like the previous answer works fine too, but maybe this will help anyone else trying to achieve this with AJAX. The author's XMLHttpRequest method worked great for me!
The code that worked for me (almost verbatim from the blog post) ->
document.getElementById('exportpdf').addEventListener('click', function () {
var request = new XMLHttpRequest();
request.open('POST', '/your/post/endpoint/here', true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
request.responseType = 'blob';
request.onload = function() {
if(request.status === 200) {
var disposition = request.getResponseHeader('content-disposition');
var matches = /"([^"]*)"/.exec(disposition);
var filename = (matches != null && matches[1] ? matches[1] : 'file.pdf');
var blob = new Blob([request.response], { type: 'application/pdf' });
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
};
I tried to get it to work with jQuery AJAX but failed, so I went with XMLHttpRequest. With jQuery, The download would work, but the content was always empty. I tried to do something like in this post -
https://keyangxiang.com/2017/09/01/HTML5-XHR-download-binary-content-as-Blob/
$.ajax does not support either arraybuffer or blob as its dataType. Thus we need write a beforeSend handler:
//setup ajax
$.ajaxSetup({
beforeSend:function(jqXHR,settings){
if (settings.dataType === 'binary'){
settings.xhr().responseType='arraybuffer';
settings.processData=false;
}
}
})
//use ajax now
$.ajax({
url:url,
dataType:"binary",
success:function(data){
console.log(data); //ArrayBuffer
console.log(new Blob([data])) // Blob
}
})
But never got it to work. Maybe someone smarter can figure out the jQuery method :)
I am a beginner with jQuery, AJAX and php. Here is what I am trying to achieve:
- If a user enters the website through a page that does not already have an email form, show a modal pop-up asking them to opt-in with email address.
- Once user clicks submit, change the content in the modal to show a thank you message and then automatically close the modal, allowing the user to interact with the page they originally came to.
- Send submitted info to a database
-I do not want to redirect them to a confirmation page upon submit, but it would be OK if the modal did not automatically close and instead just displayed a confirm message.
I have to host the php on a different server than the website is hosted on, so I think am having a cross-domain response issue. I am able to successfully submit the form (submission goes into database) in Firefox, Chrome, Safari and IE10, and I don't see any error messages in the console when I submit the form. However, data will not transmit from IE8.
I've done some research online and read about using JSON, JSONP, and XDR but a) I'm not clear as to how to implement (over my head right now) and b) seems using these methods seems to increase the risk of someone getting access to these email address submissions.
What can I do to make this work in IE8? Any guidance will be appreciated. An iFrame was the closest alternative I could find so far, but the scrollbars do not disappear and they are unacceptable.
Here are my scripts (web server automatically uses jquery 1.3.2 and I have to use a newer version for the modal, hence the use of noConflict. Not an option to remove reference to 1.3.2):
<script type="text/javascript">
var jQuery_1_7_2 = jQuery.noConflict(true);
function validateEmail(email) {
var reg = /^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return reg.test(email);
}
jQuery_1_7_2(document).ready(function(){
var emailFormExists = jQuery_1_7_2('#e2ma_signup_form');
if (document.cookie.indexOf('visited=true') == -1 && !(emailFormExists.length)){
var fifteenDays = 1000*60*60*24*15;
var expires = new Date((new Date()).valueOf() + fifteenDays);
document.cookie = "visited=true;expires=" + expires.toUTCString();
jQuery_1_7_2.fancybox({width:"100%", inline:true, href:"#inline"});
}
else
{
jQuery_1_7_2('#e2ma_signup_form').length
var fifteenDays = 1000*60*60*24*15;
var expires = new Date((new Date()).valueOf() + fifteenDays);
document.cookie = "visited=true;expires=" + expires.toUTCString();
}
jQuery_1_7_2("#contact").submit(function() { return false; });
jQuery_1_7_2("#send").on("click", function(){
var emailval = jQuery_1_7_2("#email").val();
var mailvalid = validateEmail(emailval);
if(mailvalid == false) {
jQuery_1_7_2("#email").addClass("error");
}
else if(mailvalid == true){
jQuery_1_7_2("#email").removeClass("error");
}
if(mailvalid == true) {
// if both validate we attempt to send the e-mail
// first we hide the submit btn so the user doesnt click twice
jQuery_1_7_2("#contact").fadeOut("fast", function(){
jQuery_1_7_2(this).before("<p><strong>Thanks for opting in!</strong></p>");
setTimeout("jQuery_1_7_2.fancybox.close()", 1000);
});
jQuery_1_7_2.ajax({
type: 'POST',
url: 'http://domain.com/scripts/email-opt-in.php',
data: jQuery_1_7_2("#contact").serialize(),
success: function(data) {
if(data == "true") {
jQuery_1_7_2("#contact").fadeOut("fast", function(){
jQuery_1_7_2(this).before("<p><strong>Thanks for opting in!</strong></p>");
setTimeout("jQuery_1_7_2.fancybox.close()", 1000);
});
}
}
});
}
});
});
</script>
Here is the php:
<?php require_once('../Connections/Liz.php'); ?>
<?php
$insertSQL = "INSERT INTO optin (id, email) VALUES ('','".$_POST['email']."')";
mysql_select_db($database_Liz, $Liz);
$Result1 = mysql_query($insertSQL, $Liz) or die(mysql_error());
?>
and here is my html:
<div id="inline">
<h2>Join the mailing list!</h2>
<form id="contact" name="contact" action="#" method="post">
<label for="email">Your E-mail</label>
<input type="email" id="email" name="email" class="txt">
<button id="send">Submit</button>
</form>
</div>
First of all, I have to say that using jQuery_1_7_2() definitely looks bad for code rewrite! May I suggest var $j = jQuery.noConflict(true); -- then you can use your usual $j(window).method()'s
Anyways, you may face more trouble than its worth with cross-site posting via AJAX calls. This link may be related: CORS with jQuery and XDomainRequest in IE8/9
Using an IFRAME to post sounds like a good idea - but I don't understand why you can't hide the scrollbars. You can use CSS to move the iframe to -999em (vertical) off of the browsers viewport or wrap it in a hidden div.
I'd like to have a jQuery progress bar that updates based on the status of the server side request. I'm basing this code off of this tutorial but it uses a file uploader as its base (same as this question). I can't get it to work quite the same without the file uploader. The problem is that the progress bar only updates after process.php is done. Rather than asynchronously asking for an update on the progress, it waits for the whole process to be done. I only see the data: data alert once.
Any ideas?
Webpage:
<form id="upload-form" action='process.php' method="post" target="upload-frame">
<input type="hidden" id="uid" name="UPLOAD_IDENTIFIER" value="<?php echo $uid; ?>" >
<input type="submit" value="Submit" />
</form>
<div id="progressbar"></div>
<iframe id="upload-frame" name="upload-frame" style="display:none"></iframe>
Process.php - called when form is submitted
<?php
session_start();
$varArray=array(1,2,3,4);
$_SESSION['total']=count($varArray);
foreach($varArray as $val){
$_SESSION['current']=$val;
sleep(2);
}
?>
javascript
$(document).ready(function() {
var started = false;// This flag determines if the upload has started
$(function() {
// Start progress tracking when the form is submitted
$('#upload-form').submit(function() {
$('#progressbar').progressbar();// Initialize the jQuery UI plugin
// We know the upload is complete when the frame loads
$('#upload-frame').load(function() {
// This is to prevent infinite loop
// in case the upload is too fast
started = true;
// Do whatever you want when upload is complete
alert('Upload Complete!');
});
// Start updating progress after a 1 second delay
setTimeout(function() {
// We pass the upload identifier to our function
updateProgress($('#uid').val());
}, 1000);
});
});
function updateProgress(id) {
var time = new Date().getTime();
// Make a GET request to the server
// Pass our upload identifier as a parameter
// Also pass current time to prevent caching
$.ajax({
url: 'getProgress.php',
type: "GET",
cache: false,
data: {'uid':id},
dataType: 'text',
success: function(data){
alert("data: " + data);
var progress = parseInt(data, 10);
if (progress < 100 || !started) {
// Determine if upload has started
started = progress < 100;
// If we aren't done or started, update again
updateProgress(id);
}
// Update the progress bar percentage
// But only if we have started
started && $('#progressbar').progressbar('value', progress);
}
});
}
}(jQuery));
getProgress.php - called by the ajax request:
<?php
session_start();
if (isset($_REQUEST['uid'])) {
if (isset($_SESSION['total']) && isset($_SESSION['current'])) {
// Fetch the upload progress data
$total = $_SESSION['total'];
$current = $_SESSION['current'];
// Calculate the current percentage
$percent_done = round($current/$total*100);
echo $percent_done;
}else{
echo 100;// If there is no data, assume it's done
}
}
?>
AFAIK, PHP sessions are actually synchronous. That means that the Process.php script is blocking the getProgress.php script from running until Process.php is done with the session.
So what happens is:
Process.php starts and calls session_start ()
The server gives session control to session_start ()
getProcess.php starts and calls session_start ()
The server blocks getProcess.php until the session is unused.
Process.php completes and closes the session.
The server resumes getProcess.php and gives it control over the session.
getProcess.php now sees that the process is complete.
See http://www.php.net/manual/en/function.session-write-close.php.
Session data is usually stored after your script terminated without the need to call session_write_close(), but as session data is locked to prevent concurrent writes only one script may operate on a session at any time. [...]
I haven't tested the following code since I don't have access to a server at the moment but I imagine somethin like it should work:
<?php
$varArray=array(1,2,3,4);
session_start();
$_SESSION['total']=count($varArray);
session_write_close ();
foreach($varArray as $val){
session_start();
$_SESSION['current']=$val;
session_write_close ();
sleep(2);
}
?>