首页 渗透工具 正文
  • 本文约8949字,阅读需45分钟
  • 491
  • 0

Sec-Tools

?Sec-Tools

Sec-Tools Sec-Tools

如果你觉得本项目还不错的话,请给一个❤️Star❤️吧,感谢感谢?

Gitee:https://gitee.com/jwt1399/Sec-Tools

项目介绍 - 详细介绍 - 版本记录 - 项目部署 - TODO - 赞助

声明

因近期多人反应有人将此项目作为商品进行售卖,特作如下声明!!!

  • 1.本项目版权归本作者所有,未授权不能商用,不能作为盈利使用;
  • 2.本项目仅供学习,测试,交流使用,勿用于非法用途;
  • 3.未经本作者允许不得转载本项目内容,否则将视为侵权;
  • 4.转载或者引用本项目内容请注明来源及作者,否则将视为侵权;
  • 5.请使用者遵守《中华人民共和国网络安全法》,勿用于非授权测试,如作他用所承受的法律责任一概与作者无关,下载使用即代表使用者同意上述观点;
  • 6.对于不遵守此声明或者其他违法使用本项目内容者,本人依法保留追究权等。

?项目介绍

系统简介

本项目命名为Sec-Tools,是一款基于 Python-Django 的多功能 Web 应用渗透测试系统,包含漏洞检测、目录识别、端口扫描、指纹识别、域名探测、旁站探测、信息泄露检测等功能。

项目功能

本系统通过旁站探测域名探测功能对待检测网站进行资产收集,通过端口扫描指纹识别目录识别信息泄露检测功能对待检测网站进行信息收集,通过收集的信息分析评估网站存在哪些安全隐患,然后使用漏洞检测功能揭示网站存在的漏洞以及危害等级并给出修复建议。通过这一系列的步骤,可以对Web应用进行全面检测,从而发现网站存在的安全隐患,因此用户可以针对相应的网络威胁做出应急响应,进而提升站点的安全性。

相关技术

名称 Python Django SQLite ECharts Tabler Layer Docsify SimpleUI Boostrap Table
版本 3.7.0 3.1.4 3.35.2 5.0.1 1.0.0 3.2.0 4.11.6 2021.1.1 1.18.2

项目首页

首页采用 ECharts 对漏洞扫描的漏洞等级、指纹识别组件、安全导航数据做了可视化图表展示,图表的风格没有统一,凑合看吧?

仪表盘页

身份验证

新用户想要使用系统功能必须要注册登录,游客只能访问部分页面。本系统有普通用户和超级用户。普通用户可以使用本系统的所有功能,但是不能登录后台管理系统。超级用户不仅可以使用所用功能还可以登录后台管理系统中所有的用户权限和数据。

设计思路: 登录和注册模块在 Django 自带的认证模块的基础上进行实现,因此在后台-->用户与授权就可对注册用户进行权限分配和相应管理。我们使用 Django 自带的数据库 SQLite 来存放账户信息,重构了数据库表auth_user表,增加了用户邮箱字段,auth_user 中密码字段是加了 salt 的 sha256 值再经过 base64 编码之后的值,保障了用户的信息安全。

登录页
注册页

重设密码功能调用第三方包 django-password-reset 进行实现

步骤一
步骤二

漏洞检测

该模块主要是对目标Web系统进行安全漏洞扫描,包括SQL注入、跨站脚本攻击(XSS)、弱密码、中间件漏洞。中间件漏洞扫描包括对Weblogic、Struts2、Tomcat 、Jboss、Drupal、Nexus的已知漏洞进行检测,用户提供目标URL并选择CVE漏洞编号。

设计思路

该模块的全扫描、SQL注入漏洞扫描、XSS漏洞扫描、弱口令扫描、仅爬取是调用 AWVS API 进行实现。中间件漏洞扫描是基于脚本模拟网络请求实现。根据漏洞形成的原因,生成一些测试 payload 发送到目标系统,再由返回的状态码和数据来判断payload是否有效。

实现效果

漏洞扫描

点击扫描目标跳转到漏洞结果页:

漏洞结果

再点击扫描目标的跳转到漏洞详情页:

漏洞详情

详细实现

添加扫描目标

漏洞扫描最开始的工作是添加扫描目标到 AWVS 的扫描队列中。AWVS 提供了一个 API 接口: /api/v1/targets,使用 POST 请求, POST 请求参数为:{"address":"XXXX.XXXX.XXXX","description":"xxxx","criticality":"10"}

