SQL-injections (http://en.wikipedia.org/wiki/SQL_injection) represent a wonderful way to get external access to your database. This kind of injections can be left in the code by developers both because of lack of experience and on purpose. Is it possible to find them quickly and be sure your product is safe? Our developer Alexander shares his experience of automated search for such injections.
Once I had a task to develop a plugin prototype for IntelliJ IDEA within a short time. The plugin purpose was to analyze the code to search for SQL-injections according to a certain rule described in the given XML file.
To start plugin development for IDEA you just need to download the community version and create there a project for plugin development.
As a next step I had to realize the object representation of the rule described in XML. The main point of the rule is a listing of classes and their methods, their calling is SQL-injection. Nothing to explain here, everything is simple and has nothing to deal with specifics of plugin development.
After I had realized the object representation of the rule, I started exploring OpenAPI IDEA SDK with a view to code analysis possibilities. First of all I visited their documentation site: https://confluence.jetbrains.com/display/IDEADEV/PluginDevelopment. If I tell you the given information there was enough, I’ll probably tell you a lie…
It was clear that for code analysis I have to work with psi-elements and I made some investigations in this direction. I reviewed the interface of psi-element and its other descendants and it showed that for faster orientation it’s better to output all the structure from a Java file into the console and see what happens next. I call it exploratory attack. We need a UI action that can be called in the chosen project file in IDE. While activating the action we get AnActionEvent and then we take the element following way:
PsiElement element = event.getData(LangDataKeys.PSI_ELEMENT);
in case we called the action on the chosen element in the project tree, or:
PsiElement element = event.getData(LangDataKeys.PSI_FILE);
in case we called the action from the editor of the open file.
Back to psi-elements. Psi-element has a parent psi-element and subsidiary psi-elements. So we can get deeper recursively and output all the elements with indentations into the console. In this way I found an important.
PsiMethodCallExpression element that includes necessary information, meaning which exactly method and where do we call it from. A bit more patience and I found a way to extract this information:
PsiReferenceExpression methodExpression = expression.getMethodExpression(); PsiReference reference = methodExpression.getReference(); PsiElement result = reference.resolve(); PsiClass methodClass = (PsiClass) result.getContext(); String methodClassName = methodClass.getQualifiedName(); PsiIdentifier methodIndentifier = methodExpression.getLastChild(); String methodName = methodIndentifier.getText();
In this way we get the whole class name this method belongs to and the name of called method. That’s enough to identify whether it is a potential SQL-injection. Besides we have the psi-element of method calling, so we know what place in the code it is.
The next task – marker saving.
I created a project level component and put the marker container in it to save markers. To make the component container persistable, the component has to realize the interface ProjectComponentState<Container type>
And the fields in the container have to be marked with relevant annotations, e.g.
Displaying of markers and annotations was a sweaty piece of work. Everything was great, the way for realization of markers and annotations is easy, because you only have to realize your relevant providers and register them in the plugin. Some difficulties appeared, when I had to refresh them in the open editor. I couldn’t find the information about that on open access so quickly, so I had to use exploratory attack again. Debugging marker display mechanism I found out that it is possible to refresh SlowLineMarkersPass and it will refresh markers for the specified document. Anyway the issue with annotations highlighting the code remained. The same way I found the GeneralHighlightingPass. Class that dealt with annotations etc refreshing, but there was one hitch: to create and launch it you have to feed it with a plenty of different odd arguments and it already took the wind out of sails. Debugging didn’t help, so I had to ask for help my good old friend Google. After several cups of coffee I found an article where it was suggested to use this way
DaemonCodeAnalyzer codeAnalyzer = DaemonCodeAnalyzer.getInstance(project); codeAnalyzer.restart();
Bingo! This approach solved my problem both with markers and with annotations. Warning! If you install developed plugin into the IDE where it is developed and then you launch debugging of the same plugin, IDE sees the code exactly from the installed plugin. As a result IDE doesn’t pick up code changes and debug falls off. Take this into account and do not install your plugin into the operational IDE, before you finish development process. Eventually I got this plugin
- First of all this task doesn’t take much time. It took no more that 5 days for the whole plugin.
- We got more flexible while completing our tasks for code analysis. It isn’t always fully accessible in ready frameworks for static code analysis.
- The opportunity to use PSI elements instead of AST simplified our work.
As there is not so much information on the Internet on this topic, I hope this article might be helpful for other developers.