在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中

// 通过解析结果获得challengerc = 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.mzph.cn/news/129910.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【实战Flask API项目指南】之一 概述

实战Flask API项目指南之 概述 本系列文章将带你深入探索实战Flask API项目指南&#xff0c;通过跟随小菜的学习之旅&#xff0c;你将逐步掌握Flask在实际项目中的应用。让我们一起踏上这个精彩的学习之旅吧&#xff01; 前言 小菜是一个Python编程爱好者&#xff0c;他目前…

蓝桥杯 (C++ 求和 等差数列 顺子日期 灌溉)

目录 1、求和 题目&#xff1a; 思路&#xff1a; 代码&#xff1a; 2、等差数列 题目&#xff1a; 思路&#xff1a; 代码&#xff1a; 3、顺子日期 题目&#xff1a; 思路&#xff1a; 代码&#xff1a; 4、灌溉 题目&#xff1a; 代码&#xff1a; 1、求和…

c#中使用METest单元测试

METest是一个用于测试C#代码的单元测试框架。单元测试是一种软件测试方法&#xff0c;用于验证代码的各个单元&#xff08;函数、方法、类等&#xff09;是否按照预期工作。METest提供了一种简单而强大的方式来编写和运行单元测试。 TestMethod&#xff1a;这是一个特性&#…

KaiwuDB 内核解析 - SQL 查询的生命周期

一、概述 KaiwuDB 内核解析系列共分上下两部分&#xff0c;本文是该系列的第一部分&#xff0c;主要涵盖了网络协议到 SQL 执行器&#xff0c;解释 KaiwuDB 如何执行 SQL 查询&#xff0c;包括系统各个组件的执行路径&#xff08;网络协议、SQL 会话管理、解析器、执行计划及优…

odoo 按钮打印pdf报表

odoo打印一般是在动作里面进行的 所以此方法可用自定义按钮进行打印 <template id"report_sale_line_packing_template"> xxx </template><template id"report_sale_line_packing"><t t-call"web.basic_layout"><t …

maven的settings.xml和pom.xml配置文件详解

一、配置文件 maven的配置文件主要有 settings.xml 和pom.xml 两个文件。 其中在maven安装目录下的settings.xml&#xff0c;如&#xff1a;D:\Program Files\apache-maven-3.6.3\conf\settings.xml 是全局配置文件 用户目录的.m2子目录下的settings.xml&#xff0c;如&#…

C++分治算法------ 砍树

题目描述 伐木工人 Mirko 需要砍M米长的木材。对 Mirko 来说这是很简单的工作&#xff0c;因为他有一个漂亮的新伐木机&#xff0c;可以如野火一般砍伐森林。不过&#xff0c;Mirko 只被允许砍伐一排树。 Mirko 的伐木机工作流程如下&#xff1a;Mirko 设置一个高度参数H&…

大模型帮我梳理的docker命令

以下是一些常见的Docker命令&#xff1a; 1. docker run: 运行一个容器。示例&#xff1a;docker run <镜像名称> 2. docker pull: 下载一个镜像。示例&#xff1a;docker pull <镜像名称> 3. docker build: 构建一个镜像。示例&#xff1a;docker build -t <镜…

Linear FC FFN MLP层学习

一、Linear&#xff08;线性层&#xff09; 即神经网络的线性层&#xff0c;用于将输入映射到下一层的特征空间。它接受一个输入并与该层的权重的转置相乘。线性层没有激活函数。 公式&#xff1a; y x*W^T b&#xff0c;其中 W 是权重矩阵&#xff0c;b 是偏置向量。 pytorc…

每日一题411数组中两个数的最大异或值(哈希表、前缀树:实现前缀树)