当目标添加成功后会返回一个 target_id ,这个值在所有扫描中是唯一的。通过 target_id 判断目标是否添加成功。添加完目标后并没有开始扫描,需要使用另一个 API 接口:/api/v1/scans,使用 POST 请求,传入刚刚添加目标生成的 target_id 和用户选择的扫描类型,POST 请求参数为:{"target_id":"xxxxxxx","profile_id":"xxxxxxx"}。开始扫描将会返回状态码200。

使用 Python 的第三方库 requests 来实现 API 接口访问。核心代码如下:

#Target: POST请求/api/v1/targets
try:
    #data包含目标URL和类型,auth_headers包含API_KEY
    response = requests.post(targets_api, auth_headers, data, False)
result = response.json()
target_id = result.get('target_id')
    return target_id
except Exception:
return None
#Scan: POST请求/api/v1/scans
try:
    response = requests.post(scan_api, data, auth_headers, False)
    status_code = 200
except Exception:
status_code = 404
return status_code
 

API 接口已经实现,还需要获取用户输入的数据。由于本系统是基于 Django 实现的,所以使用 HTML+JavaScript 提供用户界面和接受和发送数据到后端,后端使用 Python 实现。首先在 urls.py 里面加入添加访问路径

path('vuln_scan', views.vuln_scan, name='vuln_scan')

在 views.py 中定义 vuln_scan() 函数接收前端的用户输入,并调用已经写好的 API 函数。用户输入的 url 为扫描的目标,扫描类型包括SQL注入、XSS漏洞、弱口令和全扫描,其中全扫描就是扫描所有类型的漏洞,如果添加成功后返回的 target_id 不是 None,说明添加成功,就可以开始调用开始扫描的 API,开始扫描后返回状态码,为200则开始扫描,返回成功否则返回失败。核心代码如下:

@csrf_exempt
def vuln_scan(request):
    #通过POST请求获取用户输入的URL和扫描类型
    url = request.POST.get('ip')
    scan_type = request.POST.get('scan_type')
    t = Target(API_URL, API_KEY)
    #将目标URL添加到扫描队列中
    target_id = t.add(url)
    #如果target_id不为None,则开始扫描
    if target_id is not None:
        s = Scan(API_URL, API_KEY)
        status_code = s.add(target_id, scan_type)
        if status_code == 200:
            return success()
    return error()
 

最后使用 JavaScript 来实现发送用户输入的数据,选择通过 POST 方法发送数据,并在发送之前判断用户输入的合法性,核心代码如下:

function get_scan_info(ip , scan_type) {
#使用POST请求发送用户输入
        $.post('/vuln_scan', {
            ip: ip ,
            scan_type: scan_type
        }, function (data) {
            if (data.code !== 200) {
                ......
            } else {
                ...... 
            }
           ......});
    }
var domain = $('input[name=scan_url]').val();
#使用循环判断用户选择的扫描类型
for(var i=0; i<document.getElementsByName("scan_type").length; i++) {
    if (document.getElementsByName("scan_type")[i].checked) {
      var scan_type=document.getElementsByName("scan_type")[i].value;
    }
}
if(domain){
    get_scan_info(domain,scan_type)
}else{
    ......
}
 

总体来说,通过上述的代码实现,实现了将用户输入通过 JavaScript 传输给后台,后台接收数据后将调用 AWVS API,然后 AWVS 开始根据用户输入开始扫描目标 URL,扫描结束后将结果保存在数据库中。实现效果如下:

获取扫描结果

在上一小节中,将目标扫描的结果保存到数据库中,我们需要得到所有的扫描目标,‘/api/v1/scans‘,请求方式为 GET,请求成功后会返回所有扫描目标的信息,利用这个 API 可以实现展示所有扫描目标。要实现展示每个扫描目标的所有漏洞的功能,需要按照 target_id 来在所有扫描目标中搜索。AWVS 也提供了相应的 API,我们需要用到的 API 为:/api/v1/vulnerabilities

?q=severity:{int};criticality:{int};status:{string};cvss_score:{logicexpression};cvss_score:{logicexpression};target_id:{target_id};group_id:{group_id}。请求方式为 GET。利用 target_id 搜索每个扫描目标。这也解决了漏洞细节页面的 URL 问题。当使用 target_id 搜索扫描目标成功时将会返回这个目标的所搜漏洞信息,包括这个目标包含的漏洞个数、每个漏洞的危险等级、扫描时间、扫描类型、扫描状态等信息。

