Artemis Documentation

Installation

获取软件最新版本

用户可从https://github.com/zsdlove/Artemis-release/releases/ 下载最新的Artemis扫描器。

配置清单

Artemis 代码安全扫描器包含主体引擎Artemis.jar和两个配置文件Checker.xml和build.properties。其中,Checker.xml中包含扫描器内置规则以及用户自定义规则;build.properties包含编译配置,以及其他的一些扫描器必要的运行时配置。

环境依赖

  • Artemis依赖jdk11之后的所有版本,请确保运行环境中的jdk大于jdk11。
  • 编译捕获所需的jdk可通过命令行参数或配置文件另外配置,如果没有配置,则默认继承Artemis运行环境所以依赖的jdk版本。

Quickstart

基本原理说明

Artemis代码分析主要分两步,第一步是进行代码编译捕获,第二步是进行代码扫描分析。其中第一步需要将代码转换为中间语义文件*.art,第二步则使用指定规则对捕获的语义文件进行分析。

基本使用说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
pony@ponydeMBP 1.0.0 % java -jar Artemis.jar -h
Usage: SAST [-hV] [-bc=<build_cmd>] [-d=<dbpath>] [-j=<java_home>]
[-mr=<mr_enable>] [-od=<out_dbpath>] [-p=<path>] [-r=<rulePath>]
[-t=<mr_target_path>]
static code analysis.
-bc, --build-command=<build_cmd>
指定编译命令.
-d, --database=<dbpath> 指定加载的数据库路径.
-h, --help Show this help message and exit.
-j, --java-home=<java_home>
指定java_home路径.
-mr, --mr-enable=<mr_enable>
是否启用mr扫描.
-od, --output-database=<out_dbpath>
指定输出的编译数据库路径.
-p, --path=<path> 指定源码路径.
-r, --rule=<rulePath> 指定规则路径.
-t, --mr-target-path=<mr_target_path>
指定target数据库路径.
-V, --version Print version information and exit.

靶场示例

https://github.com/JoyChou93/java-sec-code.git
这个靶场做得还是比较用心的,一直以来测试都是用的这个靶场。

使用步骤

java-sec-code编译依赖jdk1.8,所以我们需要在build.properties配置文件中指定java8环境配置指定如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
java_home = /Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home
report_output=report.json
build_cmd= mvn clean package -X -DskipTests=true
out_dir=workspace
model_name=deepseek-ai/DeepSeek-V2.5
max_token=512
temperature=0.7
top_p=0.7
top_k=50
frequency_penalty=0.5
n=1
model_api=https://api.siliconflow.cn/v1/chat/completions
licenseData=Licensed to: pOny, Expires: 2025-4-31
publicKey=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxidJDQRCW3aITgFN5vVF4tuaMu85igETA+cR4Pg//+aJfpjockyvAmdEiz0fKOlm+HyXDDGSzuzVgtf4MFEEI+I/UeON2BstGqE0kQd4KLs7+MbzmDttVzixVICl4i57LBHbh3Ef7ZwALknvhURH5XaZpqlIobSiiphf12uoFALK7sMfQDq0KFlkZnmvydDoF8leqqoh5wVwaA/0kKjrWH0pUu+x/l7EVxyqCsEXKdd2WYOE6zxfDxQkbBGYCjZ8W6AUQygy0T9/qXZRy4g16dN99TbnrcKTts8p1fMTOZgj9lEHtKaaDs8HvQa0CkHF1iCV6WI/5gWF9K9S4ZafwQIDAQAB
signature=T1kqV8LWUhLd2rTtyROpgYx30tGFQDnoQCicQUXvvwWqf9uyD/dvx6ivVZua2LZHbxUU85WtryRA25AGeMvXaG9KVpWYeUwnUbG4lx/w3D0eWFcoloTmRdeYgYl9q9OxhR+n7CH5CoveghZU05ZGqIlLxeglrbnlCNB8n8J1NHVxMyvpTBl9vYxfx39WyvSTIytwXZb4vnwWXQVbUwdVmuHQuKHfpPBf0W1VnvQ/p3WDgRyAbL0v2e2eITMd7SGSU/9VC23kZjCy8p/cSNZ/VivEth6BFW1k52Gis4alNR9OZUbMsgrYcpo6ORCL+gOAU1RQiO+spffPhBipa9u4gg==

编译命令指定为mvn clean package -X -DskipTests=true,其他默认即可。下面指定以下命令开启编译

编译

执行以下命令进行编译捕获

1
java -jar Artemis.jar -p test/java-sec-code-master
编译执行实战
如果你实现编译过,本地已经有依赖包缓存了,那这个捕获过程大概耗时10秒,如果没有编译过,那这个过程可能会耗时稍稍多一些。

分析

下面我们开始进行漏洞分析,我们直接执行以下命令即可:

1
java -jar Artemis.jar -d workspace

其中,workspace是我们指定的数据库保存的目录。

分析执行实战
可以看到这个过程大概耗时6秒,对于一些诸如java-sec-code-master这样小型的项目,Artemis的分析速度极快,如果再配合上mr扫描,那速度将会相当令人欣喜。

merge request scan

执行以下命令进行merge request scan,其中-t指定前一个版本的数据库,-mr指定是否启用mr扫描,-od指定新的数据库的地址

1
java -jar Artemis.jar -p test/java-sec-code-master -t workspace -mr true -od workspace2
mr扫描实战

