OWASP HTML Sanitizer allow colon in HTML - jakarta-mail

How can I allow : sign in sanitized HTML? I am using it to sanitize HTML code in generating java mail. This code has an inline image content id like <img src=\"cid:image\" height=\"70\" width=\"70\" />. Upon sanitizing, the src attribute is not included in the sanitized html.
PolicyFactory IMAGES = new HtmlPolicyBuilder().allowUrlProtocols("http", "https")
.allowElements("img")
.allowAttributes("src").matching(Pattern.compile("^cid[:][\\w]+$"))
.onElements("img")
.allowAttributes("border", "height", "width").onElements("img")
.toFactory();
String html = "<img src=\"cid:image\" height=\"70\" width=\"70\" />";
final String sanitized = IMAGES.sanitize(html);
System.out.println(sanitized);
The output of above code is:
<img height="70" width="70" />

Why it isn't working
Or rather, why it's working "too well"
By default, HtmlPolicyBuilder disallows URL protocols in src elements. This prevents injections such as
<img src="javascript:alert('xss')"/>
which could potentially lead to the execution of the script after javascript: (in this case, alert('xss'))
There are other protocols (on other elements) that can lead to similar issues:
Even though it doesn't use the javascript protocol, it's still possible to inject a base64-encoded XSS injection:
<object src="data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4="/>
or
Click me
Because of this, HtmlPolicyBuilder assumes that any attribute value containing a colon (in certain attributes) should be treated as dangerous.
How to fix it:
You have to explicitly tell the HtmlPolicyBuilder to allow the cid "protocol", using the allowUrlProtocols method:
PolicyFactory IMAGES = new HtmlPolicyBuilder().allowUrlProtocols("http", "https")
.allowElements("img")
.allowUrlProtocols("cid") // Specifically allow "cid"
.allowAttributes("src").matching(Pattern.compile("^cid[:][\\w]+$"))
.onElements("img")
.allowAttributes("border", "height", "width").onElements("img")
.toFactory();
String html = "<img src=\"cid:image\" height=\"70\" width=\"70\" />";
final String sanitized = IMAGES.sanitize(html);
System.out.println(sanitized);
Output:
<img src="cid:image" height="70" width="70" />

Related

How to get immediate text with webdriverIO

I have html DOM like this:
<div class="alert alert-danger">
<button class="close" aria-hidden="true" data-dismiss="alert" type="button">×</button>
Your username or password was incorrect.
</div>
I would like to get Your username or password was incorrect. text.
If I do:
$('.global-alerts div.alert-danger').getText()
Then I get this ×.
Is there a way to get the only text part inside that div element?
I managed to do something like this:
getErrorMessageText() {
return browser.execute(function () {
const selector = '.global-alerts div.alert-danger';
// #ts-ignore
return $(selector).contents().not($(selector).children()).text().trim();
});
}
And it works.
But does anybody have better idea? Or more of like webdriverIO approach here?
Does it work if you use something like this?
var innerHTML = $('.global-alerts div.alert-danger').getHTML(false);
the false argument tells indicates whether or not to include the selector element tag in the output.
Serious solution
I do not quite see any other way but to use execute in order to "grab" that information from the page.
I would however place it in a browser command (either do it in the config "before" hook, or add a service that adds the command in the before hook)
This is what I ended up with considering typescript as main language, ignoring the use of jQuery, and considering that you use the before hook:
/**
* Gets executed before test execution begins. At this point you can access to all global
* variables like `browser`. It is the perfect place to define custom commands.
* #param {Array.<Object>} capabilities list of capabilities details
* #param {Array.<String>} specs List of spec file paths that are to be run
* #param {Object} browser instance of created browser/device session
*/
before: function (_capabilities: any, _specs: any, browser: WebdriverIO.Browser) {
browser.addCommand(
'getNodeText',
async function() {
return this.execute(
(selector: string) =>
Array.from( document.querySelector(selector).childNodes || [])
.filter((n: HTMLElement) => n.nodeType === n.TEXT_NODE)
.map(n => n.textContent)
.reduce(function(f, c) {return f+c;}, '')
.replace('\n', '')
.trim(),
this.selector
);
},
true
);
},
With this approach, typescript might complain about the function that passed to webdriver to get executed, so you can either write it properly, or just move it to a .js file and be done with it.
Just watch for document.querySelector(selector), in theory, it should not be null since the command is executed on an already found by webdriver element.
The way you grab the text there is just await (await $('.alert.alert-danger').getNodeText());
This should return the full string from within the node itself, but not any subchild.
Note: If you end up with an element like: <div id="mytxt">my text style is <strong>strong</strong> and <italic> italic </italic>. - html fan</div> and you do this getNodeText(), you probably end up with the value my text style is and . - html fan.
The "don't get bothered to much" solution
This approach will also sort of check that the "x" button is still there.
await expect($('.global-alerts div.alert-danger')).toHaveText('xYour username or password was incorrect.')
in latest version of WebDriverIO (v8), you can use this selector: aria/YourContent. For example:
With the DOM like this:
<h1>Hello World!</h1>
You can use this selector
console.log(await $('aria/Hello World!').getText()) // outputs: "Hello World!"
Ref: https://webdriver.io/docs/selectors/#fetch-by-content