具体实现步骤和添加扫描目标大体相似,首先第一步使用 requests 来实现 API 请求。核心代码如下:

#获取所有扫描目标
response=requests.get(scan_api, self.auth_headers, False) 
scan_response=response.json().get('scans')
for scan in scan_response:
   scan['request_url'] = request_url
   scan_list.append(scan)
return scan_list
#搜索状态为“open“,对应target_id的扫描目标
vuln_search_api=f'{vuln_api}?q=status:{status};target_id:{target_id}'
try:
#使用get方式请求
    response = requests.get(vuln_search_api, auth_headers, False)
#返回搜索结果目标的所有漏洞信息
    return response.text
except Exception:
    return None
 

在 urls.py 中加入用户访问的 url ,这个需要提供一个 target_id 方便后续功能的实现,先获取所有目标的target_id,然后使用循环将所有 target_id 加入到 urlpatterns 列表中。因为在 Django 中 views 函数通常只能使用一个 request 参数,由于这里需要将 target_id 传入到 views 函数中,使用正则匹配的 “(?P<target_id>.*)$” 接收传入的 target_id,在 views 里对应函数的第二个形参名必须和 <> 里的值一致才有效。核心代码如下:

path('vulnscan', views.vulnscan, name="vulnscan"),
for target_id in target_ids:
      #使用正则匹配获取第二个参数:taget_id
urlpatterns.append(url(r'^vuln_result/(?P<target_id>.*)$', views.vuln_result, name='vuln_result/'+target_id))
 

在 views.py 里定义函数 vulnscan(request) 获取所有对应的目标漏洞信息。使用 API 得到返回的漏洞危险等级、扫描目标URL、每个漏洞唯一标识的 vuln_id、扫描类型、扫描处理时间,API 返回的扫描处理时间不是标准的时间格式,使用正则匹配的方式,将其转换为 “%Y-%m-%d %H:%M:%S“ 的格式,再定义函数 vuln_result(request,target_id),根据 target_id 获取扫描目标中所有漏洞信息,包括存在漏洞的URL、漏洞类型、状态和处理时间等信息。核心代码如下:

@login_required
def vuln_result(request, target_id):
    d = Vuln(API_URL, API_KEY)
    data = []
    vuln_details = json.loads(d.search(None,None, "open", target_id=str(target_id)))

    id = 1
    for target in vuln_details['vulnerabilities']:
        item={
            'id': id,
            'severity': target['severity'],
            'target': target['affects_url'],
            'vuln_id':target['vuln_id'],
            'vuln_name': target['vt_name'],
            'time': re.sub(r'T|\..*$', " ", target['last_seen'])
        }
        id += 1
        data.append(item)
    return render(request,'vuln-reslut.html',{'data': data})
 

在这个子功能中,前端的数据展示使用的是 Bootstrap Table。这个模板有很多实用的功能,比如表格的搜索功能、分页展示功能等等,增加了用户体验。表格的数据在 HTML 中使用双花括号来接收,在 views.py 函数中返回的到相应的 HTML 页面时,将 data 字典一起返回。这样的返回方式可以将使用字典中的 key 值获取对应的 values 值。还可以是使用 if-else、for 等语句来分类展示数据。核心代码如下:

{% for item in data %}
……………
# 这个只展示了扫描目标列,其他列类似 
<a href="/vuln_detail/{{ item.vuln_id }}"> {{ item.target }}</a>
……………
{% endfor %}
 

最后实现的效果如下图所示,根据每个扫描状态不同有不同的显示,使用红黄蓝绿来分类高危、中危、低危、info等级的漏洞。最后展示了扫描的处理时间。

表格中扫描目标列可以点击进入查看目标的所有漏洞信息,如下图所示,展示了特定的扫描目标每个漏洞的危险等级、存在漏洞的URL、漏洞的类型。 

获取漏洞细节

在实现漏洞扫描和结果展示后,还需要获取每个漏洞的细节。包括导致漏洞的请求参数、测试的 payload、数据请求包、简要的修复建议等等。因为每个漏洞也存在一个唯一的标识 vuln_id,可以根据这个值查询指定漏洞的所有信息。使用的 API 为:/api/v1/vulnerabilities/{vuln_id},请求方式为 GET。

