389 lines
11 KiB
HTML
Executable File
389 lines
11 KiB
HTML
Executable File
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
<html><head>
|
|
<!--
|
|
Possible channels of interference, explored in this document or general properties we would like the portlet markup fragment to have
|
|
1. A global variable created in HEAD
|
|
2. A global built in object (e.g. navigator)
|
|
3. (Later)Access Keys, Tab Index (who wins if there is a conflict, eg. override Alt+F)
|
|
4. Dynamically modifying the DOM, Disallowed HTML Tags
|
|
5. Direct access by traversing the DOM Tree
|
|
6. (Later)Shared prototype objects
|
|
7. (Later)Cookies (essentially a global built in object which is writeable)
|
|
8. Reference to 'this'
|
|
9. The shared namespace, shared scope (understand how the scope works)
|
|
10. Dynamically add javascript event handlers.
|
|
11. Use of 'eval', self-modifying code
|
|
12. Shared style sheets
|
|
13. Access to shared library functions, eg. parseInt()
|
|
14. Maintain general structural integrity of the document - e.g. tags should appear where they should according to the DTD
|
|
|
|
TODO:
|
|
// creating a new function using a prototype, can the new function access the local variable of the event handler which creates the new function?
|
|
// when you create a new function in different html contexts, what is the value of this?
|
|
// The parser automatically inserts HTML Elements, e.g. TBODY in the table. We have to handle that. The swing html parser doesn't recognize TBODY, though.
|
|
-->
|
|
<style>
|
|
.test{color: red;}
|
|
.odd{background-color: white;}
|
|
.even{background-color: gray;}
|
|
</style>
|
|
<script language=javascript>
|
|
<!--
|
|
//
|
|
// 1. A global value that all portlets might need to access (read/write?)
|
|
// Global variable that the portal would like the portlets to make use of
|
|
// However, this like all other system objects should be made readonly by analysis
|
|
var now=new Date,t1=0;
|
|
t1=now.getTime();
|
|
-->
|
|
</script>
|
|
|
|
<title>Example Portal Page with two Portlets</title>
|
|
</head>
|
|
<body>
|
|
|
|
<table>
|
|
<tbody>
|
|
<tr>
|
|
<td>This will maliciously be removed by a portlet if you click on the text in the gray box</td><td>That should be avoided</td>
|
|
</tr>
|
|
<tr>
|
|
<td width="40%" class=odd>
|
|
<div>
|
|
<!-- Start: Portlet 1 Markup Fragment -->
|
|
|
|
<script type="text/javascript">
|
|
<!--
|
|
// 2. Use of a system global object might be required. Such accesses should be made readonly
|
|
this.agt = navigator.userAgent.toLowerCase();
|
|
this.ie = (this.agt.indexOf("msie") != -1);
|
|
if(this.ie) {
|
|
document.write("<p>Sorry, we do not support Internet Explorer");
|
|
document.close();
|
|
} else {
|
|
document.write("<p>We applaud your taste in browsers!");
|
|
}
|
|
|
|
// The following line is erased using a style element in the malicious portlet
|
|
document.write("<p class=test>The time you started visiting this page is : " + t1 + "</p>");
|
|
|
|
-->
|
|
</script>
|
|
|
|
<h1>Plan a dinner with friends</h1><br>
|
|
<h2>Enter the names of Restaurants in order of descending preference</h2>
|
|
<form action="http://www.google.com/search" name=f onsubmit="sub(this);">
|
|
<input type=hidden name=hl value=en>
|
|
<input type=hidden name=q value="">
|
|
|
|
<script type="text/javascript">
|
|
<!--
|
|
|
|
var counter=2;
|
|
function sub(fm) {
|
|
var qstring = document.f.name1.value + " " + document.f.conf1.value + " restaurant ";
|
|
document.f.q.value = qstring;
|
|
var then = new Date;
|
|
alert("You took " + ((then.getTime()-t1)/1000) + " seconds to submit your preferences.");
|
|
return 1;
|
|
}
|
|
function createLinkElem(target, str) {
|
|
var moveElem = document.createElement("TD");
|
|
moveElem.appendChild(createLink(target, str));
|
|
return moveElem;
|
|
}
|
|
function createLink(target,str) {
|
|
var fnt = document.createElement("FONT");
|
|
fnt.setAttribute("size","-1");
|
|
fnt.appendChild(document.createTextNode(str));
|
|
var lnk = document.createElement("A");
|
|
lnk.setAttribute("href","#");
|
|
|
|
lnk.setAttribute("onclick",target);
|
|
|
|
|
|
lnk.appendChild(fnt);
|
|
return lnk;
|
|
}
|
|
function createInsertNode() {
|
|
var inElem = document.createElement("TR");
|
|
var elem = document.createElement("TD");
|
|
elem.setAttribute("colspan","6");
|
|
elem.setAttribute("align","center");
|
|
var lnk = createLink("insertRow(this);","Insert Row");
|
|
|
|
// creating an event handler by directly assigning the value of the onclick property
|
|
lnk.onclick = iRow;
|
|
elem.appendChild(lnk);
|
|
inElem.appendChild(elem);
|
|
return inElem;
|
|
}
|
|
function iRow() {
|
|
insertRow(this);
|
|
}
|
|
function mUp() {
|
|
moveUp(this);
|
|
}
|
|
function boxNode(nm, str) {
|
|
var elem = document.createElement("TD");
|
|
var inp = document.createElement("INPUT");
|
|
inp.setAttribute("maxlength","2048");
|
|
inp.setAttribute("size","55");
|
|
inp.setAttribute("name",nm);
|
|
inp.setAttribute("value","");
|
|
inp.setAttribute("title",str);
|
|
elem.appendChild(inp);
|
|
return elem;
|
|
}
|
|
function createRow(num) {
|
|
var newElem = document.createElement("TR");
|
|
|
|
var lnk = createLinkElem("moveUp(this);", "Move Up");
|
|
|
|
// creating an event handler using the addEventListener method
|
|
lnk.addEventListener('click', mUp, false);
|
|
newElem.appendChild(lnk);
|
|
|
|
var elemChild = document.createElement("TD");
|
|
elemChild.appendChild(document.createTextNode(num));
|
|
newElem.appendChild(elemChild);
|
|
|
|
newElem.appendChild(boxNode("name"+num,"Name "+num));
|
|
newElem.appendChild(boxNode("conf"+num,"Location "+num));
|
|
|
|
newElem.appendChild(createLinkElem("moveDown(this);","Move Down"));
|
|
newElem.appendChild(createLinkElem("deleteElem(this);","Delete Row"));
|
|
|
|
newElem.setAttribute("id","bar");
|
|
newElem.setAttribute("index",num);
|
|
newElem.setAttribute("rowIndex", 5);
|
|
alert(newElem.getAttribute("rowIndex"));
|
|
return newElem;
|
|
}
|
|
function insertRow(telement) {
|
|
var chld = getRow(telement);
|
|
var par = chld.parentNode;
|
|
var prev = prevRow(chld);
|
|
|
|
var numE,num;
|
|
if(prev) {
|
|
numE = prev.cells[1];
|
|
var num = numE.firstChild.nodeValue;
|
|
if(num=="Rank") {
|
|
num = 1;
|
|
} else {
|
|
num = parseInt(numE.firstChild.nodeValue) + 1;
|
|
}
|
|
} else {
|
|
num = 1;
|
|
}
|
|
par.insertBefore(createInsertNode(), chld);
|
|
par.insertBefore(createRow(num), chld);
|
|
|
|
chld = nextRow(chld);
|
|
while(chld) {
|
|
incNumber(chld, true);
|
|
chld = nextRow(chld);
|
|
}
|
|
|
|
}
|
|
function incNumber(trow, inc) {
|
|
if(trow.cells.length != 6) return;
|
|
// alert("before removing" + trow.getAttribute("id") + " = " + trow.id);
|
|
// trow.id = null;
|
|
// alert("after removing" + trow.getAttribute("id") + " = " + trow.id);
|
|
// alert("before removing" + trow.getAttribute("index") + " = " + trow.index);
|
|
// trow.index = null;
|
|
// alert("after removing" + trow.getAttribute("index") + " = " + trow.index);
|
|
alert(trow.getAttribute("rowIndex"));
|
|
|
|
var node = trow.cells[1];
|
|
var num = node.firstChild.nodeValue;
|
|
num = parseInt(num);
|
|
if(inc) {
|
|
num++;
|
|
} else {
|
|
num--;
|
|
}
|
|
trow.setAttribute("index", num);
|
|
|
|
node.firstChild.nodeValue=num+".";
|
|
|
|
node = trow.cells[2];
|
|
node = node.firstChild;
|
|
node.setAttribute("name","name"+num);
|
|
node.setAttribute("title","Name "+num);
|
|
|
|
node = trow.cells[3];
|
|
node = node.firstChild;
|
|
node.setAttribute("name","conf"+num);
|
|
node.setAttribute("title","Location "+num);
|
|
}
|
|
function prevRow(telement) {
|
|
if(!telement) {
|
|
return null;
|
|
}
|
|
var prev = telement.previousSibling;
|
|
|
|
while(prev && prev.nodeName != "TR") {
|
|
prev = prev.previousSibling;
|
|
}
|
|
return prev;
|
|
}
|
|
function nextRow(telement) {
|
|
if(!telement) {
|
|
return null;
|
|
}
|
|
var next = telement.nextSibling;
|
|
while(next && next.nodeName != "TR") {
|
|
next = next.nextSibling;
|
|
}
|
|
return next;
|
|
}
|
|
function getRow(telement) {
|
|
var chld = telement.parentNode;
|
|
while(chld.nodeName != "TR") {
|
|
chld = chld.parentNode;
|
|
}
|
|
return chld;
|
|
}
|
|
function moveUp(telement) {
|
|
var trow = getRow(telement);
|
|
var prev = prevRow(prevRow(trow));
|
|
var par = trow.parentNode;
|
|
if(prevRow(prev)) {
|
|
incNumber(trow,false);
|
|
incNumber(prev,true);
|
|
var next = nextRow(trow);
|
|
var remove = par.removeChild(trow);
|
|
par.insertBefore(remove,prev);
|
|
|
|
remove = par.removeChild(prev);
|
|
par.insertBefore(remove,next);
|
|
}
|
|
}
|
|
function moveDown(telement) {
|
|
var trow = getRow(telement);
|
|
var next = nextRow(nextRow(trow));
|
|
var par = trow.parentNode;
|
|
if(next) {
|
|
incNumber(trow,true);
|
|
incNumber(next,false);
|
|
var follo = nextRow(trow);
|
|
var remove = par.removeChild(trow);
|
|
par.insertBefore(remove,next);
|
|
|
|
remove = par.removeChild(next);
|
|
par.insertBefore(remove,follo);
|
|
}
|
|
}
|
|
function deleteElem(telement) {
|
|
var tr = getRow(telement);
|
|
follow = nextRow(tr);
|
|
|
|
var par = tr.parentNode;
|
|
var prev = prevRow(tr);
|
|
par.removeChild(prev);
|
|
par.removeChild(tr);
|
|
while(follow) {
|
|
incNumber(follow, false);
|
|
follow = nextRow(follow);
|
|
}
|
|
}
|
|
|
|
-->
|
|
</script>
|
|
|
|
<table>
|
|
<tbody>
|
|
<tr>
|
|
<td> </td><td align=center>Rank</td> <td align=center>Name of Restaurant</td> <td align=center>Location</td><td> </td><td> </td>
|
|
</tr>
|
|
<tr><td colspan=6 align=center><a href="#" onclick="insertRow(this);"><font size="-1">Insert Row</font></a></td></tr>
|
|
<tr id="bar" rowIndex="5">
|
|
<td><a href="#" onclick="moveUp(this);"><font size="-1">Move Up</font></a></td>
|
|
<td>1.</td>
|
|
<td><input maxlength=2048 size=55 name="name1" value="" title="Name 1"></td>
|
|
<td><input maxlength=2048 size=55 name="conf1" value="" title="Location 1"></td>
|
|
<td><font size="-1"><a href="#" onclick="moveDown(this);">Move Down</a></font></td>
|
|
<td><font size="-1"><a href="#" onclick="deleteElem(this);">Delete Row</a></font>
|
|
</tr>
|
|
<tr><td colspan=6 align=center><a href="#" onclick="insertRow(this);"><font size="-1">Insert Row</font></a></td></tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<p><center><input type=submit value="Submit Preferences" name=btnI></center>
|
|
</form>
|
|
|
|
|
|
|
|
<!-- End: Portlet 1 Markup Fragment -->
|
|
</div>
|
|
</td>
|
|
|
|
|
|
<td width="40%" class=even>
|
|
<div>
|
|
<!-- Start Portlet 2 Markup Fragment -->
|
|
|
|
<p id="secret" onclick="malicious(this)">This portlet contains information that is top secret. Thou shalt not read it</p>
|
|
|
|
<!-- Malicious style element -->
|
|
<!--
|
|
<style>
|
|
.test{color: white;}
|
|
</style>
|
|
-->
|
|
|
|
<script type="text/javascript">
|
|
<!--
|
|
|
|
function malicious(elem) {
|
|
var par = elem.parentNode;
|
|
// Creating a disallowed tag
|
|
var base = document.createElement("BASE");
|
|
base.setAttribute("href","http://www.hacker.com/");
|
|
par.appendChild(base);
|
|
|
|
// create a table
|
|
// var tab = document.createElement("TABLE");
|
|
// var tbody = document.createElement("TBODY");
|
|
// var tr = document.createElement("TR");
|
|
var td = document.createElement("TD");
|
|
var txt = document.createTextNode("Text");
|
|
td.appendChild(txt);
|
|
// tr.appendChild(td);
|
|
// tbody.appendChild(tr);
|
|
// tab.appendChild(td);
|
|
par.appendChild(td);
|
|
// TBODY is not automatically inserted
|
|
|
|
|
|
// Accessing and messing with other parts of the tree
|
|
while(par.nodeName != "TBODY") {
|
|
par = par.parentNode;
|
|
}
|
|
|
|
// anything outside the Restricted DOM Spec should be disallowed
|
|
par.firstChild.innerHTML = "This is crazy!";
|
|
alert(par.firstChild);
|
|
par.removeChild(par.firstChild);
|
|
|
|
}
|
|
// The following line writes into a shared global variable, and should be stopped
|
|
t1 = 1000;
|
|
|
|
// Write access to system level objects should be disallowed
|
|
window.status = "Malicious Portlet";
|
|
|
|
-->
|
|
</script>
|
|
|
|
<!-- End: Portlet 2 Markup Fragment -->
|
|
</div>
|
|
</td>
|
|
</tbody>
|
|
</table>
|
|
|
|
</body>
|
|
</html> |