VYPR
Moderate severityNVD Advisory· Published Mar 20, 2018· Updated Sep 16, 2024

CVE-2018-1322

CVE-2018-1322

Description

Apache Syncope administrator with search entitlements can recover sensitive security values via fiql and orderby parameters.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Apache Syncope administrator with search entitlements can recover sensitive security values via fiql and orderby parameters.

Vulnerability

An information disclosure vulnerability exists in Apache Syncope 1.2.x before 1.2.11, 2.0.x before 2.0.8, and unsupported releases 1.0.x and 1.1.x [1][2]. An administrator with user search entitlements can use the fiql and orderby parameters to recover sensitive security values that should not be searchable or sortable [1][2]. The affected code did not properly filter fields such as securityAnswer, token, and tokenExpireTime from search and sort operations [3][4].

Exploitation

An authenticated attacker who is an administrator with user search entitlements can craft malicious fiql or orderby queries to access sensitive security fields [1][2]. The attacker does not need any additional privileges beyond the standard search entitlements. By using the fiql parameter to search on sensitive fields or the orderby parameter to sort results by those fields, the attacker can extract the values [3][4].

Impact

Successful exploitation allows the attacker to disclose sensitive security values, such as security answers, tokens, and token expiration times, for users in the Apache Syncope system [3][4]. This constitutes a confidentiality breach of sensitive authentication-related data. The attacker may use this information for further attacks, such as account takeover or privilege escalation.

Mitigation

Apache Syncope 1.2.11, 2.0.8, and later versions fix this issue by restricting the fields usable for search and sorting [1]. The fix adds securityAnswer, token, tokenExpireTime, and other sensitive fields to the list of attributes not included in searchable fields and order-by clauses [3][4]. Users should upgrade to the patched versions immediately [1]. No workaround is available, and unsupported releases (1.0.x, 1.1.x) are also affected but will not receive patches [1].

AI Insight generated on May 22, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.apache.syncope:syncope-coreMaven
< 1.2.111.2.11
org.apache.syncope:syncope-coreMaven
>= 2.0.0, < 2.0.82.0.8

Affected products

2

Patches

4
44a5ca0fbd35

Review fields usable for search and orderBy

