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"]; } } }