Programmatically include xhtml fragment in MyFaces

I know it is possible in MyFaces to programmatically add a xhtml fragment to the component tree, instead of using ui:include.
The snipplet I am talking about is as (in the original form):
ViewDeclarationLanguage vdl = facesContext.getApplication().getViewHandler().getViewDeclarationLanguage(facesContext, facesContext.getViewRoot().getViewId());
Map<String, Object> attributes = new HashMap<String, Object>();
attributes.put("src", "/fragmentToInclude.xhtml");
UIComponent component = vdl.createComponent(facesContext, "http://java.sun.com/jsf/facelets", "include", attributes);
The problem I am facing is I am not able to pass in parameters, that would normally be passed in via <ui:param .../> tag.
What I tried, of course, was to add params into attributes map:
attributes.put("testingParam1", "Yeah, it worked!");
But this seems not to help. Content of my testing fragment is quite simple:
<ui:composition xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<div class="testingDiv">#{empty testingParam1 ? 'testingParam1 IS EMPTY' : testingParam1}</div>
</ui:composition>
The fragment is properly loaded, but I only get that 'is empty' message.
I have walked through multiple resources but haven't found answer there:
NullPointerException in MyFaces facelet inclusion
http://lu4242.blogspot.cz/2014/01/whats-new-in-myfaces-22.html
https://java.net/projects/javaserverfaces-spec-public/lists/jsr344-experts/archive/2014-03/message/12
https://java.net/projects/javaserverfaces-spec-public/lists/users/archive/2014-10/message/120
Please, do you know, is this even possible? Or am I missing something? Thanks for any hints.

How do I ng-src bind an image?

