Test de sécurité statique avec des outils open source


, . ? , — . .


? , ? , ? — , .


Java, -, SonarQube Find Security Bugs, .


Heisenbug: — , — .



:




, OWASP ZAP Accunetix.
, :


  • , : , ;
  • , ;
  • , , API .

, .


?


  • : , , , ;
  • ( - , );
  • , .

.


, .



( ) . — 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.


:


Source: https://habr.com/ru/post/undefined/


All Articles