👋 by Thanat Sirithawornsant, Senior Security Engineer, Citrix 🥳
- CodeQL is advertised as a variant analysis tool.
- It is a query language which has its own syntax.
- It can be used to find a piece of code in a code base, not necessarily bugs or defects.
- It can be used as part of you CI/CD pipelines to detect bad smells.
- Free for research and open source
https://github.com/ScaleSec/vulnado
- written in Java based on spring framework
- MVC model
- with some writeup
CodeQL offers 2 ways to use their tool
- CodeQL CLI for engineers
- LGTM.com -> CodeQL Platform
Instructions: https://help.semmle.com/codeql/codeql-cli/procedures/get-started.html
- can compile a database for CodeQL locally
- allowing engineers to do experiments and research locally
- can easily run batches on queries with ease
- can be used straight away on their platform for open source projects
- fancy UI
- a bit slower than querying locally, probably because of shared environment or some sort of restrictions
- once the project has been imported, the database can be exported
Issue | Type | Location | Line Number |
---|---|---|---|
Query built without neutralizing special characters | error | /src/main/java/com/scalesec/vulnado/User.java | 49, 40, 49, 44 |
Use of a broken or risky cryptographic algorithm | warning | /src/main/java/com/scalesec/vulnado/Postgres.java | 67, 32, 67, 63 |
Executing a command with a relative path | warning | /src/main/java/com/scalesec/vulnado/Cowsay.java | 11, 28, 11, 33 |
- let's observe how the application declare endpoints
- it should be within controller files
- what are the characteristics or the definitions?
- find the patterns and confirm your results
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.boot.autoconfigure.*;
import java.util.List;
import java.io.Serializable
@RestController
@EnableAutoConfiguration
public class CommentsController {
@Value("${app.secret}")
private String secret;
@CrossOrigin(origins = "*")
@RequestMapping(value = "/comments", method = RequestMethod.GET, produces = "application/json")
List<Comment> comments(@RequestHeader(value="x-auth-token") String token) {
User.assertAuth(secret, token);
return Comment.fetch_all();
}
[...]
}
@CrossOrigin(origins = "*")
@RequestMapping(value = "/comments", method = RequestMethod.GET, produces = "application/json")
List<Comment> comments(@RequestHeader(value="x-auth-token") String token) {
User.assertAuth(secret, token);
return Comment.fetch_all();
}
@CrossOrigin(origins = "*")
@RequestMapping(value = "/comments", method = RequestMethod.POST, produces = "application/json", consumes = "application/json")
Comment createComment(@RequestHeader(value="x-auth-token") String token, @RequestBody CommentRequest input) {
return Comment.create(input.username, input.body);
}
@CrossOrigin(origins = "*")
@RequestMapping(value = "/comments", method = RequestMethod.POST, produces = "application/json", consumes = "application/json")
Comment createComment(@RequestHeader(value="x-auth-token") String token, @RequestBody CommentRequest input) {
return Comment.create(input.username, input.body);
}
@CrossOrigin(origins = "*")
@RequestMapping(value = "/comments/{id}", method = RequestMethod.DELETE, produces = "application/json")
Boolean deleteComment(@RequestHeader(value="x-auth-token") String token, @PathVariable("id") String id) {
return Comment.delete(id);
}
- list all the endpoints
- including public ones, with allow list even
- list all the user input
- including URL query, HTTP body, URL path
https://help.semmle.com/QL/learn-ql/
https://help.semmle.com/QL/ql-handbook/index.html
https://help.semmle.com/wiki/display/JAVA/Java+queries https://github.com/github/codeql/tree/master/java/ql/src/Security/CWE