Pentesting - Send POST request with modified headers - javascript

let me explain you my situation for a pentesting I am doing:
There exist an app on www.victim.com that accept POST request with customized headers (e.g: "Authorization" : "xxxxx"). I have a domain www.attacker.com that when visited (by the "victim") needs to execute a code that forge the aforementioned POST request, send it to www.victim.com and reload the webpage. As you can see, the behavior is what is expected from a classic "form":
Code on attacker site (www.attacker.com):
<form action="www.victim.com" method="POST" id="myForm">
... some hidden input ...
<input type="submit" name="HackIt" value="Hack me!" />
</form>
The main disadvantage of the previous method is that I can not customize the header of the request before the form is submitted. That's why I tried to use AJAX and JQuery to modify header before the form is submitted:
<script>
$(document).ready(function(){
$("#myForm").submit(function(event){
event.preventDefault(); //prevent default action
var post_url = $(this).attr("action");
var request_method = $(this).attr("method");
var form_data = $(this).serialize();
$.ajax({
url : post_url,
headers: {
"Authorization": "xxxxxx",
"Accept-Language":"x_machine"
},
type: request_method,
data : form_data
});
});
});
</script>
This code almost works! However the response is interpreted by www.attacker.com and not by www.victim.com as expected. Classic form previously mentioned reloads the webpage and allows the response to be interpreted by www.victim.com.
Finally, the question is: What is the "magic recipe" to modify the headers of the request and submit it as the classic form to allow the response be interpreted by www.victim.com?
Thanks in advance!

Related

Pass javascript string variable to another page and get the variable in PHP with AJAX

I basically don't seem to understand sending a variable to another page.
I've tried PHP sessions, javascript cookies and ajax POST and GET.
I'm trying to send the innerHTML of a div, with the data created by a jQuery call,
a variable called savedartists. It displays correctly in the console.log on the sending page but the $_POST['savedArtists']
is undefined in the receiving page. I have spent hours looking at different posts on this site but I haven't been able to get it to work.
Any help is appreciated.
<input class="et_pb_button et_pb_button_0 et_pb_bg_layout_light" onClick="savequote();" type="button" id="savedchoices" value="Commander la prestation" >
<script>
function savequote() {
var savedartists = document.getElementById('selectedList').innerHTML;
console.log(savedartists);
$.ajax({
type: "POST",
url: 'example.com/artiste/mise-en-relation/',
data: { savedArtists : savedartists },
success: function(data) {
console.log("success!");
location.href = "example.com/artiste/mise-en-relation/";
}
});
}
</script>
On the receiving page (example.com/artiste/mise-en-relation/)
<?php
if(isset($_POST['savedArtists']))
{
$uid = $_POST['savedArtists'];
echo $uid;
} else {
echo 'zit!';
}
?>
Thanks for your time
Capturing as an answer for future readers...
Fundamentally what's happening here is that two requests are being made to the target page. The first one is the AJAX request:
$.ajax({
type: "POST",
url: 'example.com/artiste/mise-en-relation/',
data: { savedArtists : savedartists },
success: function(data) {
//...
}
});
This is a POST request which contains the data you expect, and works just fine. However, the result of this request is being ignored. That result is available in the success callback, but the code doesn't do anything with it:
console.log("success!");
location.href = "example.com/artiste/mise-en-relation/";
Instead, what the code is doing is performing a redirect. This creates a second request to that same page (though it's essentially irrelevant that it's the same page). This is a GET request and contains no data to send to the server.
At its simplest, you should either use AJAX or redirect the user. Currently you're mixing both.
I want to redirect to the other page.
In that case AJAX is the wrong tool for the job. You may not even need JavaScript at all, unless you want to modify the elements/values of a form before submitting that form. But if all you want is to POST data to another page while directing the user to that page, a plain old HTML form does exactly that. For example:
<form method="POST" action="example.com/artiste/mise-en-relation/">
<input type="text" name="savedArtists">
<button type="submit">Submit</button>
</form>
In this case whatever value the user enters into the <input> will be included in the POST request to example.com/artiste/mise-en-relation/ when the user submits the form.

JQuery submit form parameters are empty

