zoukankan      html  css  js  c++  java
  • LDAP注入

    概述

    LDAP(Lightweight Directory Access Protocol):即轻量级目录访问协议。是一种运行于TCP/IP之上的在线目录访问协议,主要用于目录中资源的搜索和查询。使用最广泛的LDAP服务如微软的ADAM(Active Directory Application Mode)和OpenLDAP。

     

    而LDAP 注入是利用用户引入的参数生成恶意 LDAP 查询,通过构造 LDAP 过滤器来绕过访问控制、用户权限提升。在维持正常过滤器的情况下构造出 AND、OR 操作注入来获得敏感信息。

     

    目录数据库结构

    LDAP数据库,是树结构的,数据存储在叶子节点上。

    • dn:一条记录的位置
    • dc:一条记录所属的区域
    • ou:一条记录所属的组织
    • cn/uid:一条记录的名字/ID

    首先要说明是哪一棵树(dc),然后是从树根到目标所经过的所有分叉(ou),最后就是目标的名字(cn/uid),借用一张图来表明结构如下:

    条目&对象类&属性

    • 条目(entry):是目录中存储的基本信息单元,上图每一个方框代表一个entry。一个entry有若干个属性和若干个值,有些entry还能包含子entry
    • 对象类(obejectclass):对象类封装了可选/必选属性,同时对象类也是支持继承的。一个entry必须包含一个objectClass,且需要赋予至少一个值。而且objectClass有着严格的等级之分,最顶层是top和alias。例如,organizationalPerson这个objectClass就隶属于person,而person又隶属于top
    • 属性(atrribute):顾名思义,用来存储字段值。被封装在objectclass里的,每个属性(attribute)也会分配唯一的OID号码

    基本的LDAP语法

    • = 等于
    • & 逻辑和
    •  | 逻辑或
    •  ! 逻辑不 
    • * 通配符

    逻辑操作符(AND、OR、NOT)和关系操作符(=、>=、<=、~=)

    除使用逻辑操作符外,RFC4256还允许使用下面的单独符号作为两个特殊常量:

    (&)     ->Absolute TRUE
    (|)     ->Absolute FALSE
    

      

    对象定义:

    objectclass: top
    objectclass: person
    

      

    对象类定义:

    objectclass: person
    objectclasses=( 2.5.6.6 NAME 'person' DESC 'Defines entries that generically represent people.' SUP 'top' STRUCTURAL MUST ( cn $ sn ) MAY ( userPassword $ telephoneNumber $ seeAlso $ description ) 
    

      

    属性定义:

    attributetypes=( 2.5.4.4 NAME ( 'sn' 'surName' ) DESC 'This is the X.500 surname attribute, which contains the family name of a person.' SUP 2.5.4.41 EQUALITY 2.5.13.2 ORDERING 2.5.13.3 SUBSTR 2.5.13.4 USAGE userApplications )
    

      

    搜索语法:

    主要根据属性和值进行搜索

    attribute operator value
    

      

    LDAP查询语句

    一个圆括号内的判断语句又称为一个过滤器filter。

    默认情况下,LDAP的DN和所有属性都不区分大小写。

    ( "&" or "|" (filter1) (filter2) (filter3) ...) ("!" (filter))
    

      

    LDAP注入

    无逻辑操作符的注入

    后端代码如果是这样写的:

    (attribute=$input)
    

      

    我们构造输入语句:

    $input=value)(injected_filter
    

      

    完整的语句就成下面这样了:

    (attribute=value)(injected_filter)
    

      

    由于一个括号内代表一个过滤器,在OpenLDAP实施中,第二个过滤器会被忽略,只有第一个会被执行。而在ADAM中,有两个过滤器的查询是不被允许的。因而这类情况仅对于OpenLDAP有一定的影响。

    例如我们要想查询一个字段是否存在某值时,可以用$input=x*进行推移,利用页面响应不同判断x*是否查询成功。

     

    带有逻辑操作符的注入

    (|(attribute=$input)(second_filter))
    (&(attribute=$input)(second_filter))
    

      

    此时带有逻辑操作符的括号相当于一个过滤器。此时形如value)(injected_filter)的注入会变成如下过滤器结构

    (&(attribute=value)(injected_filter))(second_filter)
    

      

    虽然过滤器语法上并不正确,OpenLDAP还是会从左到右进行处理,忽略第一个过滤器闭合后的任何字符。一些LDAP客户端Web组成会忽略第二个过滤器,将ADAM和OpenLDAP发送给第一个完成的过滤器,因而存在注入。

    案例分享

    万能用户名案例

    验证登陆的查询语句是这样:

    (&(USER=$username)(PASSWORD=$pwd))
    

      

    输入$username = admin)(&)(使查询语句变为:

    (&(USER=admin)(&))((PASSWORD=$pwd))
    

      

    即可让后面的password过滤器失效,执行第一个过滤器而返回true,达到万能密码的效果。

    权限提升案例

    现假设下面的查询会向用户列举出所有可见的低安全等级文档:

    (&(directory=document)(security_level=low))
    

      

    这里第一个参数”document”是用户入口,low是第二个参数的值。如果攻击者想列举出所有可见的高安全等级的文档,他可以利用如下的注入:

    document)(security_level=*))(&(directory=documents
    

      

    生成的过滤器为:

    (&(directory=documents)(security_level=*))(&(direcroty=documents)(security_level=low))
    ###
    LDAP服务器仅会处理第一个过滤器而忽略第二个,因而只有下面的查询会被处理:(&(directory=documents)(security_level=*)),而(&(direcroty=documents)(security_level=low))则会被忽略。结果就是,所有安全等级的可用文档都会列举给攻击者,尽管他没有权限看它们。
    

      

    总结

    LDAP注入本质就是在OpenLDAP实施中,由于一个括号内代表一个过滤器,第二个过滤器会被忽略,只有第一个会被执行。当查询语句带有逻辑操作符时,可以通过注入恶意的LDAP语句去达到不同的目的。

     
     
     
  • 相关阅读:
    5月,专用程序猿的经典大作——APUE
    [Android]Can&#39;t create handler inside thread that has not called Looper.prepare()
    HDU 4433 locker 2012 Asia Tianjin Regional Contest 减少国家DP
    mac 下有些工具 app 推荐
    机器学习倚门回首嗅青梅
    Android复制iPhone日期和时间选择器
    更新代码和工具,组织起来,提供所有博文(C++,2014.09)
    poj3349
    web项目启动,运行方法
    jstat
  • 原文地址:https://www.cnblogs.com/endust/p/11811477.html
Copyright © 2011-2022 走看看