1.Direct SQL
通过Connection和Statement类执行SQL语句,会有遭受SQL注入攻击的危险.用来封装该功能的核心类SysSQLBuilder 也有同样的危险.记住Record-Level和Filed-Level的安全机制,不会在Statement上强制执行.如下语句就有SQL注入危险.
void MyFunction str _value)
{
DictTable dictTable = new DictTable(tableNum(custTable));
Connection connection = new Connection();
Statement statement = connection.createStatement();
str sql = strfmt("SELECT * FROM %1 WHERE %2 == %3",
dictTable.name(DbBackend::Sql),
fieldStr(Custtable, accountNum),
_value);
;
statement.executeUpdate(sql);
}
应对:{
DictTable dictTable = new DictTable(tableNum(custTable));
Connection connection = new Connection();
Statement statement = connection.createStatement();
str sql = strfmt("SELECT * FROM %1 WHERE %2 == %3",
dictTable.name(DbBackend::Sql),
fieldStr(Custtable, accountNum),
_value);
;
statement.executeUpdate(sql);
}
A.使用相对安全的方式执行SQL语句:用Query类,View或者X++语句.
B.真正的解决之道是采用参数化查询(这个在Axapta怎么实现还真没找到办法).
C.不要在X++ select语句中使用forceLiterals 保留字
D.不要执行Query.literals(true).
E.避免接受用户可以直接控制的输入.
F.确保没有向用户暴露未经过显示安全验证的数据.
BP
在调用如下函数的时候,如果传入的参数既不是text常量也不是宏的时候将会有BP错误报出.
Statement.executeQuery(parameter)
Statement.executeUpdate(parameter)
2.运行时编译和执行X++代码.
如下API允许执行包含X++语句的字符串变量.
RunBuf
EvalBuf
XppCompiler
如果入侵者可以控制这些API的输入,整个系统的安全性将受到威胁.利用代码注入攻击,攻击者可以拥有client,server和database server的控制权.
确保输入参数不包含未经确认的数据.
应对:
1.要求开发者的权限.
在用户可以输入X++代码的控件和数据类型上进行开发者权限验证.设置securitykey的值属性为SysDevelopment
2.重构代码,去掉需要在运行期编译的代码
比如如下代码:
buf = @'
void go(%1 _var)
{
;
_var.%2();
}
';
buf = strfmt(buf, classId2Name(classidget(this)), methodName);
if (compiler.compile(buf))
{
runbuf(buf, this);
}
可以用void go(%1 _var)
{
;
_var.%2();
}
';
buf = strfmt(buf, classId2Name(classidget(this)), methodName);
if (compiler.compile(buf))
{
runbuf(buf, this);
}
SysDictClass::invokeObjectMethod(this, methodName);
代替.BP
当调用如下方法时会出现BP错误
Runbuf(parameter)
Evalbuf(parameter)
XppCompiler.execute()
XppCompiler.executeEx()
后面的几个就不再Mark了.