I am submiting form using $('#myForm').submit my rest service accepts content-type of application/x-www-form-urlencoded, but when using submit() I can't see the request in XHR tab in browser developer tools and the form parameters doesn't reach the Rest service, I could use AJAX post and specify content-type, but Rest service produces octet stream in other words the response contains a downloadable file csv/pdf, what could be the solution to submit form correctly?
Why you are not using $.ajax() with type:"post" ?. you can set header easily there
// Request with custom header
$.ajax({
url: 'foo/bar',
type: 'post',
headers: { 'content-type': 'application/x-www-form-urlencoded' },
data: {}, // object of your data
success: function(response){
alert(response)
}
});
IF your api response is in octet stream or downloadable file then you have to create virtual form and post it through jQuery, Because through AJAX it is not possible to download file.. When file is download content of current page will remain same event form is posted.
function autoGenerateAndSubmitForm(method, url, post_data) {
var element = document.getElementById("virtual_form");
if(element != null )
{
element.parentNode.removeChild(element);
}
var form = document.createElement("form");
form.setAttribute("id", "virtual_form");
form.setAttribute("style", "display:none;");
//form.setAttribute("target", "_blank"); // remove comment if you want to open it in new tab
form.method = method;
form.action = url;
for(i in post_data)
{
var element=document.createElement("input");
element.value=post_data[i];
element.name=i;
form.appendChild(element);
}
document.body.appendChild(form);
form.submit();
form.parentNode.removeChild(form);
}
Call below function with your poper arguments
autoGenerateAndSubmitForm('POST','your_url',{your_post_data_object:"Here"});
After reading your modified Question usually if the parameters are empty at the API it could be caused by the following.
Form is Not Properly Serialized
The Content Type Specified Is Not what your API is Accepting
When you are using ajax make sure your form does not specify any action and methods else there might be a problem.
The model the API is expecting doesn't match what the form has submitted
When using Ajax change your button type to "button" instead of "submit".

Run a PHP script on an external server with feedback (via AJAX) only returns Error 405

My problem is this: I have a HTML form for sending an EMail. And I have a PHP file to process said Form and send the EMail. The problem is, they are not on the same server (I have access to the PHP file, though). I have Bootstrap and JQuery on my page.
My form looks like this: (simplified)
<div id='form-messages'></div>
<form id='ajax-contact'>
several text fields, each one with name and id
<button type="submit" id="submit">SUBMIT</button>
</form>
It's a simple form and it works. The problem is how I send the data to the PHP script. These script tags are at the end of the <body> tag:
<script>
$(document).ready(function() {
$('#ajax-contact').on('click', function () {
// Get the form.
var form = $("#ajax-contact");
// Get the messages div.
var formMessages = $("#form-messages");
// Set up an event listener for the contact form.
$(form).submit(function(event) {
// Stop the browser from submitting the form.
event.preventDefault();
// Serialize the form data
var formData = $(form).serialize();
});
$.getJSON("my_path_to_the_php_script.php", function(formData){
});
});
});
</script>
I was told to use getJSON to work around the fact that the PHP script doesn't lie on the same server as the HTML. AFAIK .getJSON sends a JSONP-string to the PHP file. What I want to check for is simply if the PHP-script has failed or not and display an error message above the form.
The reason I try to use .getJSON is because I already tried this:
$.ajax({
url:'my_path_to_the_php_script.php',
type:'post',
data: formData,
jsonp: 'jsonp',
dataType: 'jsonp', // use JSONP
success: function(data){
// Display OK message
$(formMessages).html(<div class="alert alert-success">
X
Success!
</div>)
// Clear the form.
$(formMessages).each(function(){
this.reset();
});
}
},
error: function (error) {
$(formMessages).html(<div class="alert alert-danger">
X
Warning Message!
</div>)
}
});
Both methods don't work. All I want to do is to check if the script has failed or not. The $.getJSON() way doesn't work, it stays on the same page (as I expect), but the server returns an Error 405 page (Method not allowed). I don't have access to the header files of the PHP installation of that server. The $.ajax(dataType: 'jsonp') way doesn't work, returns Error 405.
Thanks for reading, please help.

