on 2017 Feb 18 7:15 AM
Hello Expert Team,
While decoding the crystal report's HTTP network request for security audit, we have come across a very serious threat and loopholes in crystal reports which we see as very dangerous if not addressed as early as possible.
This post is continuation to reproduce steps for the question: Security Threat / Breach in Crystal Reports
Development Environment:
Symptoms:
It is required that if you are developing a sensitive data app, you may wants to keep your Database structure & Business Logic secured from end user.
Crystal Report gives option to specify allowed format to be exported, and hence many Application Developer will prefer to not to let export format like Crystal Reports & XML which contains the DB Structure & Business Logic. While there is other exploit available in Crystal Report allowing Crystal Report Formats to be download puts system at more risk.
Crystal Report should not allow to export format other than the one specified in Allowed Format.
Steps to reproduce:
Experts, Please at least put your comments if you able to reproduce and see this as a threat.
Temporary Solution: While we wait for this bugs to be addressed by Crystal Report Experts team, you can restrict the export request base on Query String Parameters at server side manually.
For more threat and exploits in Crystal Report see the question here: Security Threat / Breach in Crystal Reports
Code:
Web.Config:
===========
<?xml version="1.0"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<appSettings>
<add key="CrystalImageCleaner-AutoStart" value="true"/>
<add key="CrystalImageCleaner-Sleep" value="60000"/>
<add key="CrystalImageCleaner-Age" value="120000"/>
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.6.1">
<assemblies>
<add assembly="CrystalDecisions.CrystalReports.Engine, Version=13.0.2000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304"/>
<add assembly="CrystalDecisions.Shared, Version=13.0.2000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304"/>
<add assembly="CrystalDecisions.Web, Version=13.0.2000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304"/>
<add assembly="CrystalDecisions.ReportSource, Version=13.0.2000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304"/>
</assemblies>
</compilation>
<sessionState mode="InProc" timeout="20"/>
</system.web>
</configuration>
ReportViewer.aspx
===================
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="ReportViewer.aspx.cs" Inherits="ReportViewer" %>
<%@ Register TagPrefix="CR" Namespace="CrystalDecisions.Web" Assembly="CrystalDecisions.Web" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<CR:CrystalReportViewer ID="ExternalCrystalReportViewer" runat="server"
Height="1039px"
Width="901px"
ReuseParameterValuesOnRefresh="False"
HasRefreshButton="True"
HasCrystalLogo="False"
HasToggleParameterPanelButton="True"
ToolPanelView="ParameterPanel"
EnableDatabaseLogonPrompt="False"/>
</div>
</form>
</body>
</html>
ReportViewer.aspx.cs
====================
using System;
using CrystalDecisions.Shared;
using CrystalDecisions.CrystalReports.Engine;
using System.IO;
public partial class ReportViewer : System.Web.UI.Page
{
private ConnectionInfo getconnetionInfo()
{
ConnectionInfo crConnectionInfo = new ConnectionInfo();
crConnectionInfo.UserID = "user2";
crConnectionInfo.Password = "user2";
crConnectionInfo.ServerName = "(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED)(SERVICE_NAME = XE)))";
return crConnectionInfo;
}
protected void Page_Init(object sender, EventArgs e)
{
}
protected void Page_Load(object sender, EventArgs e)
{
if (Session["rd"] == null)
{
try
{
ConnectionInfo crConnectionInfo = getconnetionInfo();
string reportUrl = System.Web.HttpContext.Current.Server.MapPath("~/App_Data/" + "report-1.rpt");
ReportDocument rd = new ReportDocument();
rd.FileName = reportUrl;
rd.Load(reportUrl, OpenReportMethod.OpenReportByTempCopy);
rd.SetDatabaseLogon(crConnectionInfo.UserID, crConnectionInfo.Password);
ExternalCrystalReportViewer.AllowedExportFormats = (int)(ViewerExportFormats.ExcelRecordFormat |
ViewerExportFormats.XLSXFormat |
ViewerExportFormats.WordFormat |
ViewerExportFormats.PdfFormat);
ExternalCrystalReportViewer.ReportSource = rd;
Session["rd"] = rd;
}
catch (Exception ex)
{
//Manage Exceptions
}
}
else
{
ExternalCrystalReportViewer.ReportSource = (ReportDocument)Session["rd"];
}
}
}
Request clarification before answering.
Hi Vishal,
I sent the link to DEV and they are going to look into this issue.
Incident 125375 / 2017 / Security Threat / Exploit in Crystal Reports, Restricted export format can be exported
This issue has been fixed and validated with some internal builds. The correction is currently planned to be available in the official version of:
- SAP BusinessObjects BI Platform .NET SDK Redistributable 4.1 SP11
- SAP BusinessObjects BI Platform .NET SDK Redistributable 4.2 SP5
- SAP Crystal Reports, version for Microsoft Visual Studio SP21
Thanks again
Don
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Vishal,
There is no security leak in the Viewer, all you need to do is select which Export Types you want your users to see as an option.
Add this to the Viewer code:
// set up the format export types:
int myFOpts = (int)(
//CrystalDecisions.Shared.ViewerExportFormats.RptFormat |
CrystalDecisions.Shared.ViewerExportFormats.PdfFormat |
//CrystalDecisions.Shared.ViewerExportFormats.RptrFormat |
CrystalDecisions.Shared.ViewerExportFormats.XLSXFormat |
CrystalDecisions.Shared.ViewerExportFormats.CsvFormat |
CrystalDecisions.Shared.ViewerExportFormats.EditableRtfFormat |
CrystalDecisions.Shared.ViewerExportFormats.ExcelRecordFormat |
CrystalDecisions.Shared.ViewerExportFormats.RtfFormat |
CrystalDecisions.Shared.ViewerExportFormats.WordFormat |
CrystalDecisions.Shared.ViewerExportFormats.XmlFormat |
CrystalDecisions.Shared.ViewerExportFormats.ExcelFormat |
CrystalDecisions.Shared.ViewerExportFormats.ExcelRecordFormat);
//CrystalDecisions.Shared.ViewerExportFormats.NoFormat); // no exports allowed
//int myFOpts = (int)(CrystalDecisions.Shared.ViewerExportFormats.AllFormats);
crystalReportViewer1.AllowedExportFormats = myFOpts;
Don
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thank you so much Mr.Don Williams for your valuable input, I was really waiting for your response.
As you suggested to set the format in Viewer, We have already set it as below:
ExternalCrystalReportViewer.AllowedExportFormats = (int)(ViewerExportFormats.ExcelRecordFormat |
ViewerExportFormats.XLSXFormat |
ViewerExportFormats.WordFormat |
ViewerExportFormats.PdfFormat);
And as per the format set, Report will display only this four format for export, but hacker can manipulate this input at client side and set any other format they wants to download, and when it is requested at server side CR will not recheck before export that what formats were set to allowed.
As mentioned in my question, request you to please try this once in your Mozilla Browser with Data Tamper Tool:
Steps to reproduce:
Please let me know if you need any input to reproduce this incidence.
Once again thank you very much for your valuable input, and awaiting your comment.
User | Count |
---|---|
59 | |
10 | |
8 | |
8 | |
7 | |
6 | |
6 | |
5 | |
5 | |
4 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.