在渗透的侦查踩点阶段,进行全面的信息收集对后面实施渗透的尝试尤为重要

通过子域名爆破、搜索引擎查询等方式收集目标资产信息之外,对于开放443端口HTTPS服务的网站,我们可通过HTTPS证书来收集子域名和兄弟域名

例如通过浏览器证书功能查看详细信息在 一栏,可以发现不少该使用证书授权的域名:

DNS Name=developers.weixin.qq.com
DNS Name=ad.weixin.qq.com
DNS Name=game.weixin.qq.com
DNS Name=as.weixin.qq.com
DNS Name=hk.open.weixin.qq.com
DNS Name=open.weixin.qq.com
DNS Name=api.weixin.qq.com
DNS Name=sz.api.weixin.qq.com
DNS Name=long.open.weixin.qq.com
DNS Name=mp.weixinbridge.com
DNS Name=servicewechat.com
DNS Name=hk.mp.weixin.qq.com
DNS Name=sz.mp.weixin.qq.com
DNS Name=hk.api.weixin.qq.com
DNS Name=sh.api.weixin.qq.com
DNS Name=sz.open.weixin.qq.com
DNS Name=a.weixin.qq.com
DNS Name=mp.weixin.qq.com

下面的分享就是编写一款自动获取证书中兄弟域名的C#小工具

首先通过Socket连接服务器HTTPS服务下载证书

TcpClient client = new TcpClient()
client.Connect(“mp.weixin.qq.com”, 443);

//使用SslStream类存储流
SslStream ssl = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
try
{
ssl.AuthenticateAsClient(host);
}
//catch (AuthenticationException e)
catch (Exception e)
{
Debug.WriteLine(e.Message);
ssl.Close();
client.Close();
return cert;
}

//拿到证书,关闭
cert = new X509Certificate2(ssl.RemoteCertificate);
ssl.Close();
client.Close();

通过调试断点,可以看到cert的各属性,里面没有DNSName相关的

通过搜索我们发现X509Certificate2. GetNameInfo方法可以获取到证书的DNSName,调用方法如下

cert.GetNameInfo(X509NameType.DnsName, false)

运行程序,得到DnsName

Console.WriteLine(“{0}”, cert.GetNameInfo(X509NameType.DnsName, false));

然而我们发现使用微软自带的类操作证书只能读到诸多“使用者可选名称”中的一个值(最后一个),需要换个思路。

进一步发掘,在X509Certificate2. Extensions对象中存储有证书的扩展信息,

遍历出来观察一下

foreach (X509Extension ext in cert.Extensions)
{
Console.WriteLine(“Oid {0} {1} {2}”, ext.Oid.FriendlyName, ext.Oid.Value, Encoding.Default.GetString(ext.RawData));
}

在证书扩展Oid.FriendlyName 为“使用者可选名称”的RawData中,存储着DNS Name值的列表,从这里可以获取到证书关联的所有兄弟域名的数据。

但是这个列表数据中间使用了不可见字符分隔,通过将RawData转码(ASCII解码),中间的分隔符为82开头,后面的两位表示域名的长度

如developers.weixin.qq.com  长度为24,转为16进制就是18

下面来处理这个问题,方法如下

if (ex.Oid.FriendlyName == “使用者可选名称”|| 
ex.Oid.FriendlyName == “Subject Alternative Name”)

//为了兼容系统中英文
{
Console.WriteLine(“{0}”, ext.Oid.FriendlyName + ” – ” + ex.Oid.Value + ” | ” + 
Encoding.Default.GetString(ext.RawData));
string dnsnames = “”;


//由于RawData是Byte数组,这里逐个转为Hex 16进制数据
for (int i = 0; i < ext.RawData.Length; i++)
{
dnsnames += ext.RawData[i].ToString(“X2”);
}
Console.WriteLine(dnsnames);

//首先通过正则切割,这里正则表达式为”82dw”因为域名长度有限Hex的首位不会是字母,而用”82ww”则会误报
string[] dnsname = Regex.Split(dnsnames, @”82dw”, RegexOptions.None);

//逐个还原域名
foreach (string dns in dnsname)
{
if (dns.Length > 6)
{

//16进制转换为字符串
var arr = Regex.Matches(dns, @”ww”).Cast<Match>
().Select(m=>m.Value);
foreach (var m in arr)
{
char c = (char)Int32.Parse(m, 
System.Globalization.NumberStyles.HexNumber);Console.Write(c);
}
Console.WriteLine(“”);
}
}
}

得到完整的域名列表

这样就没问题了,一个简单的功能实现分享给大家,希望和大家共同进步。

附源码+程序:https://pan.baidu.com/s/1nwa2VyD,可供下载

源链接

Hacking more

...