So this time we got an web application and the corresponding – following – source code.
package com.jwt.jsf.bean; import org.apache.commons.collections4.trie.PatriciaTrie; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; import java.io.StringWriter; import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped; import static org.apache.commons.lang3.StringEscapeUtils.unescapeJava; import org.apache.commons.io.IOUtils; @ManagedBean(name="notesBean") @SessionScoped public class NotesBean implements Serializable { /** * */ private PatriciaTrie<Integer> trie = init(); private static final long serialVersionUID = 1L; private static final String securitytoken = "auth_token_4835989"; public NotesBean() { super(); init(); } public String getTrie() throws IOException { if(isAdmin(trie)) { InputStream in=getStreamFromResourcesFolder("data/flag.txt"); StringWriter writer = new StringWriter(); IOUtils.copy(in, writer, "UTF-8"); String flag = writer.toString(); return flag; } return "INTRUSION WILL BE REPORTED!"; } public void setTrie(String note) { trie.put(unescapeJava(note), 0); } private static PatriciaTrie<Integer> init(){ PatriciaTrie<Integer> trie = new PatriciaTrie<Integer>(); trie.put(securitytoken,0); return trie; } private static boolean isAdmin(PatriciaTrie<Integer> trie){ return !trie.containsKey(securitytoken); } private static InputStream getStreamFromResourcesFolder(String filePath) { return Thread.currentThread().getContextClassLoader().getResourceAsStream(filePath); } }
The code creates a trie and stores the security token auth_token_4835989 and a string entered by the user in it. Later it checks if the trie contains the security token, if not, the flag is returned.
I had a closer look on input validation and found the method unescapeJava (line 43). I googled for the method and found the following stack overflow post https://stackoverflow.com/questions/3537706/how-to-unescape-a-java-string-literal-in-java. The first respond says that It forgets about \0 for null. So I just put \0 as user input and got the flag: HV19{get_th3_chocolateZ}.
The actual bug, which is in the patrician trie implementation – not the unescape java function – can be found here.