• 如果您想对本站表示支持,请随手点击一下广告即可~
  • 本站致力于提供原创、优秀的技术文章~
  • 有任何疑问或建议 均可以在站点右侧栏处 通过各种方式联系站长哦~
  • CTF – RootMe解题报告 [Web-Server : LDAP injection – authentication]

    渗透测试 EXP 158阅读 0评论

    挑战入口:Root-Me(https://www.root-me.org/en/Challenges/Web-Server/LDAP-injection-authentication)
      分类目录:Link to …(http://exp-blog.com/2019/01/02/pid-2597/12/)

    前置知识

    知道原理其实就是很水的一道题。

    关于 LDAP 的前置知识可以参考这几篇文章:

    相关语法

    这里简单解释一下, LDAP(Lightweight Directory Access Protocol,轻量级目录访问协议)其实就是数据库的一种替代形式,其原理是以目录树结构存储数据,不过它的语法比传统数据库要稍微简单一点。

    与本题相关的一些 LDAP 语法:

    • WHERE A=xxx AND B=yyy ,转变成 LDAP 语法就是 (&(A=xxx)(B=yyy))
    • WHERE A=xxx OR B=yyy ,转变成 LDAP 语法就是 (|(A=xxx)(B=yyy))
    • WHERE A LIKE 'x%' ,转变成 LDAP 语法就是 (&(A=x*)(B=*))(&(A=x*)(&))(注:(&)是永真式)
    • 支持嵌套,如: (&(A=xxx)(|(A=xxx)(C=zzz)))

    LDAP 把括号称之为【过滤器】,所有元素/操作都必须在括号内

    找到注入点

    知道这些就可以解题了。

    注意题目要求是【绕过登陆校验】。

    开启挑战后要求输入账号密码,因为知道是 LDAP ,那么就尝试闭合括号令其语法报错,看看会不会返回一些有用的异常信息。

    输入探针 Username = admin) , Password = 123456 ,页面回显异常:

    ERROR : Invalid LDAP syntax : (&(uid=admin))(userPassword=123456))

    很明显,用于登陆验证的 LDAP 代码逻辑为:

    (&(uid=[username])(userPassword=[password]))

    其中 [username][password] 就是我们可控的注入点。

    构造 payload

    其实知道这两个注入点,绕过密码的注入方式就可以很灵活了(我至少想到了 5 种注入方法),关键是题目对 LDAP 的语法校验有多严格,这直接决定有效的 payload 数量。


    方法一:正确账号+嵌套式

    构造 payload :

    • username = 账号)(|(uid=账号
    • password = exp)

    实际拼接成的 payload 为:(&(uid=账号)(|(uid=账号)(userPassword=exp)))

    这个 payload 先计算后面的 或运算,当 账号 正确的时候,由于 (uid=账号) 为真,所以无论 userPassword 输入任何值,整个条件式都是真,从而实现密码绕过。所以这个 payload 的关键是找到正确的账号 (相比于猜密码,账号会更好猜)。

    可以猜到的 账号 有 4 个:

    • admin
    • administrator
    • root
    • ch25 (这是从 URL 取到的题号,从 rootme 的经验上看,题号经常就是账号)

      逐个账号试,发现 ch25 果然就是账号,得到密码(回显被加密,需要看源码),完成挑战:


    方法二:模糊匹配+嵌套式

    相较于方法一,其实有另一个更巧妙的方法,可以构造这样的 payload :

    • username = *)(|(uid=*
    • password = exp)

    实际拼接成的 payload 为:(&(uid=*)(|(uid=*)(userPassword=exp)))

    这个 payload 先计算后面的 或运算,而且由于 (uid=*) 是模糊匹配,必定永真(连账号也不用猜),所以无论 userPassword 输入任何值,整个条件式都是永真。

    此方法在本题可以成功绕过验证,得到密码。

    使用模糊匹配的前提是 * 没有被过滤,否则也是只能猜账号,但一般来说,账号比密码更好猜。


    方法三:永真式+解析器截断

    构造 payload (此方式同样要求猜测正确的账号以绕过,由于已经知道是 ch25 就不猜了):

    • username = ch25)(&)
    • password = exp

    实际拼接成的 payload 为:(&(uid=ch25)(&))(userPassword=exp))

    注意这个 payload 的前半部分 (&(uid=ch25)(&)) 语法是正确的,但后半部分 (userPassword=exp)) 因为括号没有配对,是语法错误的。

    在某些对 LDAP 语法校验不严谨的题型,依然会从左到右执行,直到报错为止,因此这个 payload 在某些环境是可以实现绕过的。但是很明显这题不行:


    方法四:永真式+%00截断

    构造 payload (此方式同样要求猜测正确的账号以绕过,由于已经知道是 ch25 就不猜了):

    • username = ch25)(&))%00
    • password = exp

    实际拼接成的 payload 为:(&(uid=ch25)(&))%00)(userPassword=exp))

    这与方法三很类似,只是截断依赖于 %00 而非解析器。

    %00 是 C 或 PHP 的字符串终止符 \0 的 URL 编码,只要这个字符没有被过滤,在 LDAP 校验严谨的环境下也能对语法错误的 LDAP 进行截断。但是很明显这题不行:


    方法五:串行过滤器

    构造 payload (此方式同样要求猜测正确的账号以绕过,由于已经知道是 ch25 就不猜了):

    • username = ch25)(uid=ch25)) (&(1=0
    • password = exp

    实际拼接成的 payload 为:(&(uid=ch25)(uid=ch25)) (&(1=0)(userPassword=exp))

    此方法构造了两个过滤器,在语法校验不严谨的 LDAP 中,只会执行第一个过滤器 (&(uid=ch25)(uid=ch25)) ,而第二个过滤器 (&(1=0)(userPassword=exp)) 则不会被执行,从而可以实现密码绕过。

    而对于第一个过滤器,只要账号是正确的,就必定为真。不过此方式在本题也行不通:


    转载请注明:EXP 技术分享博客 » CTF – RootMe解题报告 [Web-Server : LDAP injection – authentication]

    喜欢 (1) 分享 (0)
    发表我的评论
    取消评论

    表情

    Hi,您需要填写昵称和邮箱!

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址