Database

节点描述

节点 说明 如何获取
YieldStmt yield语句 示例:db.nodes.where(_.getClass.getSimpleName==”YieldStmt”)
MethodCallReferenceExpr 方法引用语句 类似第一个示例
ArrayAccessExpr 数组访问表达式 类似第一个示例
ConditionExpr 条件表达式 类似第一个示例
AssignExpr 赋值表达式 类似第一个示例
BreakStmt break语句 类似第一个示例
BooleanLiteralExpr 布尔表达式 类似第一个示例
DoStmt do语句 类似第一个示例
SwitchExpr switch语句 类似第一个示例
LambdaExpr lambda表达式 类似第一个示例
AnnotationStmt 注解语句 类似第一个示例
NullLiteralExpr 空值表达式 类似第一个示例
ReturnStmt 返回语句 类似第一个示例
ThrowStmt throw语句 类似第一个示例
NameExpr 名字表达式 类似第一个示例
BlockStmt 基本块 类似第一个示例
LongLiteralExpr 长整型表达式 类似第一个示例
CastExpr 强制转换表达式 类似第一个示例
TypeDecl 类型声明 类似第一个示例
FieldAccessExpr 字段访问表达式 类似第一个示例
MethodDecl 函数声明 类似第一个示例
ForStmt for语句 类似第一个示例
ForeachStmt foreach语句 类似第一个示例
WhileStmt while语句 类似第一个示例
IntegerLiteralExpr 整型值表达式 类似第一个示例
VariableDeclarator 变量声明者 类似第一个示例
CatchClause catchclause声明 类似第一个示例
IfStmt if语句 类似第一个示例
ObjectCreationExpr 对象创建 类似第一个示例
ParameterStmt 参数语句 类似第一个示例
ExprStmt 表达式语句 类似第一个示例
SwitchStmt switch语句 类似第一个示例
BinaryExpr binary表达式 类似第一个示例
ArrayInitializerExpr 数组初始化表达式 类似第一个示例
DoubleLiteralExpr Double值表达式 类似第一个示例
CallExpr 函数调用表达式 类似第一个示例
TryStmt try语句 类似第一个示例
FinallyStmt finally语句 类似第一个示例
VariableDecExpr 变量声明表达式 类似第一个示例
TypeExpr 类型表达式 类似第一个示例
ArrayCreateExpr 数组创建表达式 类似第一个示例
SwitchEntry switch入口 类似第一个示例
StringLiteralExpr 字符串值表达式 类似第一个示例
XMLNode xml节点 类似第一个示例

节点基本属性描述

每一个节点的最终父类都是AST,其中,AST的基本数据结构如下

属性 类型 说明
id int 节点编号,具有唯一性
code sting 节点代码
start_line int 节点起始行
end_line int 节点结束行
parent int 父节点
filePath string 文件路径
method_id int 节点所在函数

Basic Usages

关键词使用说明

关键字 说明 示例
db 数据库,所有的数据都从这来
call 函数调用 db.call
method 函数声明 db.method
types 类型声明 db.types
xml xml文件信息 db.xml
where 条件判断 db.call.where(_.name==”niceshot”)
whereNot 条件判断 db.call.whereNot(_.name==”nicejob”)
filter 条件过滤 db.call.filter(_.name==”nicejob”)
limit 枚举限制,限制获取的节点数量 db.call.limit(10)
methodDeclaration 获取函数调用对应的函数声明信息 callExpr.methodDeclaration
hasPathTo 污点路径追踪 sink.hasPathTo(source)

Rule Develop

以下是一个sql注入检测规则的示例,阁下可仿造此规则编写其他漏洞检测规则,编写的规则放置在Checker.xml的customize-rules节点下即可。规则编号你可以自定义,不过,如果自定义编号的话,你需要补充这个编号对应的描述信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
val sources:List[ParameterStmt]= db.method
.where(_.annotation.nonEmpty)
.where {
it => {
it.annotation.count(_.code.contains("RequestMapping"))>0
|| it.annotation.count(_.code.contains("GetMapping"))>0
|| it.annotation.count(_.code.contains("ResponseBody"))>0
}
}
.filter(_.params.nonEmpty).map(_.params.head)
val sink:List[Expr]=db.call.where{
it=>{
it.fullName=="java.sql.Statement.executeQuery"
|| it.fullName=="java.sql.Statement.addBatch"
|| it.fullName=="java.sql.Statement.execute"
|| it.fullName=="java.sql.Statement.executeLargeUpdate"
|| it.fullName=="java.sql.Statement.executeUpdate"
|| it.fullName=="java.sql.Statement.executeBatch"
}
}.filter(_.arguments.nonEmpty).map(_.arguments.head)
val paths=sink.hashPathTo(sources)
paths.show //打印路径
paths.num //统计路径数量

注意事项:

  • 注意规则每一行规则代码都需要加上<br>进行换行,否则后端规则编译器会编译异常。
  • 规则需要使用cdata节点进行包裹,以避免规则中的关键词对xml的解析产生影响。

online query

说明

从1.1.0版本起,artemis支持在线query。可通过以下命令启动一个query服务器:

1
java -jar Artemis.jar -d [path/to/database] -sp 8089

(注:sp指定端口号)

接口请求示例

1
http://localhost:8089/query?data=db.method.last.fullname

其中,data参数后面跟我们query的语句

演示

启动服务器

启动服务器演示

在线query

在线query演示