同样地,首先使用 requests 来实现 API 的调用,传入 vuln_id 来查询指定漏洞的所有信息,代码如下:

#获取指定漏洞的相关信息
def get(self, vuln_id):
    vuln_get_api = f'{self.vuln_api}/{vuln_id}'
    try:
        #使用GET请求将vuln_id传给API,结果以json格式返回
        response = requests.get(vuln_get_api, auth_headers, False)
        return response.json()
    except Exception:
        return None
 

在 urls.py 中添加漏洞细节的 url,这里与上一节展示扫描目标的所有漏洞类似,都用正则匹配的形式接收 views.py里函数的第二个形参,但是这里不在使用 target_id 而是使用 vuln_id。代码如下:

for vuln_id in vuln_ids:
    urlpatterns.append(url(r'^vuln_detail/(?P<vuln_id>.*)$', views.vuln_detail, name='vuln_detail/' + vuln_id))
 

在 views.py 里面定义 vuln_details(request,vuln_id) 函数,根据 vuln_id 查询指定漏洞的相关信息。该函数将 API 返回的值中有用的信息提取出来到字典 data 里,返回给 vuln-details.html 页面,使用 双花括号 来接收该漏洞的受影响的URL、处理时间、漏洞类型、漏洞测试参数、数据请求包、简要的修复建议等信息。实现效果如下图所示。

@login_required
def vuln_detail(request,vuln_id):
    d = Vuln(API_URL,API_KEY)
    data = d.get(vuln_id)
    print(data)
    parameter_list = BeautifulSoup(data['details'], features="html.parser").findAll('span')
    request_list = BeautifulSoup(data['details'], features="html.parser").findAll('li')
    data_dict = {
        'affects_url': data['affects_url'],
        'last_seen': re.sub(r'T|\..*$', " ", data['last_seen']),
        'vt_name': data['vt_name'],
        'details': data['details'].replace("  ",'').replace('</p>',''),
        'request': data['request'],
        'recommendation': data['recommendation'].replace('<br/>','\n')
    }
    try:
        data_dict['parameter_name'] = parameter_list[0].contents[0]
        data_dict['parameter_data'] = parameter_list[1].contents[0]
    except:
        pass
    num = 1
    try:
        Str = ''
        for i in range(len(request_list)):
            Str += str(request_list[i].contents[0])+str(request_list[i].contents[1]).replace('<strong>', '').replace('</strong>', '')+'\n'
            num += 1
    except:
        pass
    data_dict['Tests_performed'] = Str
    data_dict['num'] = num
    data_dict['details'] = data_dict['details'].replace('class="bb-dark"','style="color: #ff0000"')
    return render(request, "vuln-detail.html", {'data': data_dict})
 

基于POC验证的中间件漏洞扫描

本系统使用POC脚本实现对一些中间件的漏洞扫描[7],包括Weblogic、Tomcat、Drupal、JBoss、Nexus、Struts2等等。通过每个漏洞的特点,使用Python编写不同的POC脚本验证目标是否存在该漏洞。

首先这里的用户界面和基于AWVS的漏洞扫描共用,单独加入了中间件漏洞CVE编号的选择。使用JavaScript发送用户输入的数据到后端。核心代码如下:

#使用POST请求提交用户的输入
function get_Middleware_scan(ip , CVE_id) {
    $.post('/Middleware_scan', {
    ip: ip , #目标URL
    CVE_id: CVE_id  #选择的CVE编号
}, function (data) {
#处理返回结果
      ………
      ………}); 
}
 

将目标添加到数据库后,再查询数据库开始扫描,通过 ajax 来访问 start_Middleware_scan 调用开始扫描的函数,由于扫描时间可能会很长,需要设置足够的 timeout 来等待扫描的结果返回。核心代码如下:

$.ajax({
#使用POST请求发送目标URL和CVE编号,设置超时为1秒
    type: "POST",
    url: '/start_Middleware_scan',
    timeout: 10000,
    data: {
    ip: ip,
    CVE_id: CVE_id
    }
});
 

在 urls.py 里加入中间件漏洞扫描的访问路径,需要加入两个路径:’Middleware_scan‘‘start_Middleware_scan’。前者是用户添加扫描目标时的路径,用于接收用户输入的目标和CVE编号之后将其插入数据库。后者是将目标插入数据库之后,通过时间戳、状态、目标 URL 以及 CVE 编号查询出来开始扫描。当扫描结束时更新数据库中对应扫描目标的状态。这样的设计可以实时的看到扫描的状态。