I am trying to use data-ng-src to display a pictures in my angular application. I get a value from my database field called "pic". For example let say the return value of the field "pic" is 125(this is an integer value). I have a image file on my server called 125.jpg at file location
\\someserv\zpicturesFiles\zpicturesResources\Database\VFP\PhotoID\itc\portrait\
I need to render this in my html, but I don't know how to attach the file location with the value in the binding {{e.pic}}. I need {{e.pic}} to pickup
\\someserv\zpicturesFiles\zpicturesResources\Database\VFP\PhotoID\itc\portrait\125.jpg
but currently {{e.pic}} has an integer value of 125 (because that what it returned from sql server db). How can I make {{e.pic}} see the value of \someserv\zpicturesFiles\zpicturesResources\Database\VFP\PhotoID\itc\portrait\125.jpg. This is in an ng-repeat. Here is my code so far implementing the suggestion below.
<section class="mainbar" data-ng-controller="employees as vm">
....
<div class="padd" data-ng-repeat="e in vm.employees">
<div class="user">
<img data-ng-src="{{'\\someserv\zpicturesFiles\zpicturesResources\Database\VFP\PhotoID\itc\portrait\' + e.pic + '.jpg' }}">
class="img-polaroid user-pic"/>
I am getting an error as follows:
Error: [$parse:lexerr] Lexer Error: Unterminated quote at columns
97-99 [' ] in expression
['\someserv\zpicturesFiles\zpicturesResources\Database\VFP\PhotoID\itc\portrait\'
+ e.pic + '.jpg' ]. http://errors.angularjs.org/1.2.12/$parse/lexerr?p0=Unterminated%20quote&p1=s%2097-99%20%5B'%20%5D&p2='%5C%5Csomeserv%5CzpictureFiles%5CzpicturesResources%5CDatabase%5CVFP%5CPhotoID%5Citc%5Cportrait%5C'%20%2B%20e.pic%20%2B%20'.jpg'%20
at http:// localhost:56014/scripts/angular.js:78:12
what is it not liking?
thanks
Nick
Fiddle Example. The reason I added the e.pick && '\...' is because ng-src will hide until the value is valid. In the fiddle you will see broken will flash with a broken image, until pathExt is set.
Use:
<img data-ng-src="{{e.pic && '\fileserver\pictures\' + e.pic + '.jpg' }}"
Alternatively create something on your scope to make it cleaner:
$scope.getImage = function(e){
return e && e.pic && ('\fileserver\pictures\' + e.pic + '.jpg');
}
HTML:
<img data-ng-src="getImage(e)" >

Pass JSP Input with href link

I want to pass input data with a href instead of a button. The problem is I am sending an array, my for loop the input data is being stored so It creates multiple links. What is the course of action to take to fix this.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Firstjsp</title>
</head>
<body>
<% String locations[] = {"Loan 1", "33.890542", "151.274856", "Address 1","true", "-35404.34"};
for (int i =0; i<locations.length; i++)
{
%>
<form name="submitForm" method="POST" action="Mapper.jsp">
<Input type = "Hidden" name = "loc" value = "<%= locations[i] %>">
View Map
</form>
<%
}
%>
</body>
</html>
The HTTP request query string takes the form of name1=value1&name2=value2&name3=value3. So all you need to do is converting the String[] to a String in exactly that format. Additional requirement is to use URLEncoder to encode the names and values so that any special characters are been converted to %nn format for proper usage in URLs.
This should do:
StringBuilder builder = new StringBuilder();
for (String location : locations) {
if (builder.length() > 0) builder.append("&");
builder.append("loc=").append(URLEncoder.encode(location, "UTF-8");
}
String locationsQuery = builder.toString();
Then you can specify it in the link as follows:
View Map
How to obtain it in the other side has already been answered in your previous question.
Unrelated to the concrete problem, writing raw Java code in JSPs is officially discouraged since a decade. You can achieve the same on a more easy manner with JSTL <c:url>, <c:param> and <c:forEach>. Here's a kickoff example assuming that you've done a request.setAttribute("locations", locations) in your preprocessing servlet or in top of JSP:
<c:url value="Mapper.jsp" var="mapperURL">
<c:forEach items="${locations}" var="loc">
<c:param name="loc" value="${loc}" />
</c:forEach>
</c:url>
View Map

retain value of input type file in a jsp file while being dynamically generated

i have a jsp page where i have a input type file and i m allowing the user to browse files. i have one such input on jsp and the rest i m generating dynamically by javascript.
this is my jsp code:
<div id="labelContainer" style="display:inline">
<table align="center">
<tr>
<td align="left"><input type="text" id="label0" name="label0" size="15"></td>
<td align="center"><input type="file" id="filePath0" name="browsetrainset0"></td>
<td id="addlabel" ><img src="../images/add.png" title="Add Label" onclick="addLabel()"></td>
<td id="removelabel"><img src="../images/remove.png" title="Remove Label" onclick="removeLabel('labelDiv0')"></td>
</tr>
</table>
</div>
and this is my javacsritp code:
function addLabel(){
var text="";
lCount++;
text+=("<table id='labelDiv"+lCount+"' align='center'>");
text+=("<tr>");
text+=("<td align='left' style='display:none'><input type='checkbox' checked='true' name='labelchkbox'/></td>");
text+=("<td align='left' id='label'><input type='text' id='label"+lCount+"' name='label"+lCount+"' size='15'></td>");
text+=("<td align='center'id='filePath' ><input type='file' id='filePath"+lCount+"'name='browsetrainset"+lCoun t+"'></td>");
text+=("<td id='addlabel' ><img src='../images/add.png' title='Add Label' onclick='addLabel()'></td>");
text+=("<td id='removelabel'><img src='../images/remove.png' title='Remove Label' onclick=\"removeLabel('labelDiv"+lCount+"')\"></td>");
text+=("</tr>");
text+=("</table>");
document.getElementById("labelContainer").innerHTM L+=text;
}
but i m not able to retain the value of the file path i browse, on the jsp page once i click the add label and generate another input type file.
I am using IE7. Please tell me how to reatin the value of the browsed files so that i can use them further.
document.getElementById("labelContainer").innerHTM L+=text;
Never, ever use += on innerHTML. It does not do what you think.
Instead, it laboriously serialises the entire contents of the div into HTML, adds your string onto the HTML code, and then parses the whole lot back into objects.
This is slow, and loses all information that cannot be remembered in an HTML string, such as JavaScript references, event handlers (all your onclicks will stop working) and form field contents (including file uploads).
You could add all the new HTML content to a temporary container instead, then move that using DOM methods to the destination:
var div= document.createElement('div');
div.innerHTML= text;
while (div.firstChild)
document.getElementById("labelContainer").appendChild(div.firstChild);
Or you can use DOM methods to create and add the nodes directly. In your case since the new nodes are so similar to the old ones, you could clone them:
function addLabel() {
var container= document.getElementById('labelContainer');
var tables= container.getElementsByTagName('table');
var n= tables.length;
var table= tables[0].cloneNode(true);
table.id= 'labelDiv'+n;
var inputs= table.getElementsByTagName('input');
inputs[0].id=inputs[0].name= 'label'+n;
inputs[1].id=inputs[1].name= 'browsetrainset'+n;
container.appendChild(table);
}
(Care: IE has some issues with changing field names with things like radio buttons though.)
If you want to be accessible without JavaScript (generally a good idea), the usual approach is to include the maximum number of entries you might, and use script to hide the ones that aren't in use.
If I remember correctly, it is not possible to programmatically set the filepsec associated with an <input type="file"> element, as this would constitute a security risk, by allowing malicious scripts to upload files that had not been specifically chosen by the user.
The only way to set the filespec is to browse to it from the web browser.

Resources