Browse Source

Patch security #17

master
Daniel Quathamer 2 weeks ago
parent
commit
d6c8f996cc
  1. 2
      superx/WEB-INF/conf/edustore/db/install/conf/builddatum.txt
  2. 65
      superx/WEB-INF/conf/edustore/db/install/prozeduren/proc_get_dbform_right_pg.sql
  3. 67
      superx/WEB-INF/patch/xml/patch_2026-10-07.xml
  4. 14
      superx/edit/kern/show_html_content.jsp
  5. 30
      superx/edit/kern/sx_repository_list.jsp
  6. 12
      superx/xml/nd_templates.xsl

2
superx/WEB-INF/conf/edustore/db/install/conf/builddatum.txt

@ -1 +1 @@ @@ -1 +1 @@
03.10.2026
05.10.2026

65
superx/WEB-INF/conf/edustore/db/install/prozeduren/proc_get_dbform_right_pg.sql

@ -14,55 +14,28 @@ if p_isadmin=1 @@ -14,55 +14,28 @@ if p_isadmin=1
p_recht:=1;
else
--Bedingung 2:
-- kein Admin: Besteht Recht über Gruppe zu Sachgebiet "Bearbeitung*" oder "Administration*" ?
if 0 < (SELECT count(*) from user_group_bez U,group_sachgeb_bez B, sachgebiete S
where S.tid=B.sachgebiete_id
and U.groupinfo_id=B.groupinfo_id
and U.userinfo_id=p_userid
and (S.name like ''Bearbeitung%'' or S.name like ''Administration%'')
)
-- kein Admin: Besteht Recht über Gruppe zu Sachgebiet "Administration*" ?
if exists (SELECT sg.* from sachgebiete sg
JOIN sachgeb_dbform_bez sdb ON sg.tid = sdb.sachgebiete_id
JOIN db_forms df ON df.tid = dbform_id
JOIN user_sachgeb_bez usb ON sg.tid = usb.sachgebiete_id
WHERE trim(df.name) = trim(p_form) AND usb.userinfo_id =p_userid
and (sg.name like ''Bearbeitung%'' or sg.name like ''Administration%'')
union SELECT sg.*
FROM sachgebiete sg
JOIN sachgeb_dbform_bez sdb ON sg.tid = sdb.sachgebiete_id
JOIN db_forms df ON df.tid = dbform_id
JOIN group_sachgeb_bez gsb ON sg.tid = gsb.sachgebiete_id
JOIN user_group_bez ugb on ugb.groupinfo_id=gsb.groupinfo_id
WHERE trim(df.name) = trim(p_form)
AND ugb.userinfo_id =p_userid
and (sg.name like ''Bearbeitung%'' or sg.name like ''Administration%'')
)
then
p_recht:=1;
else
--Bedingung 3:
--Besteht Recht über User zu zu Sachgebiet "Bearbeitung*" oder "Administration*" ?
if 0 < (SELECT count(*) from user_sachgeb_bez B, sachgebiete S
where S.tid=B.sachgebiete_id
and B.userinfo_id=p_userid
and (S.name like ''Bearbeitung%'' or S.name like ''Administration%'')
)
then
p_recht:=1;
else
--Bedingung 4:
--kein Admin, keine Bearbeiter: Besteht Leserecht über Gruppe zu Sachgebiet des DBFORMS?
if 0 < (SELECT count(*) from sachgeb_dbform_bez B, db_Forms D,user_group_bez U,group_sachgeb_bez G
where D.tid=B.dbform_id
and trim(D.name) = trim(p_form)
and B.sachgebiete_id=G.sachgebiete_id
and U.groupinfo_id=G.groupinfo_id
and U.userinfo_id=p_userid)
then
p_recht:=2;
else
--Bedingung 5:
--Besteht Recht über User zu zu Sachgebiet des DBFORMS ?
if 0 < (SELECT count(*) from sachgeb_dbform_bez B, db_Forms D,user_sachgeb_bez U
where D.tid=B.dbform_id
and trim(D.name) = trim(p_form)
and B.sachgebiete_id=U.sachgebiete_id
and U.userinfo_id=p_userid)
then
p_recht:=2;
end if; --Ende Bedingung 5
end if; --Ende Bedingung 4
end if; --Ende Bedingung 3
end if; --Ende Bedingung 2
end if; --Ende Bedingung 1
end if;
end if;
return p_recht;