数据库使用的是 Sqlite,在 models.py 里创建一个数据库表 Middleware_vuln ,字段包括ID、目标URL、状态、结果、CVE编号、时间戳。在 Django 里定义这个类表示我们需要创建的数据库,在 modles.py 里创建好之后,使用命令python manage.py makemigrations来记录 modles.py 的所有改动,并且将这个改动迁移到 migrations 这个文件下生成一个文件例如:0001文件,如果你接下来还要进行改动的话可能生成就是另外一个文件不一定都是0001文件,但是这个命令并没有作用到数据库,再使用命令 python manage.py migrate 将根据刚刚检测到的改动来创建数据库表和字段属性。核心代码如下:

class Middleware_vuln(models.Model):
#类名为数据库表名,变量名为字段名,字段属性定义如下
    id = models.AutoField(primary_key=True)
    url = models.CharField(max_length=100, null=True)
    status = models.CharField(max_length=20, null=True)
    result = models.CharField(max_length=100, null=True)
    CVE_id = models.CharField(max_length=100, null=True)
    time = models.CharField(max_length=100, null=True, unique=True)
 

在添加目标和开始检测的时候我们需要插入数据库和查询数据库,这里使用 Django 的函数来处理数据库的增删查改。对于 Middleware_vule 的插入使用 Middleware_vuln.objects.create(url, status, result, CVE_id, time),更新使用 Middleware_vuln.objects.filter(time).update(status, result)。还需要使用 try-except 来处理异常情况并打印出错信息。

def insert_Middleware_data(url, CVE_id, Time, result=None, status="runing"):
    try:
        Middleware_vuln.objects.create(url=url, status=status, result=result, CVE_id=CVE_id, time=Time)
        print("insert success")
        return True
    except:
        print("data insert error")
        return False

def update_Middleware_data(url, CVE_id, Time, result):
    try:
        Middleware_vuln.objects.filter(url=url, status='runing', CVE_id=CVE_id, time=Time).update(status="completed", result=result)
        print("update success")
    except:
        print("data updata error")
 

views.py里定义 Middleware_scan() 获取用户输入,并插入到数据库中,其中时间戳 Time 为全局变量,作为后面开始扫描部分查询数据库的条件,在插入数据成功就返回 success(),否侧返回 error(),这里返回的函数时返回的状态码,success()返回的是200,error()返回404,通过上面 JavaScrip t接收后做出判断,并弹出相应的提示框,核心代码如下:

Time = 0.0
@csrf_exempt
@login_required
def Middleware_scan(request):
    #使用POST请求获取用户输入,并将其插入数据库中。
    #Time作为全局变量插入到数据库中,作为查询目标信息的条件。
    global Time
    try:
        url= request.POST.get('ip')
        CVE_id = request.POST.get('CVE_id').replace('-',"_")
        Time = time.time()  # time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(t))时间戳转日期格式
        if insert_Middleware_data(url, CVE_id, Time):
            return success()
    except:
        return error()
 

又定义函数 start_Middleware_scan(),实现将数据库中时间戳为 Time,状态为 run 的目标查询出来,根据 CVE编号调用对应的 POC 脚本。最后更新数据库的扫描结果和扫描状态,由于在上一步中将数据插入数据库中可能会花费一点时间,所以需要使用 sleep() 等待数据插入后再进行查询工作和扫描工作,保证不遗漏扫描目标。

@csrf_exempt
@login_required
def start_Middleware_scan(request):
    try:
        url = request.POST.get('ip')
        ip, port = urlparse(url).netloc.split(':')
        CVE_id = request.POST.get('CVE_id').replace('-', "_")
        time.sleep(5) #等待数据插入成功后在查询出来扫描
        msg = Middleware_vuln.objects.filter(url=url, status='runing', CVE_id=CVE_id, time=Time)
        print(msg)
        #扫描条目可能不止一条,需要使用循环来扫描
        for target in msg:
            result = POC_Check(target.url, target.CVE_id)
            
                                        
温馨提示:本文最后更新于2024年1月20日 12:06,若内容或图片失效,请在下方留言或联系博主。
评论
博主关闭了评论