pages keep refreshing after call javascript function returned from ajax response

I have tried most answers about call javascript function returned from ajax response. Every answer worked but I must call alert to show the ajax response to see the result.(If not use alert in the function refreshResults, sometime the result will show but disappear immediately) It seems the page keep refreshing.
Here is the screenshot.
I already tested the browser can receive data successfully from the server. The problem is how to show the data from the browser side.
Here is the code related to receive data from the server and how the server return data.
ajax
function sendAjaxQuery(url, data) {
$.ajax({
type: 'POST',
url: url,
data: data,
success: function (data) {
//eval(document.getElementById("refreshResults").innerHTML);
refreshResults(data);
//$("#firstname").text(data);
// alert('success '+data);
}
});
}
This is how I send data to server.
sendAjaxQuery('http://localhost:3000/results.html',JSON.stringify($('form').serializeObject()));
js
<script type="text/javascript">
function refreshResults(data){
$("#firstname").text(data);
alert(data);
}
</script>
The server side is nodejs. (The server side return a string. Status is 200). The http header is
"Content-Type": "text/plain",'Access-Control-Allow-Origin': '*'
This is the click handler.
function sendData() {
var form = document.getElementById('myform');
sendAjaxQuery('http://localhost:3000/results.html',JSON.stringify($('form').serializeObject()));
}
var sendButton = document.getElementById('sendButton');
sendButton.onclick = sendData;
This is the according html
<form id="myform">
<input type="text" name="Search" value="">
<button id="sendButton" >Search</button>
What is the whole point of the sendAjaxQuery method ?
It just recreates what the $.post does
Just use
// url and data should be whatever you pass to sendAjaxQuery now
$.post(url, data, refreshResults);
whenever you want to make an ajax call..
Update Seeing that you are submitting the contents of a form, the problem might be that you allow the form to be submitted the normal way as well (which causes a refresh of the page).
You will need to cancel the normal action of the button that started this action..
Since you are using jQuery, it is better to use that for binding the event handlers
change
var sendButton = document.getElementById('sendButton');
sendButton.onclick = sendData;
to
$('#sendButton').on('click', function(e){
e.preventDefault();
sendData();
});

Download file via jquery ajax post

