Skip to content

Commit

Permalink
[VAS] 11330 : add sanity on html injection
Browse files Browse the repository at this point in the history
  • Loading branch information
oussamasic committed Apr 3, 2023
1 parent 0e30808 commit 4e56c08
Show file tree
Hide file tree
Showing 10 changed files with 135 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public static void checkSafeFilePath(String path) {
* using File.separator FileSystem String
* @throws IOException thrown when any check fails with UnChecked or Runtime exception
*/
public static void checkSafeFilePath(String rootPath, String... subPaths) {
public static void checkSafeFilePath(String rootPath, String... subPaths) throws InvalidFileSanitizeException {
try {
checkNullParameter(rootPath);
String finalPath = rootPath;
Expand All @@ -86,7 +86,7 @@ public static void checkSafeFilePath(String rootPath, String... subPaths) {
}
checkSafeFilePath(finalPath);
} catch (Exception e) {
throw e;
throw new InvalidFileSanitizeException(e.getMessage());
}
}

Expand Down Expand Up @@ -145,7 +145,7 @@ private static void doFilenameCheck(String pathName) {
if(!pathName.matches(FILENAME_PATTERN)) {
LOGGER.error("Invalid pathName {} ", pathName);
throw new InvalidFileSanitizeException(String
.format("Invalid filename (%s) (has unauthorized characters in part %s", pathName));
.format("Invalid filename (%s) : has unauthorized characters", pathName));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@
*/
public class SanityChecker {

private static final String INVALID_IDENTIFIER_SANITIZE = "Sanitizing failed; Invalid input identifier : ";
private static final String INVALID_HEADER_SANITIZE = "Sanitizing failed; Invalid request header : ";
private static final String INVALID_CRITERIA = "Criteria failed when sanitizing, it may contains insecure data : ";
private static final String JSON_IS_NOT_VALID_FROM_SANITIZE_CHECK = "Json is not valid from Sanitize check";
private static final int DEFAULT_LIMIT_PARAMETER_SIZE = 5000;
Expand All @@ -63,11 +61,7 @@ public class SanityChecker {
private static final long DEFAULT_LIMIT_FILE_SIZE = 8000000000L;

public static final String HTTP_PARAMETER_VALUE = "HTTPParameterValue";
private static final String HTTP_PARAMETER_NAME = "HTTPParameterName";
private static final String HTTP_HEADER_NAME = "HTTPHeaderName";
private static final String HTTP_HEADER_VALUE = "HTTPHeaderValue";

// TODO : verify the difference between this defined limit and the previous ones
private static final int REQUEST_LIMIT = 10000;

/**
Expand Down Expand Up @@ -108,14 +102,10 @@ public static boolean isValidParameter(String value) {
return !isStringInfected(value, HTTP_PARAMETER_VALUE) || PARAMETERS_KEYS_OF_DSL_QUERY_WHITELIST.contains(value);
}

public static boolean isValidParameterName(String value) {
return !isStringInfected(value, HTTP_PARAMETER_NAME);
}

/**
* Sanitize the fileName
*
* @param fileName
* @param fileName : name of a file
* @return true/false
*/
public static void isValidFileName(String fileName) throws PreconditionFailedException {
Expand Down Expand Up @@ -170,7 +160,7 @@ public static void checkJsonAll(String json) throws InvalidParseOperationExcepti
* checkSecureParameter : Check sanity of String: no javascript/xml tag, neither html tag
* check if the string is not infected or contains illegal characters
*
* @param params
* @param params : sequence of strings de check
* @throws PreconditionFailedException
* @throws InvalidParseOperationException
*/
Expand Down Expand Up @@ -227,11 +217,11 @@ private static void checkSecureParam(String param)
try {
checkSanityTags(param, getLimitParamSize());
checkHtmlPattern(param);
} catch (InvalidParseOperationException exception) {
} catch (InvalidParseOperationException | PreconditionFailedException exception) {
throw new InvalidParseOperationException("Error with the parameter ", exception);
}
} else {
throw new PreconditionFailedException("the parameter is not valid");
throw new PreconditionFailedException("the parameter " + param + " is not valid");
}
}

Expand Down Expand Up @@ -299,11 +289,11 @@ private static void checkSanityTags(String dataLine, String invalidTag)
* checkHtmlPattern : check against Html Pattern within value (not allowed)
*
* @param param
* @throws InvalidParseOperationException when Sanity Check is in error
* @throws PreconditionFailedException when Sanity Check is in error
*/
private static void checkHtmlPattern(String param) throws InvalidParseOperationException {
public static void checkHtmlPattern(String param) throws PreconditionFailedException {
if (StringUtils.HTML_PATTERN.matcher(param).find()) {
throw new InvalidParseOperationException("HTML PATTERN found");
throw new PreconditionFailedException("the parameter : " + param + " is not valid");
}
}

Expand Down Expand Up @@ -334,7 +324,7 @@ public static void checkJsonSanity(JsonNode json) throws InvalidParseOperationEx
while (fields.hasNext()) {
final Map.Entry<String, JsonNode> entry = fields.next();
final String key = entry.getKey();
if (isValidParameterName(key) || PARAMETERS_KEYS_OF_DSL_QUERY_WHITELIST.contains(key)) {
if (isValidParameter(key)) {
checkSanityTags(key, getLimitFieldSize());
} else {
throw new PreconditionFailedException("Invalid JSON key: " + key);
Expand All @@ -352,7 +342,11 @@ public static void checkJsonSanity(JsonNode json) throws InvalidParseOperationEx
}
} else if (!value.isValueNode()) {
checkJsonSanity(value);
} else {
} else if(value.isTextual()) {
checkHtmlPattern(value.textValue());
checkSanityTags(value.textValue(), getLimitParamSize());
}
else {
validateJSONField(value);
}
}
Expand All @@ -378,20 +372,6 @@ private static void checkJsonFileSize(String json) throws InvalidParseOperationE
}
}

/*
* @return the limit File Size (XML or JSON)
*/
public static long getLimitFileSize() {
return limitFileSize;
}

/**
* @param limitFileSize the limit File Size to set (XML or JSON)
*/
public static void setLimitFileSize(long limitFileSize) {
SanityChecker.limitFileSize = limitFileSize;
}

/**
* @return the limit Size of a Json
*/
Expand All @@ -413,13 +393,6 @@ public static int getLimitFieldSize() {
return limitFieldSize;
}

/**
* @param limitFieldSize the limit Size of a Field in a Json to set
*/
public static void setLimitFieldSize(int limitFieldSize) {
SanityChecker.limitFieldSize = limitFieldSize;
}

/**
* @return the limit Size of a parameter
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@
public class SafeFileCheckerTest {
private final String VALID_ROOT_PATH = "mydirectory";
private final String INVALID_ROOT_PATH = "my|filena?me?query=<code>danger</code>.json";
private final String VALID_SUBPATH = "good_json_sanity";
private final String VALID_SUBPATH = "good_json_sanity.json";
private final String INVALID_PATH = "file#..$$/text";

private static List<String> validPaths = new ArrayList<>();
private static List<String> invalidPaths = new ArrayList<>();
private static List<String> validFilenames = new ArrayList<>();
private static final List<String> validPaths = new ArrayList<>();
private static final List<String> invalidPaths = new ArrayList<>();
private static final List<String> validFilenames = new ArrayList<>();

@BeforeClass
public static void setUpBeforeClass() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,27 +45,25 @@
import java.util.Optional;

import static org.assertj.core.api.Assertions.assertThatCode;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

public class SanityCheckerTest {

private final String TEST_BAD_JSON = "bad_json";
private final String TEST_GOOD_JSON = "good_json_sanity";
private final String TEST_GOOD_JSON_CRITERIA = "good_criteria.json";
private final String TEST_BAD_JSON = "bad_json.json";

@Before
public void setUp() {
}

@Test
public void givenJsonWhenValueIsTooBigORContainXMLTag()
throws InvalidParseOperationException, IOException {
throws InvalidParseOperationException, PreconditionFailedException, IOException {
final File file = PropertiesUtils.findFile(TEST_BAD_JSON);
final JsonNode json = JsonHandler.getFromFile(file);
Assertions.assertThat(json).isNotNull();
assertThatCode(() -> SanityChecker.checkJsonSanity(json)).
isInstanceOf(InvalidParseOperationException.class);
isInstanceOf(PreconditionFailedException.class);
}

@Test
Expand Down Expand Up @@ -103,14 +101,14 @@ public void givenJsonStringWhenValueIsTooBigORContainXMLTagUsingAll()
public void givenJsonWhenGoodSanityThenReturnTrue()
throws FileNotFoundException, InvalidParseOperationException {
final long limit = SanityChecker.getLimitJsonSize();
final String TEST_GOOD_JSON = "good_json_sanity.json";
try {
SanityChecker.setLimitJsonSize(100);
final File file = PropertiesUtils.findFile(TEST_GOOD_JSON);
final JsonNode json = JsonHandler.getFromFile(file);
try {
SanityChecker.checkJsonAll(json);
fail("Should failed with an exception");
} catch (final InvalidParseOperationException e) {
} catch (final InvalidParseOperationException ignored) {
}
SanityChecker.setLimitJsonSize(10000);
SanityChecker.checkJsonAll(json);
Expand All @@ -129,6 +127,7 @@ public void givenStringNotValidParam() throws InvalidParseOperationException, Pr
@Test
public void givenCriteriaWhenGoodSanityThenReturnTrue()
throws FileNotFoundException, InvalidParseOperationException, PreconditionFailedException {
final String TEST_GOOD_JSON_CRITERIA = "good_criteria.json";
final File file = PropertiesUtils.findFile(TEST_GOOD_JSON_CRITERIA);
final JsonNode json = JsonHandler.getFromFile(file);
assertThatCode(() ->
Expand Down Expand Up @@ -163,7 +162,7 @@ public void testCheckSecureParameterWithXmlString()
@Test
public void testCheckSecureParameterWithBadStringAndThrowException() {
assertThatCode(() -> SanityChecker.checkSecureParameter("§§§§§***ù^65")).
hasMessage("the parameter is not valid");
hasMessage("the parameter §§§§§***ù^65 is not valid");
}

@Test(expected = PreconditionFailedException.class)
Expand Down Expand Up @@ -266,7 +265,7 @@ public void testCheckSecureParameterWithIdAsParameter() {

@Test
public void isValidParameterName_tests() {
assertTrue(SanityChecker.isValidParameterName("vitamui-primary"));
assertTrue(SanityChecker.isValidParameter("vitamui-primary"));
}

@Test
Expand Down Expand Up @@ -313,4 +312,62 @@ public void sanitizeJson_should_not_fail_with_ingest_search_keys()
doesNotThrowAnyException();
}

@Test
public void test_isValidParameterName_with_html_code() {
assertFalse(SanityChecker.isValidParameter("<vitamui>aa<primary>"));
}

@Test
public void test_sanitizeCriteria_with_object_contains_xml_tag()
throws InvalidParseOperationException, PreconditionFailedException, IOException {
final String OBJECT_XML_TAG = "object_with_xml_tag.json";
final File file = PropertiesUtils.findFile(OBJECT_XML_TAG);
final JsonNode json = JsonHandler.getFromFile(file);
Assertions.assertThat(json).isNotNull();
assertThatCode(() -> SanityChecker.sanitizeCriteria(json)).
isInstanceOf(PreconditionFailedException.class);
}

@Test
public void test_checkHtmlPattern_with_html_text() {
assertThatCode(() -> SanityChecker.checkHtmlPattern("<div class=\"col-6 form-control\"> <p class=\"title-text\">bla bla bla</p></div>"))
.isInstanceOf(PreconditionFailedException.class)
.hasMessageContaining("the parameter :");
}

@Test
public void test_sanitizeCriteria_with_object_contains_html_tag()
throws InvalidParseOperationException, PreconditionFailedException, IOException {
final String OBJECT_HTML_TAG = "object_with_html_tag.json";
final File file = PropertiesUtils.findFile(OBJECT_HTML_TAG);
final JsonNode json = JsonHandler.getFromFile(file);
Assertions.assertThat(json).isNotNull();
assertThatCode(() -> SanityChecker.sanitizeCriteria(json)).
isInstanceOf(PreconditionFailedException.class);
}

@Test
public void test_checkHtmlPattern_with_correct_text() {
assertThatCode(() -> SanityChecker.checkHtmlPattern("test test good values"))
.doesNotThrowAnyException();
}

@Test
public void test_sanitizeCriteria_with_object_contains_correct_values()
throws InvalidParseOperationException, PreconditionFailedException, IOException {
final String OBJECT_WITH_CORRECT_VALUES = "object_with_correct_values.json";
final File file = PropertiesUtils.findFile(OBJECT_WITH_CORRECT_VALUES);
final JsonNode json = JsonHandler.getFromFile(file);
Assertions.assertThat(json).isNotNull();
assertThatCode(() -> SanityChecker.sanitizeCriteria(json)).
doesNotThrowAnyException();
}

@Test
public void test_checkJsonAll_with_null_object() {
assertThatCode(() -> SanityChecker.checkJsonAll((JsonNode) null)).
isInstanceOf(InvalidParseOperationException.class)
.hasMessage("Json is not valid from Sanitize check");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@
"firstname" : "nabil",
"surname" : "CHEN"
},
"id": "$id_async$",
"type": "vitamui",
"state": "done",
"task_status": "commit",
"start_date": "2020-08-11T03:06:17.396Z",
"end_date": "2020-08-11T03:06:17.396Z",
"expiration_date": "2020-08-11T03:06:17.396Z",
"result_link": "https://xxx/v1/vitamui/456"
"result_link": "link link"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"firstName" : "Oussama",
"lastName" : "zerouali",
"id": "PersonId",
"type": "vitamui",
"state": "done",
"task_status": "commit",
"start_date": "2020-08-11T03:06:17.396Z",
"end_date": "2020-08-11T03:06:17.396Z",
"expiration_date": "2020-08-11T03:06:17.396Z",
"result_link": "link to link"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"firstName" : "<div class=\"col-6 form-control\"> <p class=\"title-text\">bla bla bla</p></div>",
"lastName" : "<div class=\"col-6 form-control\"> <p class=\"title-text\">bla bla bla</p></div>",
"id": "PersonId",
"type": "vitamui",
"state": "done",
"task_status": "commit",
"start_date": "2020-08-11T03:06:17.396Z",
"end_date": "2020-08-11T03:06:17.396Z",
"expiration_date": "2020-08-11T03:06:17.396Z",
"result_link": "link to link"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"firstName" : "Oussama",
"lastName" : "zerouali",
"id": "PersonId",
"type": "vitamui",
"state": "done",
"task_status": "commit",
"xml_tag" : "<note><to>Tove</to><from>Jani</from><heading>Reminder</heading><body>Don't forget me this weekend!</body></note>",
"start_date": "2020-08-11T03:06:17.396Z",
"end_date": "2020-08-11T03:06:17.396Z",
"expiration_date": "2020-08-11T03:06:17.396Z",
"result_link": "link to link"
}
23 changes: 10 additions & 13 deletions ui/ui-frontend/projects/identity/src/app/user/user.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,19 +71,16 @@ export class UserService extends SearchService<User> {
user.email = user.email;

return this.userApi.create(user).pipe(
tap(
(response: User) => {
this.snackBarService.open({
message: 'SHARED.SNACKBAR.USER_CREATE',
icon: 'vitamui-icon-key',
translateParams: {
param1: response.firstname,
param2: response.lastname,
},
});
},
(error) => this.snackBarService.open({ message: error.error.message, translate: false })
)
tap((response: User) => {
this.snackBarService.open({
message: 'SHARED.SNACKBAR.USER_CREATE',
icon: 'vitamui-icon-key',
translateParams: {
param1: response.firstname,
param2: response.lastname,
},
});
})
);
}

Expand Down

0 comments on commit 4e56c08

Please sign in to comment.