https://github.com/apache/syncopeFrancesco ChicchiriccòMar 8, 2018via ghsa
3 files changed · +36 3
  • common/src/main/java/org/apache/syncope/common/search/SearchableFields.java+1 1 modified
    @@ -33,7 +33,7 @@ public class SearchableFields {
         protected static final String[] ATTRIBUTES_NOTINCLUDED = {
             "attrs", "derAttrs", "virAttrs",
             "serialVersionUID", "memberships", "entitlements", "resources", "password",
    -        "propagationTOs", "propagationStatusMap"
    +        "propagationTOs", "propagationStatusMap", "securityAnswer", "token", "tokenExpireTime"
         };
     
         public static final List<String> get(final SubjectType subjectType) {
    
  • core/src/main/java/org/apache/syncope/core/persistence/dao/impl/SubjectSearchDAOImpl.java+18 2 modified
    @@ -63,6 +63,10 @@ public class SubjectSearchDAOImpl extends AbstractDAOImpl implements SubjectSear
     
         private static final String[] SUBJECT_FIELDS = new String[] { "parent", "userOwner", "roleOwner" };
     
    +    private static final String[] ORDER_BY_NOT_ALLOWED = {
    +        "serialVersionUID", "password", "securityQuestion", "securityAnswer", "token", "tokenExpireTime"
    +    };
    +
         @Autowired
         private UserDAO userDAO;
     
    @@ -285,12 +289,24 @@ private StringBuilder buildOrderBy(final OrderBySupport obs) {
             return orderBy;
         }
     
    -    private OrderBySupport parseOrderBy(final SearchSupport svs, final List<OrderByClause> orderByClauses) {
    +    protected List<OrderByClause> filterOrderBy(final List<OrderByClause> orderBy) {
    +        List<OrderByClause> result = new ArrayList<OrderByClause>();
    +
    +        for (OrderByClause clause : orderBy) {
    +            if (!ArrayUtils.contains(ORDER_BY_NOT_ALLOWED, clause.getField())) {
    +                result.add(clause);
    +            }
    +        }
    +
    +        return result;
    +    }
    +
    +    private OrderBySupport parseOrderBy(final SearchSupport svs, final List<OrderByClause> orderBy) {
             final AttributableUtil attrUtil = AttributableUtil.getInstance(svs.type.asAttributableType());
     
             OrderBySupport obs = new OrderBySupport();
     
    -        for (OrderByClause clause : orderByClauses) {
    +        for (OrderByClause clause : filterOrderBy(orderBy)) {
                 OrderBySupport.Item item = new OrderBySupport.Item();
     
                 Field subjectField = ReflectionUtils.findField(attrUtil.attributableClass(), clause.getField());
    
  • core/src/test/java/org/apache/syncope/core/rest/SearchTestITCase.java+17 0 modified
    @@ -27,6 +27,7 @@
     import java.util.HashSet;
     import java.util.List;
     import java.util.Set;
    +import org.apache.commons.lang3.RandomStringUtils;
     import org.apache.syncope.client.SyncopeClient;
     import org.apache.syncope.common.reqres.PagedResult;
     import org.apache.syncope.common.services.UserSelfService;
    @@ -199,6 +200,22 @@ public void nested() {
             }
         }
     
    +    @Test
    +    public void searchBySecurityAnswer() {
    +        String securityAnswer = RandomStringUtils.randomAlphanumeric(10);
    +        UserTO userTO = UserTestITCase.getUniqueSampleTO("securityAnswer@syncope.apache.org");
    +        userTO.setSecurityQuestion(1L);
    +        userTO.setSecurityAnswer(securityAnswer);
    +
    +        userTO = createUser(userTO);
    +        assertNotNull(userTO.getSecurityQuestion());
    +
    +        PagedResult<UserTO> matchingUsers = userService.search(SyncopeClient.getUserSearchConditionBuilder().
    +                is("securityAnswer").equalTo(securityAnswer).query());
    +        assertNotNull(matchingUsers);
    +        assertTrue(matchingUsers.getResult().isEmpty());
    +    }
    +
         @Test
         public void orderBy() {
             PagedResult<UserTO> users = userService.search(
    
44a5ca0fbd35

Review fields usable for search and orderBy

https://github.com/apache/syncopeFrancesco ChicchiriccòMar 8, 2018via ghsa
3 files changed · +36 3
  • common/src/main/java/org/apache/syncope/common/search/SearchableFields.java+1 1 modified
    @@ -33,7 +33,7 @@ public class SearchableFields {
         protected static final String[] ATTRIBUTES_NOTINCLUDED = {
             "attrs", "derAttrs", "virAttrs",
             "serialVersionUID", "memberships", "entitlements", "resources", "password",
    -        "propagationTOs", "propagationStatusMap"
    +        "propagationTOs", "propagationStatusMap", "securityAnswer", "token", "tokenExpireTime"
         };
     
         public static final List<String> get(final SubjectType subjectType) {
    
  • core/src/main/java/org/apache/syncope/core/persistence/dao/impl/SubjectSearchDAOImpl.java+18 2 modified
    @@ -63,6 +63,10 @@ public class SubjectSearchDAOImpl extends AbstractDAOImpl implements SubjectSear
     
         private static final String[] SUBJECT_FIELDS = new String[] { "parent", "userOwner", "roleOwner" };
     
    +    private static final String[] ORDER_BY_NOT_ALLOWED = {
    +        "serialVersionUID", "password", "securityQuestion", "securityAnswer", "token", "tokenExpireTime"
    +    };
    +
         @Autowired
         private UserDAO userDAO;
     
    @@ -285,12 +289,24 @@ private StringBuilder buildOrderBy(final OrderBySupport obs) {
             return orderBy;
         }
     
    -    private OrderBySupport parseOrderBy(final SearchSupport svs, final List<OrderByClause> orderByClauses) {
    +    protected List<OrderByClause> filterOrderBy(final List<OrderByClause> orderBy) {
    +        List<OrderByClause> result = new ArrayList<OrderByClause>();
    +
    +        for (OrderByClause clause : orderBy) {
    +            if (!ArrayUtils.contains(ORDER_BY_NOT_ALLOWED, clause.getField())) {
    +                result.add(clause);
    +            }
    +        }
    +
    +        return result;
    +    }
    +
    +    private OrderBySupport parseOrderBy(final SearchSupport svs, final List<OrderByClause> orderBy) {
             final AttributableUtil attrUtil = AttributableUtil.getInstance(svs.type.asAttributableType());
     
             OrderBySupport obs = new OrderBySupport();
     
    -        for (OrderByClause clause : orderByClauses) {
    +        for (OrderByClause clause : filterOrderBy(orderBy)) {
                 OrderBySupport.Item item = new OrderBySupport.Item();
     
                 Field subjectField = ReflectionUtils.findField(attrUtil.attributableClass(), clause.getField());
    
  • core/src/test/java/org/apache/syncope/core/rest/SearchTestITCase.java+17 0 modified
    @@ -27,6 +27,7 @@
     import java.util.HashSet;
     import java.util.List;
     import java.util.Set;
    +import org.apache.commons.lang3.RandomStringUtils;
     import org.apache.syncope.client.SyncopeClient;
     import org.apache.syncope.common.reqres.PagedResult;
     import org.apache.syncope.common.services.UserSelfService;
    @@ -199,6 +200,22 @@ public void nested() {
             }
         }
     
    +    @Test
    +    public void searchBySecurityAnswer() {
    +        String securityAnswer = RandomStringUtils.randomAlphanumeric(10);
    +        UserTO userTO = UserTestITCase.getUniqueSampleTO("securityAnswer@syncope.apache.org");
    +        userTO.setSecurityQuestion(1L);
    +        userTO.setSecurityAnswer(securityAnswer);
    +
    +        userTO = createUser(userTO);
    +        assertNotNull(userTO.getSecurityQuestion());
    +
    +        PagedResult<UserTO> matchingUsers = userService.search(SyncopeClient.getUserSearchConditionBuilder().
    +                is("securityAnswer").equalTo(securityAnswer).query());
    +        assertNotNull(matchingUsers);
    +        assertTrue(matchingUsers.getResult().isEmpty());
    +    }
    +
         @Test
         public void orderBy() {
             PagedResult<UserTO> users = userService.search(
    
735579b6f987

Review fields usable for search and orderBy

https://github.com/apache/syncopeFrancesco ChicchiriccòMar 7, 2018via ghsa
5 files changed · +40 4
  • common/lib/src/main/java/org/apache/syncope/common/lib/search/SearchableFields.java+1 1 modified
    @@ -36,7 +36,7 @@
     public final class SearchableFields {
     
         private static final String[] ATTRIBUTES_NOTINCLUDED = {
    -        "serialVersionUID", "password", "type", "udynMembershipCond"
    +        "serialVersionUID", "password", "type", "udynMembershipCond", "securityAnswer", "token", "tokenExpireTime"
         };
     
         private static final Set<String> ANY_FIELDS = new HashSet<>();
    
  • core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnySearchDAO.java+17 0 modified
    @@ -30,7 +30,10 @@
     import javax.validation.constraints.Max;
     import javax.validation.constraints.Min;
     import org.apache.commons.collections4.CollectionUtils;
    +import org.apache.commons.collections4.ListUtils;
    +import org.apache.commons.collections4.Predicate;
     import org.apache.commons.collections4.Transformer;
    +import org.apache.commons.lang3.ArrayUtils;
     import org.apache.commons.lang3.ClassUtils;
     import org.apache.commons.lang3.SerializationUtils;
     import org.apache.commons.lang3.tuple.Pair;
    @@ -68,6 +71,10 @@
     
     public abstract class AbstractAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO {
     
    +    private static final String[] ORDER_BY_NOT_ALLOWED = {
    +        "serialVersionUID", "password", "securityQuestion", "securityAnswer", "token", "tokenExpireTime"
    +    };
    +
         @Autowired
         protected RealmDAO realmDAO;
     
    @@ -134,6 +141,16 @@ public <T extends Any<?>> List<T> search(
             return search(SyncopeConstants.FULL_ADMIN_REALMS, cond, -1, -1, orderBy, kind);
         }
     
    +    protected List<OrderByClause> filterOrderBy(final List<OrderByClause> orderBy) {
    +        return ListUtils.select(orderBy, new Predicate<OrderByClause>() {
    +
    +            @Override
    +            public boolean evaluate(final OrderByClause clause) {
    +                return !ArrayUtils.contains(ORDER_BY_NOT_ALLOWED, clause.getField());
    +            }
    +        });
    +    }
    +
         protected abstract <T extends Any<?>> List<T> doSearch(
                 Set<String> adminRealms,
                 SearchCond searchCondition,
    
  • core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java+2 2 modified
    @@ -276,13 +276,13 @@ private StringBuilder buildOrderBy(final OrderBySupport obs) {
         }
     
         private OrderBySupport parseOrderBy(
    -            final AnyTypeKind kind, final SearchSupport svs, final List<OrderByClause> orderByClauses) {
    +            final AnyTypeKind kind, final SearchSupport svs, final List<OrderByClause> orderBy) {
     
             AnyUtils attrUtils = anyUtilsFactory.getInstance(kind);
     
             OrderBySupport obs = new OrderBySupport();
     
    -        for (OrderByClause clause : orderByClauses) {
    +        for (OrderByClause clause : filterOrderBy(orderBy)) {
                 OrderBySupport.Item item = new OrderBySupport.Item();
     
                 // Manage difference among external key attribute and internal JPA @Id
    
  • ext/elasticsearch/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAO.java+1 1 modified
    @@ -147,7 +147,7 @@ private void addSort(
     
             AnyUtils attrUtils = anyUtilsFactory.getInstance(kind);
     
    -        for (OrderByClause clause : orderBy) {
    +        for (OrderByClause clause : filterOrderBy(orderBy)) {
                 String sortName = null;
     
                 // Manage difference among external key attribute and internal JPA @Id
    
  • fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java+19 0 modified
    @@ -29,6 +29,7 @@
     import org.apache.commons.collections4.CollectionUtils;
     import org.apache.commons.collections4.IterableUtils;
     import org.apache.commons.collections4.Predicate;
    +import org.apache.commons.lang3.RandomStringUtils;
     import org.apache.syncope.client.lib.SyncopeClient;
     import org.apache.syncope.common.lib.SyncopeConstants;
     import org.apache.syncope.common.lib.patch.AnyObjectPatch;
    @@ -406,6 +407,24 @@ public boolean evaluate(final UserTO user) {
             }));
         }
     
    +    @Test
    +    public void searchBySecurityAnswer() {
    +        String securityAnswer = RandomStringUtils.randomAlphanumeric(10);
    +        UserTO userTO = UserITCase.getUniqueSampleTO("securityAnswer@syncope.apache.org");
    +        userTO.setSecurityQuestion("887028ea-66fc-41e7-b397-620d7ea6dfbb");
    +        userTO.setSecurityAnswer(securityAnswer);
    +
    +        userTO = createUser(userTO).getEntity();
    +        assertNotNull(userTO.getSecurityQuestion());
    +
    +        PagedResult<UserTO> matchingUsers = userService.search(
    +                new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
    +                        fiql(SyncopeClient.getUserSearchConditionBuilder().
    +                                is("securityAnswer").equalTo(securityAnswer).query()).build());
    +        assertNotNull(matchingUsers);
    +        assertTrue(matchingUsers.getResult().isEmpty());
    +    }
    +
         @Test
         public void assignable() {
             PagedResult<GroupTO> groups = groupService.search(new AnyQuery.Builder().realm("/even/two").page(1).size(1000).
    
735579b6f987

Review fields usable for search and orderBy

https://github.com/apache/syncopeFrancesco ChicchiriccòMar 7, 2018via ghsa
5 files changed · +40 4
  • common/lib/src/main/java/org/apache/syncope/common/lib/search/SearchableFields.java+1 1 modified
    @@ -36,7 +36,7 @@
     public final class SearchableFields {
     
         private static final String[] ATTRIBUTES_NOTINCLUDED = {
    -        "serialVersionUID", "password", "type", "udynMembershipCond"
    +        "serialVersionUID", "password", "type", "udynMembershipCond", "securityAnswer", "token", "tokenExpireTime"
         };
     
         private static final Set<String> ANY_FIELDS = new HashSet<>();
    
  • core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnySearchDAO.java+17 0 modified
    @@ -30,7 +30,10 @@
     import javax.validation.constraints.Max;
     import javax.validation.constraints.Min;
     import org.apache.commons.collections4.CollectionUtils;
    +import org.apache.commons.collections4.ListUtils;
    +import org.apache.commons.collections4.Predicate;
     import org.apache.commons.collections4.Transformer;
    +import org.apache.commons.lang3.ArrayUtils;
     import org.apache.commons.lang3.ClassUtils;
     import org.apache.commons.lang3.SerializationUtils;
     import org.apache.commons.lang3.tuple.Pair;
    @@ -68,6 +71,10 @@
     
     public abstract class AbstractAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO {
     
    +    private static final String[] ORDER_BY_NOT_ALLOWED = {
    +        "serialVersionUID", "password", "securityQuestion", "securityAnswer", "token", "tokenExpireTime"
    +    };
    +
         @Autowired
         protected RealmDAO realmDAO;
     
    @@ -134,6 +141,16 @@ public <T extends Any<?>> List<T> search(
             return search(SyncopeConstants.FULL_ADMIN_REALMS, cond, -1, -1, orderBy, kind);
         }
     
    +    protected List<OrderByClause> filterOrderBy(final List<OrderByClause> orderBy) {
    +        return ListUtils.select(orderBy, new Predicate<OrderByClause>() {
    +
    +            @Override
    +            public boolean evaluate(final OrderByClause clause) {
    +                return !ArrayUtils.contains(ORDER_BY_NOT_ALLOWED, clause.getField());
    +            }
    +        });
    +    }
    +
         protected abstract <T extends Any<?>> List<T> doSearch(
                 Set<String> adminRealms,
                 SearchCond searchCondition,
    
  • core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java+2 2 modified
    @@ -276,13 +276,13 @@ private StringBuilder buildOrderBy(final OrderBySupport obs) {
         }
     
         private OrderBySupport parseOrderBy(
    -            final AnyTypeKind kind, final SearchSupport svs, final List<OrderByClause> orderByClauses) {
    +            final AnyTypeKind kind, final SearchSupport svs, final List<OrderByClause> orderBy) {
     
             AnyUtils attrUtils = anyUtilsFactory.getInstance(kind);
     
             OrderBySupport obs = new OrderBySupport();
     
    -        for (OrderByClause clause : orderByClauses) {
    +        for (OrderByClause clause : filterOrderBy(orderBy)) {
                 OrderBySupport.Item item = new OrderBySupport.Item();
     
                 // Manage difference among external key attribute and internal JPA @Id
    
  • ext/elasticsearch/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAO.java+1 1 modified
    @@ -147,7 +147,7 @@ private void addSort(
     
             AnyUtils attrUtils = anyUtilsFactory.getInstance(kind);
     
    -        for (OrderByClause clause : orderBy) {
    +        for (OrderByClause clause : filterOrderBy(orderBy)) {
                 String sortName = null;
     
                 // Manage difference among external key attribute and internal JPA @Id
    
  • fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java+19 0 modified
    @@ -29,6 +29,7 @@
     import org.apache.commons.collections4.CollectionUtils;
     import org.apache.commons.collections4.IterableUtils;
     import org.apache.commons.collections4.Predicate;
    +import org.apache.commons.lang3.RandomStringUtils;
     import org.apache.syncope.client.lib.SyncopeClient;
     import org.apache.syncope.common.lib.SyncopeConstants;
     import org.apache.syncope.common.lib.patch.AnyObjectPatch;
    @@ -406,6 +407,24 @@ public boolean evaluate(final UserTO user) {
             }));
         }
     
    +    @Test
    +    public void searchBySecurityAnswer() {
    +        String securityAnswer = RandomStringUtils.randomAlphanumeric(10);
    +        UserTO userTO = UserITCase.getUniqueSampleTO("securityAnswer@syncope.apache.org");
    +        userTO.setSecurityQuestion("887028ea-66fc-41e7-b397-620d7ea6dfbb");
    +        userTO.setSecurityAnswer(securityAnswer);
    +
    +        userTO = createUser(userTO).getEntity();
    +        assertNotNull(userTO.getSecurityQuestion());
    +
    +        PagedResult<UserTO> matchingUsers = userService.search(
    +                new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
    +                        fiql(SyncopeClient.getUserSearchConditionBuilder().
    +                                is("securityAnswer").equalTo(securityAnswer).query()).build());
    +        assertNotNull(matchingUsers);
    +        assertTrue(matchingUsers.getResult().isEmpty());
    +    }
    +
         @Test
         public void assignable() {
             PagedResult<GroupTO> groups = groupService.search(new AnyQuery.Builder().realm("/even/two").page(1).size(1000).
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

8

News mentions

0

No linked articles in our index yet.