Receiving text from the user, most notably through a control, and rendering it as HTML in another control can lead to a cross-site scripting vulnerability.
If the XSS attack vector includes a user-defined control, then we can mitigate the issue by sanitizing the user-provided input in the implementation of the control:
- Where possible, define the property type to something other than
stringorany. If a value should be used, then opt for theenumtype which only allows a predefined set of strings. - Use escaping functions in
sap.base.security. Relevant sanitizers includeencodeXMLandencodeHTML. - When using API with
apiVersion: 2(Semantic Rendering), do not useRenderManager.unsafeHtmlunless the control propertysanitizeContentis set totrue. - When using the now-deprecated older API with
RenderManager.writeorRenderManager.writeAttribute, use their respective counterpartsRenderManager.writeEscapedandRenderManager.writeAttributeEscapedwhich sanitizes their rendered contents.
An XSS attack vector can still exist even when no user-defined control is used. In this case, a model property or a control property act as an intermediate step when external data is passed in. In this case, the UI5 application should not use the property as is, but should sanitize the contents before reading it. Such sanitization can take place in the controller or in the view declaration using expression bindings.
This custom control vulnerable.control.xss calls unsafeHtml on a given RenderManager instance in its static renderer function. Since its text property is an unrestricted string type, it can point to a string with contents that can be interpreted as HTML. If it is the case, unsafeHtml will render the string, running a possibly embedded JavaScript code in it.
sap.ui.define(["sap/ui/core/Control"], function (Control) {
return Control.extend("vulnerable.control.xss", {
metadata: { properties: { text: { type: "string" } } },
renderer: {
apiVersion: 2,
render: function (oRm, oControl) {
oRm.openStart("div", oControl);
oRm.unsafeHtml(oControl.getText()); // sink
oRm.close("div");
}
}
});
})This is the same custom control without the possibility of XSS using several means of sanitization: The property text is enforced to a non-string type, hence disallows unrestricted strings (This is espcially applicable if the expected input is a number anyways). Also, the sap.base.security.encodeXML function is used to escape HTML control characters.
sap.ui.define(["sap/ui/core/Control", "sap/base/security/encodeXML"], function (Control, encodeXML) {
return Control.extend("vulnerable.control.xss", {
metadata: { properties: { text: { type: "int" } } }, // constrain the type
renderer: {
apiVersion: 2,
render: function (oRm, oControl) {
oRm.openStart("div", oControl);
oRm.unsafeHtml(encodeXML(oControl.getText()); // encode using security functions
oRm.close("div");
}
}
});
})This example contains only library controls that are not user-defined. The untrusted user input flows from sap.m.Input and directly flows out via sap.ui.core.HTML through the model property input as declared in the onInit method of the controller.
<sap.ui.core.mvc.View controllerName="vulnerable.controller.app">
<sap.m.Input value="{/input}" /> <!-- XSS Source -->
<sap.ui.core.HTML content="{/input}"/> <!-- XSS Sink -->
</sap.ui.core.mvc.View>sap.ui.define(["sap/ui/core/mvc/Controller", "sap/ui/model/json/JSONModel"],
function (Controller, JSONModel) {
return Controller.extend("vulnerable.controller.app", {
onInit: function () {
var oData = { input: null };
var oModel = new JSONModel(oData);
this.getView().setModel(oModel);
},
});
},
);The issue can be resolved by setting the HTML control's sanitizeContent attribute to true.
<sap.ui.core.mvc.View controllerName="vulnerable.controller.app">
<sap.m.Input value="{/input}" />
<sap.ui.core.HTML content="{/input}" sanitizeContent="true" />
</sap.ui.core.mvc.View>- OWASP: DOM Based XSS.
- SAP UI5 Documentation: Cross-site Scripting in UI5.
- SAP UI5 Documentation: Prevention of Cross-site Scripting in UI5.
- SAP UI5 Documentation: API Documentation of sap.ui.core.RenderManager.
- SAP UI5 Documentation: Defining Control Properties.
- SAP UI5 Documentation: Expression Binding.
- SAP UI5 API Reference:
sap.ui.core.HTML. - Common Weakness Enumeration: CWE-79.
- Common Weakness Enumeration: CWE-116.