红队C2研发日记2:C2 Server端的认证实现
这节来实现一下c2 中的server端代码,也就是TeamServer,这种基于c/s架构的,应该是目前主流的C2通信设计架构。
Server端的话使用.net8 SDK 以及 asp.net web api来完成,这样的话是可以实现跨平台部署的。
同时这次的Server打算秉持一个轻量级,易部署,可分布式的一个思想,然后我们的Client可以同时连接多个Server而无需Client的多开。
(文章内容仅用于红队开发研究学习)
开发环境
开发包:.NET8 SDK。
IDE:asp.net webapi 不涉及UI,直接用VS搞就可以了。
代码不会很详细,大概过程思路展示一下
创建监听
我们这里首先处理的是server和client直接的交互,还不涉及到agent,首先创建一个https的服务端,并监听端口:
var builder = WebApplication.CreateBuilder();
X509Certificate2 cert = new Certificate().GenerateSelfSignedCertificate(new RandomShit().GenerateStringR(8));
builder.WebHost.UseKestrel(options =>
{
options.Listen(IPAddress.Any, port, ListenOptions =>
{
ListenOptions.UseHttps(cert);
});
});
builder.Services.AddControllers();
var app = builder.Build();
app.UseAuthentication();
app.UseRouting();
app.UseAuthorization();
app.MapControllers();
app.RunAsync();
上述就是一个最简单的创建HTTP服务的代码。第二行是用来生成自签名证书的,用于和Client的ssl通信证书。
引入JWT
端口创建好了,我们client登录一般是需要认证的,认证后server应该会下发token,然后后续client所有的操作,比如对agent下发命令,都应该携带token进行认证。
这里token我可以用JWT来实现,在asp.net 中引入配置一下:
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.SaveToken = true;
options.RequireHttpsMetadata = true;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Credential._Key))
};
});
配置认证API
Client初次连接Server需要一个API来实现认证的过程,校验登录密码,并返回结果。
一般在asp.net webapi开发中类似过程都被称为是controller的部分(MVC开发模式),我这里创建一个类,并继承ControllerBase,因为我们要返回http状态。
我们这里通过属性指定POST请求方式,同时指定API路由:
[ApiController]
publicclassIdentityAuthenticationController:ControllerBase
{
[HttpPost(ServerRouteMap.ServerIdentityRoute)]
public IActionResult ServerIdentity([FromBody] identityRequest request)
{
if (new IdentityViewModel().IdentityServerPass(request.password))
{
var token = new jwt().GenerateJWTToken(request.identityName);
var res = JsonConvert.SerializeObject(new identityResponse{
identityResult = true,
IV = aes.IV,
token = token,
ServerID = ServerIdentificationdata.ServerID,
});
return Ok(res);
}
return Forbid();
}
}
[HttpPost(ServerRouteMap.ServerIdentityRoute)]
HttpPost属性指定了下面的API只接收POST请求,ServerRouteMap.ServerIdentityRoute
就是一个字符串用来指定API路由,比如"/api/identity"
。
上面的代码中,IdentityServerPass
是一个校验密码的过程,如果校验通过的话,则会进入到GenerateJWTToken
生成JWT的过程,生成完毕,会同结果一起返回给Client,如果验证失败,返回403 forbid即可,这里的OK(),Forbid()函数都是继承自ControllerBase的。
Client认证
客户端认证其实就是个Http请求的过程:
publicstaticasync Task<string> WebReqPost(string host,string port,string url, string postData)
{
var handler = new HttpClientHandler
{
// 忽略证书校验:
ServerCertificateCustomValidationCallback =
(HttpRequestMessage message, X509Certificate2 cert, X509Chain chain, SslPolicyErrors sslErrors) => true
};
HttpClient client = new HttpClient(handler);
var res = await client.PostAsync($"https://{host}:{port}{url}", new StringContent(postData,Encoding.UTF8, "application/json"));
if (res.StatusCode == System.Net.HttpStatusCode.OK)
{
var content = await res.Content.ReadAsStringAsync();
return content;
}
returnnull;
}
这里我们设定了不校验服务端证书的有效性,因为我们的证书是自签名,postData
里面携带了我们的认证信息,比如密码,至于传输形式可以自定义,你可以用json也可以用别的,这里涉及到网络请求尽量使用async/await
异步,避免卡顿。
大概的流程就是这样,要设计的完整一点,代码还是很多的,尤其是在数据通信的过程,比如还要涉及到加解密等等,C2开发的核心其实就是网络通信。
演示
Demo视频中添加了很多东西,比如连接页面,以及登录成功后,模拟同步的Agent数据等等,真实的更加完备的东西,后面陆续开发.... (代码在下面圈子)
推荐阅读
这是一个纯粹,开放,前沿的技术交流社区,成员主要有互联网大厂安全部门任职的成员,乙方红队专家,以及正在学习入门的小白等,目前主题主要以红队研发为主(有经验的都知道是什么意思),以及其他涉及到红队进攻侵入性技术,如果你想学习技术,认识不同的人或者寻求一个机会之类的,可以来看看👇👇👇
欢迎加入交流圈
扫码获取更多精彩
原文始发于微信公众号(黑晶):红队C2研发日记2:C2 Server端的认证实现
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论