Permalink
Browse files

[feature] Initial SetUid priviledge escalation

  • Loading branch information...
1 parent 707d49a commit 5e9711aed0a48ca151d54c3d0bf9ed7034949a62 @adamretter adamretter committed Nov 12, 2013
@@ -0,0 +1,223 @@
+package org.exist.security;
+
+import java.util.Set;
+import org.exist.config.Configuration;
+import org.exist.config.ConfigurationException;
+import org.exist.security.realm.Realm;
+import org.exist.storage.DBBroker;
+
+public class EffectiveSubject implements Subject {
+ private final Account account;
+
+ public EffectiveSubject(final Account account) {
+ this.account = account;
+ }
+
+ @Override
+ public String getRealmId() {
+ return account.getRealmId();
+ }
+
+ @Override
+ public Realm getRealm() {
+ return account.getRealm();
+ }
+
+ @Override
+ public int getId() {
+ return account.getId(); //TODO is this correct or need own reserved id?
+ }
+
+ @Override
+ public String getUsername() {
+ return "_effective_" + account.getUsername();
+ }
+
+ @Override
+ public String getName() {
+ return getUsername();
+ }
+
+ @Override
+ public boolean authenticate(final Object credentials) {
+ return false;
+ }
+
+ //<editor-fold desc="account status">
+ @Override
+ public boolean isAuthenticated() {
+ return false;
+ }
+
+ @Override
+ public boolean isExternallyAuthenticated() {
+ return false;
+ }
+
+ @Override
+ public boolean isAccountNonExpired() {
+ return account.isAccountNonExpired();
+ }
+
+ @Override
+ public boolean isAccountNonLocked() {
+ return account.isAccountNonLocked();
+ }
+
+ @Override
+ public boolean isCredentialsNonExpired() {
+ return account.isCredentialsNonExpired();
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return account.isEnabled();
+ }
+
+ @Override
+ public void setEnabled(final boolean enabled) {
+ throw new UnsupportedOperationException("You cannot change the Enabled status of the Effective User.");
+ }
+ //</editor-fold>
+
+ @Override
+ public String getSessionId() {
+ throw new UnsupportedOperationException("The Effective User has no session!");
+ }
+
+ @Override
+ public Session getSession() {
+ throw new UnsupportedOperationException("The Effective User has no session!");
+ }
+
+ //<editor-fold desc="group functions">
+ @Override
+ public String[] getGroups() {
+ return account.getGroups();
+ }
+
+ @Override
+ public int[] getGroupIds() {
+ return account.getGroupIds();
+ }
+
+ @Override
+ public boolean hasDbaRole() {
+ return account.hasDbaRole();
+ }
+
+ @Override
+ public String getPrimaryGroup() {
+ return account.getPrimaryGroup();
+ }
+
+ @Override
+ public Group getDefaultGroup() {
+ return account.getDefaultGroup();
+ }
+
+ @Override
+ public boolean hasGroup(final String group) {
+ return account.hasGroup(group);
+ }
+
+ @Override
+ public Group addGroup(final String name) throws PermissionDeniedException {
+ throw new UnsupportedOperationException("You cannot add a group to the Effective User");
+ }
+
+ @Override
+ public Group addGroup(final Group group) throws PermissionDeniedException {
+ throw new UnsupportedOperationException("You cannot add a group to the Effective User");
+ }
+
+ @Override
+ public void setPrimaryGroup(final Group group) throws PermissionDeniedException {
+ throw new UnsupportedOperationException("You cannot add a group to the Effective User");
+ }
+
+ @Override
+ public void setGroups(final String[] groups) {
+ throw new UnsupportedOperationException("You cannot set the groups of the Effective User");
+ }
+
+ @Override
+ public void remGroup(final String group) throws PermissionDeniedException {
+ throw new UnsupportedOperationException("You cannot remove a group from the Effective User");
+ }
+ //</editor-fold>
+
+ @Override
+ public void setPassword(final String passwd) {
+ throw new UnsupportedOperationException("The Effective User has no password!");
+ }
+
+ @Override
+ public String getPassword() {
+ throw new UnsupportedOperationException("The Effective User has no password!");
+ }
+
+ @Override
+ public String getDigestPassword() {
+ throw new UnsupportedOperationException("The Effective User has no password!");
+ }
+
+ @Override
+ public void assertCanModifyAccount(final Account user) throws PermissionDeniedException {
+ throw new PermissionDeniedException("The Effective User account cannot be modified");
+ }
+
+ @Override
+ public int getUserMask() {
+ return account.getUserMask();
+ }
+
+ @Override
+ public void setUserMask(final int umask) {
+ throw new UnsupportedOperationException("You cannot set the UserMask of the Effective User"); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ //<editor-fold desc="metadata">
+ @Override
+ public String getMetadataValue(final SchemaType schemaType) {
+ return account.getMetadataValue(schemaType);
+ }
+
+ @Override
+ public Set<SchemaType> getMetadataKeys() {
+ return account.getMetadataKeys();
+ }
+
+ @Override
+ public void setMetadataValue(SchemaType schemaType, String value) {
+ throw new UnsupportedOperationException("You cannot modify the metadata of the Effective User");
+ }
+
+ @Override
+ public void clearMetadata() {
+ throw new UnsupportedOperationException("You cannot modify the metadata of the Effective User");
+ }
+ //</editor-fold>
+
+ //<editor-fold desc="persistence">
+ @Override
+ public void save() throws ConfigurationException, PermissionDeniedException {
+ throw new UnsupportedOperationException("You cannot perist the Effective User.");
+ }
+
+ @Override
+ public void save(final DBBroker broker) throws ConfigurationException, PermissionDeniedException {
+ throw new UnsupportedOperationException("You cannot perist the Effective User.");
+ }
+
+ @Override
+ public boolean isConfigured() {
+ return true; //the effective user does not need configuring
+ }
+
+ @Override
+ public Configuration getConfiguration() {
+ return null; //the effective user does not need configuring
+ }
+ //</editor-fold>
+}
@@ -31,6 +31,7 @@
import org.exist.dom.BinaryDocument;
import org.exist.dom.DocumentImpl;
import org.exist.dom.QName;
+import org.exist.security.Permission;
import org.exist.security.PermissionDeniedException;
import org.exist.security.Subject;
import org.exist.security.internal.aider.UnixStylePermissionAider;
@@ -196,4 +197,8 @@ public void validate(final Subject subject, final int mode) throws PermissionDen
throw new PermissionDeniedException("Subject '" + subject.getName() + "' does not have '" + modeStr + "' access to resource '" + doc.getURI() + "'.");
}
}
+
+ public Permission getPermissions() {
+ return doc.getPermissions();
+ }
}
@@ -33,11 +33,14 @@
import java.util.Properties;
import org.apache.log4j.Logger;
import org.exist.debuggee.Debuggee;
+import org.exist.security.EffectiveSubject;
import org.exist.security.Permission;
import org.exist.security.PermissionDeniedException;
+import org.exist.security.Subject;
import org.exist.security.xacml.AccessContext;
import org.exist.security.xacml.ExistPDP;
import org.exist.security.xacml.XACMLSource;
+import org.exist.source.DBSource;
import org.exist.source.FileSource;
import org.exist.source.Source;
import org.exist.source.StringSource;
@@ -62,7 +65,7 @@
private final DBBroker broker;
/**
- *
+ * @param broker DBBroker to use for compilation and execution
*/
public XQuery(final DBBroker broker) {
this.broker = broker;
@@ -228,6 +231,21 @@ public Sequence execute(final CompiledXQuery expression, final Sequence contextS
//check execute permissions
expression.getContext().getSource().validate(broker.getSubject(), Permission.EXECUTE);
+ //if setUid become effective user
+ EffectiveSubject effectiveSubject = null;
+ final Source src = expression.getContext().getSource();
+ if(src instanceof DBSource) {
+ final DBSource dbSrc = (DBSource)src;
+ final Permission perm = dbSrc.getPermissions();
+
+ if(perm.isSetUid()) {
+ effectiveSubject = new EffectiveSubject(perm.getOwner());
+ }
+ //if(perm.isSetGid()) {
+
+ //}
+ }
+
final long start = System.currentTimeMillis();
@@ -261,27 +279,39 @@ public Sequence execute(final CompiledXQuery expression, final Sequence contextS
//do any preparation before execution
context.prepareForExecution();
- context.getProfiler().traceQueryStart();
- broker.getBrokerPool().getProcessMonitor().queryStarted(context.getWatchDog());
+ final Subject callingUser = broker.getSubject();
try {
- final Sequence result = expression.eval(contextSequence);
- if(LOG.isDebugEnabled()) {
- final NumberFormat nf = NumberFormat.getNumberInstance();
- LOG.debug("Execution took " + nf.format(System.currentTimeMillis() - start) + " ms");
+ if(effectiveSubject != null) {
+ broker.setSubject(effectiveSubject); //switch to effective user (e.g. setuid/setgid)
}
+
+ context.getProfiler().traceQueryStart();
+ broker.getBrokerPool().getProcessMonitor().queryStarted(context.getWatchDog());
+ try {
+ final Sequence result = expression.eval(contextSequence);
+ if(LOG.isDebugEnabled()) {
+ final NumberFormat nf = NumberFormat.getNumberInstance();
+ LOG.debug("Execution took " + nf.format(System.currentTimeMillis() - start) + " ms");
+ }
- if(outputProperties != null) {
- context.checkOptions(outputProperties); //must be done before context.reset!
- }
+ if(outputProperties != null) {
+ context.checkOptions(outputProperties); //must be done before context.reset!
+ }
- return result;
+ return result;
+ } finally {
+ context.getProfiler().traceQueryEnd(context);
+ expression.reset();
+ if(resetContext) {
+ context.reset();
+ }
+ broker.getBrokerPool().getProcessMonitor().queryCompleted(context.getWatchDog());
+ }
+
} finally {
- context.getProfiler().traceQueryEnd(context);
- expression.reset();
- if(resetContext) {
- context.reset();
+ if(effectiveSubject != null) {
+ broker.setSubject(callingUser);
}
- broker.getBrokerPool().getProcessMonitor().queryCompleted(context.getWatchDog());
}
}
Oops, something went wrong.

0 comments on commit 5e9711a

Please sign in to comment.