golang 服务检查收集器 - #poc

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golang 服务检查收集器 - #poc相关的知识,希望对你有一定的参考价值。

package main

import (
	"net/http"
	"sync"

	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.Default()

	r.GET("/service/check", ListChecks)
	r.POST("/service/check", AddCheck)
	r.DELETE("/service/check/:service/:host", RmCheck)

	r.Run(":8080")
}

type ServiceCheck struct {
	Timestamp int    `json:"timestamp"`
	Service   string `json:"service"`
	Hostname  string `json:"hostname"`
	Status    int    `json:"status"`
	Output    string `json:"output"`
}

var (
	mutex  sync.RWMutex
	checks = map[string]ServiceCheck{}
)

func ListChecks(c *gin.Context) {
	mutex.RLock()
	defer mutex.RUnlock()

	c.JSON(http.StatusOK, checks)
}

func AddCheck(c *gin.Context) {
	mutex.Lock()
	defer mutex.Unlock()

	var check ServiceCheck
	if !bindJSON(c, &check) {
		return
	}

	checks[check.Service+"@"+check.Hostname] = check

	c.JSON(http.StatusOK, check)
}

func RmCheck(c *gin.Context) {
	mutex.Lock()
	defer mutex.Unlock()

	service := c.Param("service")
	hostname := c.Param("hostname")

	if _, ok := checks[service+"@"+hostname]; !ok {
		c.JSON(http.StatusBadRequest, gin.H{
			"message": "No check found for " + service + "/" + hostname,
		})
	}

	delete(checks, service+hostname)

	c.JSON(http.StatusNoContent, nil)
}

func bindJSON(c *gin.Context, obj interface{}) bool {
	err := c.BindJSON(&obj)
	isError := err != nil
	if isError {
		c.JSON(http.StatusBadRequest, gin.H{
			"message": err.Error(),
		})
	}
	return !isError
}

hash碰撞POC

hash碰撞POC:

该类型漏洞POC编写过程难点有二:

一. hash碰撞数据的产生或收集

二. 使用responseTime来判断是否存在hash,如何精确的得到

三. 如何估算出服务器的处理/响应时间,以用来判断是否存在漏洞。

 

github能找到hash碰撞的POC,使用python编写的

该POC生成hashcollision的算法思想:

1. 取一个随机数n,由n生成 k维的笛卡尔积

可以理解为k维的数组,如array[AA][BB][CC],计算后为“AABBCC”

2. 将所有数组的值取出来,设定hash算法,计算每个值在该hash算法下的hash值

3. 随机取一个数的hash值,再取出其他与该hash值相同的数,组成hash碰撞的payload

将payload放入POST数据中,使用socket发包,由发包后和接受完整数据后的时间差得出响应时间。

 

该POC的弊端在于,如果只是做检测,没必要每次都生成payload,只需要生成一次payload,就可以多次测试了。

另一个难点,如何准确的判断responseTime。

这一点以burpsuite的时间为准

以自己搭建的内网测试环境,代码为

 

<?php
 $startTime = microtime(true);
$rest = file_get_contents("php://input");
$a=json_decode($rest,true);
?>

 

burpsuite中,不发送POST数据时间为10ms左右,发送正常的json数据时间为 100ms左右

而自己编写的代码,发送正常json数据数据时

1. 计算requests前后的时间差,会有很大的误差,发送数据的时间和接受的时间都会计入在内。而发送的payload较大,通常达到1M,所以时间上有误差。得出时间1300ms左右

2. requests的elapsed.total_seconds()计算得出的时间会比第一种方法少,为800ms左右

3. github上的POC,使用socket发送数据,截取recv前后的时间差, 时间在1200ms左右。

很难接近burpsuite得出的时间,我想主要是request将发送数据的时间计算在内了吧。

由此,可以估算发送数据的时间

time=(发送正常json的时间-不发送数据的时间)  ,再 *4/5 (*4/5是估算去除掉服务器处理正常json时的处理时间)

 

