
, . ? , β . .
? , ? , ? β , .
Java, -, SonarQube Find Security Bugs, .
Heisenbug: β , β .
:
, OWASP ZAP Accunetix.
, :
, .
?
.
, .
( ) . β Lint, 1979 , . Lint β , grep.
, :

, : API, , .
β . , , , .
, , . .
(, β SQL β) , .
?
-, (AST). AST . , .
Java- - :

, AST:
β β, equals(), hashCode()β;
β β password secretβ.
-, (Control Flow Graph, CFG). CFG , .

. CFG . CFG β , , , taint analysis.
, , , , . cross-site scripting (XSS) :
String foo = request.getParameter("foo");
response.getWriter().write(foo);
JavaScript .
? Β«fooΒ», . . , foo , html , HTML-.
Taint analysis , : , cross site scripting, β , .
? , , . tainted, Β«taintΒ» β «», «». foo tainted, getParameter , .

, ? . , , , . , API β β,. , - .
, , . β . XSS; SQL- SQL-. .
tainted: sink, «», «».

tainted sink, .
, html foo, . β , . tainted sink. , tainted sink , , .

, , .
, , . , . web- .
β reflection. Reflection Dependency Injection- , , , taint analysis.

, . C , bar(). , bar() - sink, , .
,
web-, β . JSP, Java- , β HTML- . .

, taint analysis, , .
Java : , . . :
- : , . Java, JavaScript TypeScript, , Android-.
- : taint analysis. , , , .
- , , , Β« Β» , .
- , Β« Β» : , , , . , collaboration .
- , , . , .
, . , OWASP (Open Web Application Security Project) 2016- (https://github.com/OWASP/benchmark). OWASP β Java . :

, , . β , . , β .
( ) ( ) . .
, , , . - , . , .
OWASP Find Security Bugs , , , . .
? , , .
Find Security Bugs. Java, FindBugs, SpotBugs. Find Security Bugs , , Android.
Java, taint analysis.
, , , SonarQube. Find Security Bugs SonarQube, .
. β Spring Thymeleaf.
, Find Security Bugs , . GitHub.
1
β XSS, HTML-.
@ExceptionHandler({IllegalArgumentException.class})
public void oops(HttpServletRequest request, HttpServletResponse response) {
String originalURL = request.getRequestURL() + "?" +
URLDecoder.decode(request.getQueryString());
PrintWriter writer = response.getWriter();
writer.write("<h1>Error procesing page " + originalURL + "</h1>");
writer.flush();
}
, .
originalURL tainted, request.getQueryString() HttpServletRequest .
writer.write() sink, ββ .
, , , :

2
@GetMapping("/photo")
public String photo(@RequestParam("id") long id, Model model) {
Photo photo = photoRepository.findOne(id);
m.addAttribute("photo", photo)
return "/photo";
}
<div th:each="comment : ${photo.comments}">
<p th:utext="${comment.text}"></p>
</div>
Spring endpoint, . . ?
. photoRepository.findOne(id) , , taint. (th:utext ). HTML-, HTML.
Find Security Bugs .
.
: , - ( Β«ph:utextΒ») β . , , - .
: .
, addAttribute() sink, taint sink .
Find Security Bugs . . Find Security Bugs c :

sink β addAttribute(). , , , , , , , ββ .
, Find Security Bugs , , Java-.
3
@GetMapping("/photo")
public String photo(@RequestParam("id") long id, Model model) {
Photo photo = photoRepository.findOne(id);
model.addAttribute("photo", photo);
return "/photo";
}
Spring endpoint, . ?
! , . IDOR β Insecure Direct Object Reference.
:
@GetMapping("/photo")
public String photo(@RequestParam("id") long id, Model model) {
Photo photo = photoRepository.findOne(id);
User currentUser = getCurrentUser = getCurrentUser();
if (!canAccess(currentUser, author)) {
return "/error/302";
}
model.addAttribute("user", author);
model.addAttribute("photo", photo);
return "/photo";
}
: ? , , - , . , .
, , .
, Β«, , , Spring endpoint- , canAccess(). , Β».
. Find Security Bugs β Java.
import edu.umd.cs.findbugs.Detector;
public class IdorDetector implements Detector {
@Override
public void vistClassContext(ClassContext classContext) {
}
@Override
public void report() {
}
}
Find Security Bugs Detector. , , .
, : visitClassContext(), , report(), , .
? , Spring endpoint- , , :
public void visitClassContext(ClassContext classContext) {
List<Method> endpoints = findEndpoints(classContext);
for (Method m : endpoint) {
checkCanAccessCalled(classContext, m);
}
Spring endpoint-? Spring? , .
REQUEST_MAPPING_ANNOTATION_TYPES = Arrays.asList(
"Lorg/springframework/web/bind/annotation/GetMapping;",
"Lorg/springframework/web/bind/annotation/PostMapping;",
private List<Method> findEndpoints(JavaClass javaClass) {
for (Method m : javaClass.getMethods()) {
for (AnnotationEntry ae : m.getAnnotationEntries())) {
if (REQUEST_MAPPING_ANNOTATION_TYPES
.contains(ae.getAnnotationType())) {
endpoints.add(m);
}
}
}
, Spring ( , ). , , . , .
. ? control flow graph, .
private void checkCanAccessCalled(ClassContext classContext, Method m) {
CFG cfg = classContext.getCFG(m);
for (Iterator<Location> i = cfg.locationIterator(); i.hasNext(); ) {
Instruction inst = i.next().getHandle().getInstruction();
if (inst instanceof INVOKESPECIAL) {
if (CAN_ACCESS_METHOD_NAME.equals(invoke.getMethodName(cpg)) &&
className.equals(invoke.getClassName(cpgΒ» {
found = true;
}
}
}
CFG endpoint- . , .
if (!found) {
bugReporter.reportBug(
new BugInstance(this, "IDOR", Priorities.NORMAL_PRIORITY)
.addClass(javaClass)
.addMethod(javaClass, method));
}
endpoint, , .
Find Security Bugs , , .
, . , .
?
, , , - .
, :
:
public abstract class BaseController {
protected boolean canAccess() {
return false;
}
}
public class Controller extends BaseController {
@GetMapping("foo")
public String foo() {
canAccess()
}
:
public class Controller {
private boolean canAccess() {
}
private boolean canAccessEx() {
canAccess()
}
@GetMapping("foo")
public String foo() {
canAccessEx()
}
}
:
public class Controller {
private boolean canAccess() {
}
private boolean canAccessEx() {
if (x) {
canAccess()
} else {
}
}
@GetMapping("foo")
public String foo() {
canAccessEx()
}
}
, , , :).
, , , .
, β β , , , .
Find Security Bugs , , Java.
: