patternjavascriptMinor
Can XSS or anything else get through this?
Viewed 0 times
thiscanelseanythingxssgetthrough
Problem
I coded a php chat that stores the text in a txt file and retrieves it, and I want to know if XSS can get past it or if someone can replace
This is
And this is the code to the html page (JavaScript included):
xhr.open("POST","uhh.php"); with something that contains the same php code but without htmlspecialchars or something like that. What are the vulnerabilities? (More specifically, I don't want people putting html elements through the chat, and that also leads to security issues.)This is
uhh.php:10){
$split=array_slice($split,1);
}
file_put_contents("uhh.txt",join("\n",$split) . "\n");
}
?>
watchu lookeen at???And this is the code to the html page (JavaScript included):
Chatting
#chatlog {
text-align:left;
border:1px solid black;
width:300px;
height:200px;
}
#chatbar {
width:300px;
}
Bagelhead: lolBagelhead: yes t isAbe: ok proxy off nowBagelhead: gtgBagelhead: :PTest: TestAbe: <p>Test</p>Abe: TestTEST: abTEST: abe
setInterval(function(){
var xhr=new XMLHttpRequest();
xhr.open("GET","uhh.txt?a="+Math.random());
xhr.onload=function(){
document.getElementById("chatlog").innerHTML=xhr.responseText.replace(/\n/g,"");
}
xhr.send();
},1000)
var cb=document.querySelector("#chatbar"),usr="";
function chat(m){
var xhr=new XMLHttpRequest();
xhr.open("POST","uhh.php");
var fd=new FormData();
fd.append("usr",usr);
fd.append("msg",m);
xhr.send(fd);
}
window.onkeyup=function(e){
if(e.keyIdentifier=="U+00BF"){
cb.focus();
}else if(e.keyIdentifier=="Enter"){
if(usr){
chat(cb.value);
cb.value="";
}else{
usr=cb.value;
cb.placeholder="Press / to chat";
cb.value="";
cb.maxLength=9001;
}
}
}
uhh.txt is just a blank text file.Solution
Looks safe to me, but I would change the way you request the server. This way, you send many requests to the server and for more then few people using it, the server could be flooded by these requests. It would however require switching txt file for script file. Then you could use so called long poll.
You are probably wondering what long poll is and how it works. Long poll is technique where client opens connection to the server and leaves it open. When new message comes, server sends it and closes the connection. Trick is, client immediately opens new connection. Same happens when old connection times out.
Problem here is, when you use PHP on server side, it just executes some code and closes the connection. So, you have 2 possibilities: Best idea is to use server written in node.js, which is made for such things (and there are other advantages like that you don't have to store the message anywhere, you just recieve it and immediately send it to all clients and other...). If you want or have to use PHP, then you must use the sleep() function. Then, you have while loop, that each for example 200 miliseconds check for new message in database and either sends it or sleeps for another 200 miliseconds.
If you want to try, here is part of my client code which takes care of server communication:
```
//function, that returns right kind of AJAX object based on browser
//I don't have worst case scenario (AJAX not supported) here, because I usually check for required support at the beginning of the script
function createAjax() {
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
} else {
return new ActiveXObject('Microsoft.XMLHTTP');
}
}
/*
Class that takes care of receiving new messages from server
PARAMS:
longPollServerURL - string - URL of server file, which acts as long poll server
lastIdGetURL - string - URL of txt file, where last message id is saved
newMessageCallback - function - callback to get called when new message is received
it is called with 4 params:
id of the message, time when the message was sent as unix timestamp,
nickname of the person who sent it, message text itself
*/
function ChatLongPoll(longPollServerURL, lastIdGetURL, newMessageCallback) {
var mainContext = this,
httpRequest = createAjax();
//function that starts long poll and sets what should happen when connection ends
this.startLongPoll = function() {
httpRequest.onreadystatechange = function() {
if (httpRequest.readyState == 4) {
var _decodedResponse = JSON.parse(httpRequest.responseText);
if (_decodedResponse.status == 'new') {
for (var i = 0; i <_decodedResponse.messages.length; i++) {
newMessageCallback(_decodedResponse.messages[i].id, _decodedResponse.messages[i].time, _decodedResponse.messages[i].from, _decodedResponse.messages[i].messageText);
mainContext.lastMessageId = _decodedResponse.messages[i].id;
}
}
mainContext.openLongPoll();
}
};
mainContext.openLongPoll();
};
//function that opens connection to the server
this.openLongPoll = function() {
httpRequest.open('GET', longPollServerURL + '?lastId=' + mainContext.lastMessageId, true);
httpRequest.send(null);
};
//function that downloads ID of last message sent
this.getLastMessageId = function() {
var _id = false;
httpRequest.onreadystatechange = function() {
if (httpRequest.readyState == 4) {
_id = httpRequest.responseText;
}
};
httpRequest.open('GET', lastIdGetURL, false);
httpRequest.send(null);
return _id;
};
this.lastMessageId = this.getLastMessageId();
}
/*
Class that takes care of sending messages to server
PARAMS:
newMessageServerURL - string - URL of file, which saves and validates the message
callback - function - function to handle response from server (ok / wrongFormat / noName / ... status etc... (that depends on how you make your server))
*/
function ChatSendMessage(newMessageServerURL, callback) {
var httpRequest = createAjax();
httpRequest.onreadystatechange = function() {
if (httpRequest.readyState == 4) {
callback(JSON.parse(httpRequest.responseText));
}
};
//function that sends the message to server and saves it to httpRequest.lastMessage
this.sendMessage = function (from, messageText) {
var L_postData = 'from=' + encodeURIComponent(from) + '&messageText=' + encodeURIComponent(messageText);
httpRequest.lastMessage = messageText;
httpRequest.open('POST', newMessageServerURL, true);
httpRequest.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
httpRequest.send(L_postData);
};
}
/*
Short class that jus
You are probably wondering what long poll is and how it works. Long poll is technique where client opens connection to the server and leaves it open. When new message comes, server sends it and closes the connection. Trick is, client immediately opens new connection. Same happens when old connection times out.
Problem here is, when you use PHP on server side, it just executes some code and closes the connection. So, you have 2 possibilities: Best idea is to use server written in node.js, which is made for such things (and there are other advantages like that you don't have to store the message anywhere, you just recieve it and immediately send it to all clients and other...). If you want or have to use PHP, then you must use the sleep() function. Then, you have while loop, that each for example 200 miliseconds check for new message in database and either sends it or sleeps for another 200 miliseconds.
If you want to try, here is part of my client code which takes care of server communication:
```
//function, that returns right kind of AJAX object based on browser
//I don't have worst case scenario (AJAX not supported) here, because I usually check for required support at the beginning of the script
function createAjax() {
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
} else {
return new ActiveXObject('Microsoft.XMLHTTP');
}
}
/*
Class that takes care of receiving new messages from server
PARAMS:
longPollServerURL - string - URL of server file, which acts as long poll server
lastIdGetURL - string - URL of txt file, where last message id is saved
newMessageCallback - function - callback to get called when new message is received
it is called with 4 params:
id of the message, time when the message was sent as unix timestamp,
nickname of the person who sent it, message text itself
*/
function ChatLongPoll(longPollServerURL, lastIdGetURL, newMessageCallback) {
var mainContext = this,
httpRequest = createAjax();
//function that starts long poll and sets what should happen when connection ends
this.startLongPoll = function() {
httpRequest.onreadystatechange = function() {
if (httpRequest.readyState == 4) {
var _decodedResponse = JSON.parse(httpRequest.responseText);
if (_decodedResponse.status == 'new') {
for (var i = 0; i <_decodedResponse.messages.length; i++) {
newMessageCallback(_decodedResponse.messages[i].id, _decodedResponse.messages[i].time, _decodedResponse.messages[i].from, _decodedResponse.messages[i].messageText);
mainContext.lastMessageId = _decodedResponse.messages[i].id;
}
}
mainContext.openLongPoll();
}
};
mainContext.openLongPoll();
};
//function that opens connection to the server
this.openLongPoll = function() {
httpRequest.open('GET', longPollServerURL + '?lastId=' + mainContext.lastMessageId, true);
httpRequest.send(null);
};
//function that downloads ID of last message sent
this.getLastMessageId = function() {
var _id = false;
httpRequest.onreadystatechange = function() {
if (httpRequest.readyState == 4) {
_id = httpRequest.responseText;
}
};
httpRequest.open('GET', lastIdGetURL, false);
httpRequest.send(null);
return _id;
};
this.lastMessageId = this.getLastMessageId();
}
/*
Class that takes care of sending messages to server
PARAMS:
newMessageServerURL - string - URL of file, which saves and validates the message
callback - function - function to handle response from server (ok / wrongFormat / noName / ... status etc... (that depends on how you make your server))
*/
function ChatSendMessage(newMessageServerURL, callback) {
var httpRequest = createAjax();
httpRequest.onreadystatechange = function() {
if (httpRequest.readyState == 4) {
callback(JSON.parse(httpRequest.responseText));
}
};
//function that sends the message to server and saves it to httpRequest.lastMessage
this.sendMessage = function (from, messageText) {
var L_postData = 'from=' + encodeURIComponent(from) + '&messageText=' + encodeURIComponent(messageText);
httpRequest.lastMessage = messageText;
httpRequest.open('POST', newMessageServerURL, true);
httpRequest.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
httpRequest.send(L_postData);
};
}
/*
Short class that jus
Code Snippets
//function, that returns right kind of AJAX object based on browser
//I don't have worst case scenario (AJAX not supported) here, because I usually check for required support at the beginning of the script
function createAjax() {
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
} else {
return new ActiveXObject('Microsoft.XMLHTTP');
}
}
/*
Class that takes care of receiving new messages from server
PARAMS:
longPollServerURL - string - URL of server file, which acts as long poll server
lastIdGetURL - string - URL of txt file, where last message id is saved
newMessageCallback - function - callback to get called when new message is received
it is called with 4 params:
id of the message, time when the message was sent as unix timestamp,
nickname of the person who sent it, message text itself
*/
function ChatLongPoll(longPollServerURL, lastIdGetURL, newMessageCallback) {
var mainContext = this,
httpRequest = createAjax();
//function that starts long poll and sets what should happen when connection ends
this.startLongPoll = function() {
httpRequest.onreadystatechange = function() {
if (httpRequest.readyState == 4) {
var _decodedResponse = JSON.parse(httpRequest.responseText);
if (_decodedResponse.status == 'new') {
for (var i = 0; i <_decodedResponse.messages.length; i++) {
newMessageCallback(_decodedResponse.messages[i].id, _decodedResponse.messages[i].time, _decodedResponse.messages[i].from, _decodedResponse.messages[i].messageText);
mainContext.lastMessageId = _decodedResponse.messages[i].id;
}
}
mainContext.openLongPoll();
}
};
mainContext.openLongPoll();
};
//function that opens connection to the server
this.openLongPoll = function() {
httpRequest.open('GET', longPollServerURL + '?lastId=' + mainContext.lastMessageId, true);
httpRequest.send(null);
};
//function that downloads ID of last message sent
this.getLastMessageId = function() {
var _id = false;
httpRequest.onreadystatechange = function() {
if (httpRequest.readyState == 4) {
_id = httpRequest.responseText;
}
};
httpRequest.open('GET', lastIdGetURL, false);
httpRequest.send(null);
return _id;
};
this.lastMessageId = this.getLastMessageId();
}
/*
Class that takes care of sending messages to server
PARAMS:
newMessageServerURL - string - URL of file, which saves and validates the message
callback - function - function to handle response from server (ok / wrongFormat / noName / ... status etc... (that depends on how you make your server))
*/
function ChatSendMessage(newMessageServerURL, callback) {
var httpRequest = createAjax();
httpRequest.Context
StackExchange Code Review Q#48254, answer score: 3
Revisions (0)
No revisions yet.