数组中两个数的最大异或值(哈希表、前缀树&#xff1a;实现前缀树) LeetCode题目&#xff1a;https://leetcode.cn/problems/maximum-xor-of-two-numbers-in-an-array/ 哈希表解法 本题使用哈希表方法主要运用到一个定理&#xff1a;异或满足算法交换律。即如果a^b c&#x…

【Spring MVC】Spring MVC框架的介绍及其使用方法

目录 一、MVC模式 1.1 MVC模式的发展 1.1.1 Model1 模型 1.1.2 Model2 模型 1.2 MVC模式简介 1.模型(Model) 2.视图(View) 3.控制器(Controller) 二、Spring MVC模型简介 三、Spring MVC 六大核心组件 3.1 六大组件简介 1.前端控制器 DispatcherServlet&#xff08…

Notepad++下载、使用

下载 https://notepad-plus-plus.org/downloads/ 安装 双击安装 选择安装路径 使用 在文件夹中搜索 文件类型可以根据需要设置 如 *.* 说明是所有文件类型&#xff1b; *.tar 说明是所有文件后缀是是tar的文件‘&#xff1b;

多个PDF发票合并实现一张A4纸打印2张电子/数电发票功能

python教程79--A4纸增值税电子发票合并打印_python 打印 发票设置_颐街的博客-CSDN博客文章浏览阅读7.9k次。接上篇https://blog.csdn.net/itmsn/article/details/121902974?spm1001.2014.3001.5501一张A4纸上下2张增值税电子发票实现办法。使用环境&#xff1a;python3.8、ma…

JAVA 实现PDF转图片(pdfbox版)

依赖&#xff1a; pdf存放路径 正文开始&#xff1a; pdf转换多张图片、长图 Test void pdf2Image() {String dstImgFolder "";String PdfFilePath "";String relativelyPathSystem.getProperty("user.dir");PdfFilePath relativelyPath &qu…

企业之间的竞争,ISO三体系认证至关重要!

ISO三体系认证是指ISO 9001质量管理体系认证、ISO 14001环境管理体系认证、ISO 45001(OHSAS18001)职业健康安全管理体系认证。企业&#xff08;组织&#xff09;自愿申请、通过ISO三体系认证&#xff0c;并贯彻落实&#xff0c;确实能获益多多。 ISO 9001质量管理体系 我们经…

Scala的类和对象

1. 初识类和对象 Scala 的类与 Java 的类具有非常多的相似性&#xff0c;示例如下&#xff1a; // 1. 在 scala 中&#xff0c;类不需要用 public 声明,所有的类都具有公共的可见性 class Person {// 2. 声明私有变量,用 var 修饰的变量默认拥有 getter/setter 属性private var…

Ps:PSDT 模板文件

自 Photoshop CC 2015.5 版以后&#xff0c;Ps 中新增了一种文件格式&#xff1a;.PSDT。 说明&#xff1a; PSD、PDD、PSDT 都是 Ps 的专用文件格式&#xff0c;需要继续在 Ps 中进行编辑的文件可存为此类格式。 PSD Photoshop document Photoshop 默认文档格式&#xff0c;支…

选择适合你的办公桌:提高工作效率的关键

​在如今的数字时代&#xff0c;越来越多的人将办公桌移到家里或办公室。但是&#xff0c;如何选择适合你的办公桌可能是个挑战。不同的工作需要和工作空间大小会影响你的选择。下面是一些简单的建议&#xff0c;帮助你找到适合你的办公桌&#xff0c;提高工作效率。 首先&…

使用pytorch处理自己的数据集

目录 1 返回本地文件中的数据集 2 根据当前已有的数据集创建每一个样本数据对应的标签 3 tensorboard的使用 4 transforms处理数据 tranfroms.Totensor的使用 transforms.Normalize的使用 transforms.Resize的使用 transforms.Compose使用 5 dataset_transforms使用 1 返回本地…

Android 基于 J2V8 运行 JavasScript 实践

V8 引擎是由 Google 开源的 JavaScript 引擎&#xff0c;Chrome 就是基于 V8 开发&#xff0c;V8 是跨平台的&#xff0c;J2V8 基于 V8 进行开发&#xff0c;使得 js 代码能够在 Android 平台上脱离 WebView 运行。目前&#xff0c;也有很多关于 Android J2V8 的文章&#xff0…