设置判断存在碰撞漏洞的时间线 limit为  

limit=发送正常json数据的时间-time(发送数据的时间)

在每一个payload发送的时间上减去  n/m*time()按发送数据的大小比例估算出的发送数据的时间)

 如果超过划定的时间线,则可能为hash碰撞漏洞

 

经测试,可判断出自己搭建的环境上的hash碰撞漏洞。

测试仍然受网络速度影响。

存在许多瑕疵,仍然可以改进。

比如增加数据量,让服务器处理碰撞数据的时间倍增,则发送数据的时间比重缩小,影响降低。

 

最后贴上测试代码,其中的payload明天再贴上

payload数据还可以改进增加。

#coding:utf-8
import time
import requests
import jsonToString
import pycurl

import thread

class Test:
        def __init__(self):
                self.contents = ‘‘
        def body_callback(self,buf):
                self.contents = self.contents + buf

def timeOfRequest(url,data):
    start=time.time()
    #print data
    try:
        q=requests.post(url,data)
        #print q.content
        return q.elapsed.total_seconds()
    except:
        pass
    end=time.time()
    return 1000000
    #return (end-start)

def test_gzip(input_url,data):
        t = Test()
        #gzip_test = file("gzip_test.txt", ‘w‘)
        c = pycurl.Curl()
        c.setopt(pycurl.WRITEFUNCTION,t.body_callback)
        c.setopt(pycurl.ENCODING, gzip)
        c.setopt(pycurl.URL,input_url)
        c.setopt(pycurl.POSTFIELDS,  data)
        c.perform()
        http_total_time = c.getinfo(pycurl.TOTAL_TIME)
        return http_total_time
        http_size = c.getinfo(pycurl.SIZE_DOWNLOAD)
        print conn_time pre_tran start_tran total_time
        print "%f %f %f %f"%(http_conn_time,http_pre_tran,http_start_tran,http_total_time)

#print timeOfRequest(url,"normal")
def control(url,string,data):
    #print string
    return test_gzip(url,data)
    #time=timeOfRequest(url,data)
    #print time
    #if time > 26:
    #    print "Probably have hashcollistion"

def show(times,limit):
    for name in times:
        if times[name]>limit:
            print "Probably have HashCollision==>",
        print name+":",
        print times[name]

def check(url):
    nulldata=open("null.txt","r").readline()
    normaldata=open("normal.txt","r").readline()
    phpjsondata=open("phpjson.txt","r").readline()
    javajsondata=open("javajson.txt","r").readline()
    phpdata=jsonToString.jsonToString(phpjsondata)
    javadata=jsonToString.jsonToString(javajsondata)

    times={}

    print "NO THREAD"
    times["null"]=control(url,"null",nulldata)
    time.sleep(1)
    times["normal"]=control(url,"normal",normaldata)  #利用normal,算出发送大量数据的时间,所占比例约为 (normal-null)*4/5
    time.sleep(1)


    trantime=(times["normal"]-times["null"])*4/5
    base=times["normal"]-trantime
    limit=base*13
    print limit


    times["phpjson"]=control(url,"phpjson",phpjsondata)-1.36*trantime
    times["php"]=control(url,"php",phpdata)-1.36*trantime
    times["javajson"]=control(url,"javajson",javajsondata)-2.3*trantime
    times["java"]=control(url,"java",javadata)-2.3*trantime

    show(times,limit)


if __name__ == __main__:
    url="http://10.252.223.15/test.php"
    check(url)
    # while 1:
    #     pass

 

以上是关于golang 服务检查收集器 - #poc的主要内容,如果未能解决你的问题,请参考以下文章

hash碰撞POC

所有可用的和最新的CVE及其PoC合集

网站指纹收集及其利用方式

Python十几行代码获取db库新增的poc

golang 一个简单的golang Web服务器,具有基本的日志记录,跟踪,运行状况检查,正常关闭和零依赖关系

golang 一个简单的golang Web服务器,具有基本的日志记录,跟踪,运行状况检查,正常关闭和零依赖关系