我正在开发的应用程序使用 Apache POI 创建 Excel 导出。通过安全审核,我们注意到,如果用户不够小心,包含恶意值的单元格可能会生成任意进程。
要重现,请运行以下命令:
import java.io.FileOutputStream;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
public class BadWorkbookCreator {
public static void main(String[] args) throws Exception {
try(
Workbook wb = new HSSFWorkbook();
FileOutputStream fos = new FileOutputStream("C:/workbook-bad.xls")
) {
Sheet sheet = wb.createSheet("Sheet");
Row row = sheet.createRow(0);
row.createCell(0).setCellValue("Aaaaaaaaaa");
row.createCell(1).setCellValue("-2+3 +cmd|'/C calc'!G20");
wb.write(fos);
}
}
}
然后打开生成的文件:
然后按照以下步骤操作:
- 点击 (A) 选择包含恶意内容的单元格
- 单击 (B),使光标位于公式编辑器中
- 按回车键
- 系统将询问您是否允许 Excel 运行外部应用程序;如果您回答是,则启动 Calc(或任何恶意代码)
有人可能会说用户有责任让 Excel 运行任意的东西,并且用户被警告过。但是,Excel 是从受信任的来源下载的,有人可能会落入陷阱。
使用 Excel,您可以在公式编辑器中的文本前面放置一个单引号以将其转义。以编程方式在单元格内容中放置单引号(例如下面的代码)使单引号可见!
String cellValue = cell.getStringCellValue();
if( cellValue != null && "=-+@".indexOf(cellValue.charAt(0)) >= 0 ) {
cell.setCellValue("'" + cellValue);
}
问题:有没有办法让公式编辑器中的值保持转义,但在单元格中显示正确的值,没有前导单引号?
最佳答案
感谢Axel Richter here的辛勤调查和 Nikos Paraskevopoulos here ....
从 Apache POI 3.16 beta 1 开始(或者对于那些生活危险的人,20161105 之后的任何夜间构建),CellStyle 上有方便的方法对于 getQuotePrefixed和 setQuotePrefixed(boolean)
您的代码可能会变成:
// Do this once for the workbook
CellStyle safeFormulaStyle = workbook.createCellStyle();
safeFormulaStyle.setQuotePrefixed(true);
// Per cell
String cellValue = cell.getStringCellValue();
if( cellValue != null && "=-+@".indexOf(cellValue.charAt(0)) >= 0 ) {
cell.setCellStyle(safeFormulaStyle);
}
关于java - 避免公式注入(inject),保留单元格值(HSSF/*.xls 中的引号前缀),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40398766/