poc学习part1
PoC(全称: Proof of Concept), 中文译作概念验证。即漏洞验证程序,而漏洞利用程序即为Exp。因为python的简单易懂加上类库比较丰富,所以首先Python来进行编写。
POC注意事项
dvwa的sql注入poc
这个是要自己在id参数里面添加’
根据返回结果才可以验证出来
1 | import re |
这就是一个简单的poc,可用来验证dvwa中cookie类sql注入,程序很简单但却能验证是否存在漏洞
切入
这里提到了sql注入,那就以SQL注入为切入点,恰好sql注入也是很多人入门的一个漏洞。编写之前我们要了解下漏洞原理,以及漏洞的分类
注入原理
是发生于应用程序与数据库层的安全漏洞。简而言之,是在输入的字符串之中注入 SQL 指令,在设计不良的程序当中忽略了检查,那么这些注入进去的指令就会被数据库服务器误认为是正常的 SQL 指令而运行,因此遭到破坏或是入侵
注入分类
下面这些个分类是我个人的见解。
注入点类型分类
数字型注入点
形如http://xxx.com/news.php?id=1这种形式,其注入点 id 类型为数字,所以叫数字型注入点。这一类的 SQL 语句原型大概为
select * from 表名 where id=1
。字符型注入点*
形如http://xxx.com/news.php?name=admin这种形式,其注入点 name 类型为字符类型,所以叫字符型注入点。这一类的 SQL 语句原型大概为
select * from 表名 where name='admin'
。注意多了引号。搜索型注入点*
这类注入主要是指在进行数据搜索时没过滤搜索参数,一般在链接地址中有“keyword=关键字”,有的不显示在的链接地址里面,而是直接通过搜索框表单提交。
此类注入点提交的 SQL 语句,其原形大致为:*
select * from 表名 where 字段 like '%关键字%'
。数据提交方式分类
这种分类其实只是 HTTP 传递数据的方式不同,严格来讲和 SQL 没多大关系,但是在编写 PoC 的时候,这会影响到我们的代码中发送数据的形式
GET 注入
提交数据的方式是 GET , 注入点的位置在 GET 参数部分。比如有这样的一个链接
http://xxx.com/news.php?id=1
, id 是注入点。POST 注入*
使用 POST 方式提交数据,注入点位置在 POST 数据部分,常发生在表单中。
Cookie 注入*
HTTP 请求的时候会带上客户端的 Cookie, 注入点存在 Cookie 当中的某个字段中。
HTTP 头部注入*
注入点在 HTTP 请求头部的某个字段中。比如存在 User-Agent 字段中。严格讲的话,Cookie 其实应该也是算头部注入的一种形式。因为在 HTTP 请求的时候,Cookie 是头部的一个字段。
执行效果分类
这个分类也是 sqlmap 所支持的注入模式,这个分类的依据也是后面我们用 PoC 判断是否存在注入的依据。
基于报错注入
这一类的也叫有回显注入,页面会返回错误信息,或者是把注入语句的结果直接返回在页面中。
基于布尔的盲注*
根据返回页面的结果判断构造的 SQL 条件语句的真假性
基于时间的盲注*
当根据页面返回的内容不能判断出任何信息时,使用条件语句查看时间延迟语句是否执行,也就是看页面返回时间是否增长来判断是否执行。
例子分析:
这里因为我是参考着文章进行学习,但是原有漏洞的分析文章已经无了,我先把链接挂在这
https://mp.weixin.qq.com/s/Ef9Bmp53sEuDLv3KwqdI-g
这里poc编写的漏洞是CmsEasy 5.5 UTF-8 20140802/celive/live/header.php SQL注入漏洞(wooyun-2010-070827)
一般来说如果漏洞的分析文章已经给出了具体的利用方法,我们就可以不关注整个漏洞的成因和原理,直接去看漏洞的复现方式,获得payload和url即可
url:http:/xxx.com/celive/live/header.php
post:xajax=LiveMessage&xajaxargs[0][name]=1’,(SELECT 1 FROM (select count(*),concat(floor(rand(0)*2),(select concat(username, 0x23,password) from cmseasy_user where groupid=2 limit 1))a from information_schema.tables group by a)b),”,”,”,’1’, ‘127.0.0.1’, ‘2’)#
一般不推荐使用在线站点测试,懂的都懂,这里建议本地搭建或者寻找docker测试
该漏洞的注入点在 POST 数据部分,我们需要发起一个 POST 请求,我们选择 Firefox 浏览器和 HackBar 插件。填上目标 url 和 payload,然后发送。可以看到返回页面报错,而报错信息中出现了 cmseasy_user 表中的数据
既然能够成功复现,那就可以尝试poc的编写
编写
编写之前,poc总是单独成体,那如果是多个poc或者是我们需要利用多个poc就应运而生了框架来管理,但是这里我们先用无框架poc编写
根据文章我们可以知道,payload是可以证明漏洞存在的,但是如果直接将poc运用到一些扫描类的产品中,这些肯定是不允许的,所以我们需要遵守几个原则
- 无损扫描
也就是要求不能对目标服务器有任何危害,只要证明目标存在漏洞,所以我们只要能证明可以执行 SQL 指令就好了
类似这种
- 减少误报漏报
误报和漏报两者相伴相随。如果误报率低了,那么相对的,漏报率就跟警察叔叔抓坏人,一抓一个准,但是这样的话,肯定就会有很多漏网之鱼了。所以就需要找到一个平衡点。
一般来说,大部分人追求的原则是可以漏报,但不能误报
所以就要求我们判断的字符在正常的页面要尽可能不会经常出现,比如可以输出一串md5的值到页面
为什么选 md5 呢,因为 mysql 里面有 md5 这个函数,写起来简单,要是像 Oracle 数据库里面没 md5 这个函数怎么办呢?我们有 char() 函数(Oracle 里面是 chr()),可以把 ASCII 码转化成字符串,手动多打几个随机字符就好啦
根据以上原则,我们把payload进行修改
url:http:/xxx.com/celive/live/header.php
post:xajax=LiveMessage&xajaxargs[0][name]=1’,(SELECT 1 FROM (select count(*),concat(floor(rand(0)*2),(select md5(233)))a from information_schema.tables group by a)b),”,”,”,’1’, ‘127.0.0.1’, ‘2’)#
md5(233) 的值就是 e165421110ba03099a1c0393373c5b43
ok,基本复现成功,可以写poc了。
目的是写一个能发送post请求的,然后返回我们设置的md5值
刚开始我们以最最简单的html形式来尝试实现:
1 | <!DOCTYPE html> |
将上面的html代码,用浏览器打开,点击提交按钮,就能看到效果了。
所以poc的实现形式也是多种多样的,以上html代码也是poc
因为poc是证明漏洞存在的代码,所以代码只要能实现的话,就没有语言之分,看你个人喜欢或者习惯而已。
如果是以Python形式实现就是这样:
原链接使用python2和urllib包进行实现,我这里是python3环境稍加变动而已,不影响
1 | import requests |
下面简单讲一下这个代码做了什么:
main 方法里面大概处理了一下用户的输入
verify 方法里面先是拼接了一下要发送的目的 url, 然后把 post_data(也就是我们的 Payload)发送到目的 url, 最后再处理了一下服务端的响应页面。其实整个过程就像是我们自己用浏览器去手工验证一样,只不过实行了自动化改进。
当然上述的代码,实际运行的时候还是需要改进的,毕竟有很多细节的地方还需要再完善。比如说我们的输入部分每个都需要手动输入,假设有很多个 PoC, 这很麻烦了吧,而且不是每个人都能想到那么多特殊情况。另外输出结果的时候,就用了一个 print , 显然这样的输出很不友好,而且一个 PoC 还不能支持批量扫描,如果你想加载多个 PoC 去扫描多个目标的时候,效率就很低下。
所以应运而生了Poc框架,能够有效避免一些重复工作(当然你编程能力很强能够自己改动也是可以的)