67
superx/WEB-INF/patch/xml/patch_2026-10-07.xml

@ -0,0 +1,67 @@ @@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<patch patch_id="2026-10-07">
<systeme>
<system name="his1" codierung="utf8"/>
<system name="superx" codierung="utf8"/>
<system name="superx" codierung="iso"/>
</systeme>
<module name="kern" systeminfo_id="xxx" inst_from="xx">
<patch-description feature_id="380056">Sicherheitspatch Bearbeitungsrechte DBFORMS
<ol><li>
In SuperX konnten angemeldete Benutzer mit einem Sachgebietsrecht, dessen Bezeichnung mit „Bearbeitung“ oder „Administration“ begann, Berichtsmasken konfigurieren und dabei beliebige SQL-Statements auf der BI-Datenbank ausführen.
</li>
<li>Wenn ein angemeldeter BI-Administrator parallel eine nicht vertrauenswürdige Webseite aufruft, konnte diese SQL-Befehle auf der BI-Datenbank ausführen. (CSRF in Verbindung mit SQL-Injection).
</li>
</ol>
Der Patch behebt beide Schwachstellen:
<ol><li>
Bearbeitungsformulare lassen sich von Nicht-Admins nur öffnen, wenn sie explizite Rechte auf das jew. Administrations-Sachgebiet haben.
</li>
<li>Die Möglichkeit zur SQL-Injection wurde entfernt.
</li>
</ol>
</patch-description>
<patch-test>
<!-- Bisher nur sql erlaubt. Ergebnis muss 0 sein, um zu erlauben, dass der Patch eingespielt wird! -->
<nativeaction sql="select 0 from xdummy where (select count(*) from db_version where his_system='kern') > 0 " scriptfile="" database=""/>
</patch-test>
<patch-data>
<files>
<file path="WEB-INF/conf/edustore/db/install/prozeduren/proc_get_dbform_right_pg.sql"><patch-description feature_id="380056">Korrektur Rechteprüfung DBFORMS</patch-description></file>
<file path="edit/kern/show_html_content.jsp"><patch-description feature_id="380056">Anzeige Hochschul-Repository nur für Impressumg und Datenschutz-Seite</patch-description></file>
<file path="WEB-INF/conf/edustore/db/module/kenn/schluesseltabellen/kenn_stg_astat.unl"><patch-description>Neue Fächergruppen im Bereich Studierende</patch-description></file>
<file path="WEB-INF/conf/edustore/db/module/kenn/schluesseltabellen/trans_kenn_lfb_fg.sql"><patch-description>Neue Fächergruppen im Bereich Personal</patch-description></file>
</files>
<database name="superx">
<!-- TODO: hier können beliebige Elemente der normalen Modul-XML stehen-->
<masken>
</masken>
</database>
<upgrade>
<upgrade-step>
<action error="cont">
<nativeaction sql="" scriptfile="$SUPERX_DIR/db/install/prozeduren/proc_get_dbform_right_pg.sql" database="" />
<nativeaction sql="update sachgeb_dbform_bez set sachgebiete_id=122 where sachgebiete_id=121;" scriptfile="" database="" />
</action>
</upgrade-step>
</upgrade>
</patch-data>
</module>
</patch>

14
superx/edit/kern/show_html_content.jsp