I am trying to export my web page data and download it as excel file. but the download does not start even the response return succeed.
$.ajax({
type: "POST",
url: _url,
contentType: 'multipart/form-data;boundary=SzB12x',
data: json,
});
The responseText something like this:
PK�J;Fxl/theme/theme1.xml�YOo�6����,[r��n;v��i����#-�kJH:�oC{0X7�2��mZ���d��u#�(٦b:M���������{|��^�0t#��*"w$�!0I�[�՚n�i��'����iH� g�,��|�J�!���hRh�h��?r&�L ���߶S��v#���#��׮�"���}��Жt%�hR�t"������+��������u{ނ��0K���oy�9OTWywkAͯ�
���F�� 6*�����[���U���
I think its the file but I cant download it!!
Any help please?
Thanks!
I faced the same issue and successfully solved it. My use-case is this.
Post JSON data to server and receive an excel file.
That excel file is created on the fly and returned as a response to client.
Code:
$("#my-button").on("click", function() {
// Data to post
data = {
ids: [1, 2, 3, 4, 5]
};
// Use XMLHttpRequest instead of Jquery $ajax
xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
var a;
if (xhttp.readyState === 4 && xhttp.status === 200) {
// Trick for making downloadable link
a = document.createElement('a');
a.href = window.URL.createObjectURL(xhttp.response);
// Give filename you wish to download
a.download = "test-file.xls";
a.style.display = 'none';
document.body.appendChild(a);
a.click();
}
};
// Post data to URL which handles post request
xhttp.open("POST", excelDownloadUrl);
xhttp.setRequestHeader("Content-Type", "application/json");
// You should set responseType as blob for binary responses
xhttp.responseType = 'blob';
xhttp.send(JSON.stringify(data));
});
The above snippet is just doing following
Posting an array as JSON to the server using XMLHttpRequest
After fetching content as a blob(binary), we are creating a downloadable URL and attaching it to invisible "a" link then clicking it.
Here we need to carefully set few things at the server side. I set few headers in Python Django HttpResponse. You need to set them accordingly if you are use other programming languages.
# In python django code
response = HttpResponse(file_content, content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
Since I download xls(excel) here, I adjusted contentType to above one. You need to set it according to your file type.
Try to use a hidden form to submit the request.
When a user submits an HTML form, all the data entered into the form by the user is sent as either a GET or POST request to the URL specified in the “ACTION” attribute of FORM.
<FORM action="http://www.labnol.org/sendmail.php" method="post">
...form contents...
</FORM>
In the above example, an HTTP POST request is issued to the sendmail.php script on form submission. You can add target=”_blank” to the FORM tag to process the request in a new window.
However, if you would like to submit a FORM on the page in the background without directing the browser to another page (document.location.href changes on form submit), you have two options:
Option #1. You can either create an invisible IFRAME inside your HTML page and set that as a target for the Original FORM. This will submit the form but without reloading the parent window.
<FORM action="http://example.com/script.php"
method="POST" target="hidden-form">
...form contents...
</FORM>
<IFRAME style="display:none" name="hidden-form"></IFRAME>
Option #2: There’s another method that allows you create custom payloads before submitting the form. Unlike the IFRAME based form submission, the following code makes a standard form submit request and thus your browser location will change and the current page will get added to the browser history. Credit: Rakesh Pai.
submitFORM('http://example.com/script.php', 'POST',
{'name':'digital+inspiration', 'age':'100', 'sex','M'});
function submitFORM(path, params, method) {
method = method || "post";
var form = document.createElement("form");
form.setAttribute("method", method);
form.setAttribute("action", path);
//Move the submit function to another variable
//so that it doesn't get overwritten.
form._submit_function_ = form.submit;
for(var key in params) {
if(params.hasOwnProperty(key)) {
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", key);
hiddenField.setAttribute("value", params[key]);
form.appendChild(hiddenField);
}
}
document.body.appendChild(form);
form._submit_function_();
}
In this link you can find the way to create hidden form and submit it.
enjoy!!
The approach here is directly lifted from https://gist.github.com/DavidMah/3533415.
This approach uses <form> and appends the data with a key. This approach works if the server is already expecting the data as an attribute of the request body, as opposed to being the request body itself. If the data to be uploaded is an object, you could iterate over that object's keys. If the data to be uploaded is an array, either modify the server route or [add idea here].
In browser
// Takes a URL, param name, and data string
// Sends to the server... The server can respond with binary data to download
jQuery.download = function(url, key, data) {
// Build a form
var form = $('<form></form>').attr('action', url).attr('method', 'post');
// Add the one key/value
form.append($("<input></input>").attr('type', 'hidden').attr('name', key).attr('value', data));
//send request
form.appendTo('body').submit().remove();
};
On server
# A Tidbit of sinatra code to respond
# Assume 'url' is a set variable
# Assume 'key' is the key of the value used in the javascript
post url do
data = params[:key]
puts request.body.read
headers['Content-Type'] = "application/octet-stream"
body(data)
end
Example
$.download('/path/resource/', 'data', JSON.stringify(data))
If you just want to download a file, you don't need to use ajax to do it. Actually, you cannot download file using ajax.
You can still do it by making a hyperlink Export request to a server page that responses content-type is application/vnd.ms-excel and content-disposition is attachment.
You can achieve this using an iFrame as well. A sample function:
// append the data to URL
var requestData = {
param1 : "value1",
param2 : "value2",
}
// call the function
downloadFile(<your_URL>, requestData);
function downloadFile(requestURL, data) {
// "transData" is just a user defined variable to encapsulate "downloadIFrame". It can be named anything as required.
var downloadIFrame = window.transData.downloadIFrame = window.transData.downloadIFrame || $("#downloadFileiFrame");
downloadIFrame.attr("src", requestURL + $.param(requestData));
}
// define the iFrame in your HTML and hide it.
<iframe id="downloadFileiFrame" style="display:none;"></iframe>"
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: yoururlpath,
success: function (response) {
var file = fileName+".xlsx";
window.location = "someFilePath?file=" + file;
}
});

Categories