@ -37,13 +37,9 @@ if(!entryOK) @@ -37,13 +37,9 @@ if(!entryOK)
if(defaultMandantenIDParam != null && !defaultMandantenIDParam.toString().equals("")) {
LinkMandantID.append("/"+defaultMandantenIDParam.toString());
}
//Impressum wird immer angezeigt, alles andere nur nach Login:
if (
IdOutput.equals("IMPRINT") ||
IdOutput.equals("PRIVACY") ||
( request.getSession()!=null&&request.getSession().getAttribute("sessiontype")!=null&&
request.getSession().getAttribute("sessiontype").equals("superx"))
) {
if (request.getSession()!=null&&request.getSession().getAttribute("sessiontype")!=null&&
request.getSession().getAttribute("sessiontype").equals("superx")) {
Object mandantobject=request.getSession().getAttribute("MandantenID");
Object userid=request.getSession().getAttribute("UserID");
@ -71,7 +67,7 @@ conmm = DbFormsConfigRegistry.instance().lookup().getConnection(mandantenid); @@ -71,7 +67,7 @@ conmm = DbFormsConfigRegistry.instance().lookup().getConnection(mandantenid);
PreparedStatement st_output;
ResultSet rs_output;
st_output=conmm.prepareStatement("select trim(content) from sx_repository where id=? and today() between gueltig_seit and gueltig_bis and aktiv=1");
st_output=conmm.prepareStatement("select trim(content) from sx_repository where id=? and id in ('PRIVACY','IMPRINT') and today() between gueltig_seit and gueltig_bis and aktiv=1");
st_output.setString(1,IdOutput);
rs_output = st_output.executeQuery();
String sb_output="";
@ -88,7 +84,7 @@ if(sb_output==null || sb_output.equals("")) @@ -88,7 +84,7 @@ if(sb_output==null || sb_output.equals(""))
//Titel holen:
PreparedStatement st_titel;
ResultSet rs_titel;
st_titel=conmm.prepareStatement("select trim(caption) from sx_repository where id=? and today() between gueltig_seit and gueltig_bis and aktiv=1");
st_titel=conmm.prepareStatement("select trim(caption) from sx_repository where id=? and id in ('PRIVACY','IMPRINT') and today() between gueltig_seit and gueltig_bis and aktiv=1");
st_titel.setString(1,IdOutput);
rs_titel = st_titel.executeQuery();
String sb_titel="";

30
superx/edit/kern/sx_repository_list.jsp

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
<%@ taglib uri="/WEB-INF/dbforms.tld" prefix="db" %>
<%@page pageEncoding="utf-8" contentType="text/html; charset=UTF-8" %>
<html>
<!--Automatically generated by module_scripts_create.x (SuperX) for Module kern-->
<!--Automatically generated by module_scripts_create.x (SuperX)-->
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
@ -49,10 +49,12 @@ if(mandantobject != null) @@ -49,10 +49,12 @@ if(mandantobject != null)
//der superx-Default-Mandant ist bei dbforms ein Leerstring
if(mandantenid.equals("default"))
mandantenid="";
String db_form_name="sx_repository_list";
String db_form_name="sx_repository";
String erlaubt="0";
%>
<%@ include file="/edit/check_authentication.inc" %>
<%
if(erlaubt.equals("0"))
{
@ -72,6 +74,7 @@ keyfieldsused=kf.toString(); @@ -72,6 +74,7 @@ keyfieldsused=kf.toString();
<p align="right">
<a target="_parent" href="http://www.superx-projekt.de"><img border="0" alt="Logo" src="../../images/logo.gif"></a>
<br><% if(!mandantenid.equals("default") && !mandantenid.equals(""))
out.println("<strong>Mandant: " + mandantenid +"</strong>");
%></p>
@ -87,16 +90,6 @@ if(sachgebiete_id != null && !sachgebiete_id.equals("null")){ @@ -87,16 +90,6 @@ if(sachgebiete_id != null && !sachgebiete_id.equals("null")){
filter +="sachgebiete_id="+sachgebiete_id;
}
%>
<%
String art = request.getParameter("art");
if(art != null && !art.equals("null")){
if (!filter.isEmpty()) {
filter += ",";
}
filter +=",art="+art;
}
%>
<db:dbform tableName="sx_repository" maxRows="*" autoUpdate="false" captionResource="true" multipart="false" followUp="/edit/kern/sx_repository_list.jsp" filter="<%= filter %>" orderBy="id"
dbConnectionName="<%= mandantenid %>" ><input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/><db:header>
<table class="dbform_tab" border="1" >
@ -106,11 +99,7 @@ dbConnectionName="<%= mandantenid %>" ><input type="hidden" name="${_csrf.parame @@ -106,11 +99,7 @@ dbConnectionName="<%= mandantenid %>" ><input type="hidden" name="${_csrf.parame
<db:message key="Tid"/></th><th align="left">
<db:message key="Variablenname"/></th><th align="left">
<db:message key="Beschriftung (kurz)"/></th><th align="left">
<db:message key="Art der Variable"/></th><th align="left">
<db:message key="Inhalt der Variable"/></th><th align="left">
<db:message key="Sachgebiet"/></th><th align="left">
<db:message key="Sortierschl&uuml;ssel 1"/></th><th align="left">
<db:message key="Aktiv (1,0)"/></th><th>Details</th>
<db:message key="Art der Variable"/></th><th>Details</th>
</tr>
</db:header>
<db:errors/>
@ -118,16 +107,11 @@ dbConnectionName="<%= mandantenid %>" ><input type="hidden" name="${_csrf.parame @@ -118,16 +107,11 @@ dbConnectionName="<%= mandantenid %>" ><input type="hidden" name="${_csrf.parame
<tr>
<td>
<input type="hidden" name="sachgebiete_id" value="<%= sachgebiete_id %>" />
<input type="hidden" name="art" value="<%= art %>" />
</td><td>
<db:label nullFieldValue="" styleClass="clsInputStyle" fieldName="tid"/></td><td align="left">
<db:textField nullFieldValue="" styleClass="clsInputStyle" maxlength="200" size="30" fieldName="id"/></td><td align="left">
<db:textField nullFieldValue="" styleClass="clsInputStyle" maxlength="200" size="30" fieldName="caption"/></td><td align="left">
<db:textField nullFieldValue="" styleClass="clsInputStyle" maxlength="200" size="30" fieldName="art"/></td><td style="max-width: 300px; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; line-height: 1.2em; max-height: 3.6em;"><db:label nullFieldValue="" fieldName="content" />
</td><td align="left"> <db:select fieldName="sachgebiete_id" customEntry=",,true"><% sql = "select tid, name from sachgebiete order by name;"; %><db:queryData name="sx_repository_sachgebiete60" query="<%= sql %>" dbConnectionName="<%= mandantenid %>" /></db:select></td><td align="left">
<db:textField nullFieldValue="" styleClass="clsInputStyle" size="6" fieldName="sort1"/></td><td align="left">
<db:textField nullFieldValue="" styleClass="clsInputStyle" size="6" fieldName="aktiv"/></td><td><%
<db:textField nullFieldValue="" styleClass="clsInputStyle" maxlength="200" size="30" fieldName="art"/></td><td><%
if(currentRow_sx_repository != null)
{
%><a target="details" title="Details" href="<%= response.encodeURL("/superx/edit/kern/sx_repository_edit.jsp") %>?sachgebiete_id=<%= sachgebiete_id %>&tid=<db:label nullFieldValue="" pattern="######" fieldName="tid"/>" onClick="javascript:neu=window.open('<%= response.encodeURL("/superx/edit/kern/sx_repository_edit.jsp") %>?sachgebiete_id=<%= sachgebiete_id %>&tid=<db:label nullFieldValue="" pattern="######" fieldName="tid"/>','_blank','directories=no,location=no,menubar=no,toolbar=no,scrollbars=yes,resizable=yes,width=800,height=600'); return false;"><img border="0" alt="Details" src="../../images/pencil.svg"></a><%

12
superx/xml/nd_templates.xsl

@ -4590,9 +4590,17 @@ document.forms["Weiterverarbeitung"].target = '_blank'; @@ -4590,9 +4590,17 @@ document.forms["Weiterverarbeitung"].target = '_blank';
<div class="leg_erl">
<dl> <span class="dl_title"><xsl:text>Ergebnistabelle</xsl:text></span>
<xsl:for-each select="sqlerg/headers/header [string-length(caption_long) &gt; 1 and caption_long !='null'and starts-with(f_name,'hidden')=false]">
<dt><span class="feldwert"><xsl:call-template name="nd_removeBackslash000">
<dt><span class="feldwert">
<xsl:variable name="s1">
<xsl:call-template name="nd_removeBackslash000">
<xsl:with-param name="string" select="wert" />
</xsl:call-template></span> </dt>
</xsl:call-template>
</xsl:variable>
<xsl:call-template name="removeBackslashN" >
<xsl:with-param name="derwert"><xsl:value-of select="$s1" /></xsl:with-param>
<xsl:with-param name="format"><xsl:value-of select="'html'" /></xsl:with-param>
</xsl:call-template>
</span> </dt>
<dd><xsl:call-template name="nd_prepareColCaptionlong"><xsl:with-param name="string" select="caption_long" /></xsl:call-template>
</dd>
</xsl:for-each>

Loading…
Cancel
Save