现在的位置: 首页 > 综合 > 正文

Appscan的python扩展工具: PyScan

2013年02月07日 ⁄ 综合 ⁄ 共 7678字 ⁄ 字号 评论关闭

  Appscan的python扩展工具: PyScan 收藏
      IBM Rational AppScan 是一个面向 Web 应用安全检测的自动化工具,使用它可以自动化检测 Web 应用的安全漏洞,比如跨站点脚本攻击(Cross Site Scripting Flaws)、注入式攻击(Injection Flaws)、失效的访问控制(Broken Access Control)、缓存溢出问题(Buffer Overflows)等等。这些安全漏洞大多包括在 OWASP(Open Web Application Security Project,开放式 Web 应用程序安全项目)所公布的 Web 应用安全漏洞中.
从 7.5 版本以后,Rational Appscan 提供了扩展机制 —— AppScan eXtension Framework。
       利用 Appscan 提供的 eXtension framework,用户可以非常简单的为 AppScan 提供扩展。扩展的内容几乎没有任何限制,可以从一个简单的通知程序到一个非常复杂的安全分析工具,使得用户可以根据自己的需要来客户化 AppScan。AppScan eXtension Framework 支持多种语言,如 Python、C#、C++、J#、Jscript 等等 . 本文主要介绍如何利用python进行扩展--PyScan.

       进入Pyscan的方法:在appscan中点击"工具", "扩展“, "PyScan“。如果没有,可下载安装PyScan。
appScan:AppScan SDK 的主接口 IAppScan 的实例对象。IAppScan 接口包含了 AppScan 扫描测试引擎的主要功能对象,通过使用这个接口的实例,就可以调用 AppScan 的主要功能,它一般作为客户端访问 AppScan 的入口。如该接口中的 Scan 属性,它实际上是 IScanManager 的实例对象。上面的类图列举了 IScanManager 中的部分方法,比如 Scan() 方法用来开始对目标网站的同步扫描,ScanAsync() 和 Scan() 方法功能相同,只不过是异步方法,ResetExploereAndTestData() 用来清空网站扫描和安全测试结果等等。

IAppscan接口
属性:
IConfiguration Config; # 配置信息接口
IScanManager Scan;  # 扫描管理对象

IConfiguration
包含了Appscan进行扫描的配置信息,如配置扫描的代理, 它有成员变量:
IAppScanProxySettings ProxySettings
如果想获取到Appscan的所有漏洞信息,它有成员变量:
IRules Rules; 它能指向每一条漏洞的接口: IIssueTypeData.

IIssueTypeData的公有属性
Advisory: 漏洞的咨询信息
AdvisoryID:漏洞的咨询ID
AdvisoryName:咨询名
CveId: CVE ID
Description: 漏洞描述
Name:漏洞名
RemediationID: 建议ID
RemediationTitle: 建议标题
Severity:安全分数
ThreatClass:威胁分类
UserDefined:该漏洞是否为用户自定义
VariantTypes:有关漏洞检测的过程信息,如检测所用的URL等

IScanManager
这是一个扫描管理对象,包括
公有属性:
CurrentUrl: 当前扫描的URL
ScanData:保存的扫描数据
ScanExpert:扫描专家对象
Status: 扫描状态,如Test扫描状态, Pretest预扫描状态
公有方法:
ResetScanData():清空扫描数据
ReTest():重新测试一个漏洞
ReTestAsync():异步测试
Scan(): 开启一个扫描任务
ScanAsync():开启一个扫描任务,异步扫描
SendManualTest():开始一个手动测试。
Stop():结束当前任务
IScanData
IScanManager.scanData成员是一个IScanData对象,它保存了一个任务的扫描信息。
公有属性:
AppTreeRoot:URL目录树的根结点
Config:扫描的配置信息
TotalScanDuration: 扫描时间
VisitedUrls:扫描的URL

IScanConfiguration
IScanData.Config成员是一个IScanConfiguration对象,它包含了一个任务的扫描配置信息。
公有属性:
ClientSideCertificate:客户认证设置
CommunicationTimeout:会话超时时间(从发送请求,到接收到响应)
CustomErrorPages:定制错误信息页集合。
CustomParameters:定制参数
DefaultLimit:扫描深度设置
ScanPolicy: 深度优先,还是广度优先
SessionManagement:会话管理器
StartingUrl:起启URL
TestPolicy:扫描策略,它包括了漏洞的集合

例程:

# -*- coding: cp936 -*-
import re
import sys
import string
from urlparse import urlparse, urlunparse
import win32com.client
import __main__
appScan = __main__.appScan

startingUrl = ""
vuls_conn = None

def getStartingUrl():
    '''
    get the starting url
    '''
    startingUri = System.Uri(appScan.Scan.ScanData.Config.StartingUrl)
    url = startingUri.ToString()
    print "Starting url is : ", url
    return url

def GetAllIssueTypesCount():
    '''
    Get the count of all the test rules currently installed with Appscan
    '''
    rules = appScan.Config.Rules.IssueTypes
    print len(rules)

def DisplayAllIssueTypes():
    '''
    Display all the test rules installed with Appscan
    '''
    rules = appScan.Config.Rules.IssueTypes
    for rule in rules:
        # rule is a IIssueTypeData class object
        print rule.Description
        print rule.AdvisoryID

def GetCurrentIssueTypesCount():
    '''
    Get the count of current using issue types
    '''
    issueTypesCount = appScan.Scan.ScanData.Config.TestPolicy.IssueTypes.Dictionary.get_Count()
    print "issueTypesCount = ", issueTypesCount
    return issueTypesCount

def GetIssueDescription(issueType):
    '''
    Get the issueType Description of a issueType
    '''
    rules = appScan.Config.Rules.IssueTypes
    for rule in rules:
        if rule.AdvisoryID == issueType.AdvisoryID:
            return rule.Description

def GetIssueType(issueTypeName):
    '''
    Gets an IssueType element according to the giving issueTypeName string
    The IssueType element can be used with the appScan.Scan.SendManualTest method
    '''
    # Get all issue types that partially match the name
    issueTypes = appScan.Scan.ScanData.Config.TestPolicy.IssueTypes
    values = list (issueTypes.Dictionary.Values)

    # Iterate over all of them, trying to get a match
    foundIssueType = None
    for v in values:
        # Check if a partial match was found
        print v.RulesIssueType.Description
        if v.RulesIssueType.Description.__contains__(issueTypeName):
            foundIssueType = v.RulesIssueType.ResultsIssueType

            # If an exact match was found - use that
            if v.RulesIssueType.Description == issueTypeName:
                return foundIssueType

    return foundIssueType

def DisplayConfigInfo():
    '''
    Display some configure information
    '''
    startingUri = System.Uri(appScan.Scan.ScanData.Config.StartingUrl)
    if startingUri != None:
        print "startingUri:", startingUri
       
    scanLimit = appScan.Scan.ScanData.Config.DepthLimit.Value
    print "DepthLimit = ", scanLimit
   
    scanLimit = appScan.Scan.ScanData.Config.NumberOfThreads.__str__;
    print "NumberOfThreads = ", scanLimit

    timeLimit = appScan.Scan.ScanData.Config.TimeLimit.Value
    print "timeLimit = ", timeLimit

def StartScan():
    '''
    Display current scan info
    '''   
    appScan.Scan.ScanData.Config.StartingUrl = "http://stroke.tw/"

    # Set a proxy server
    #appScan.Scan.ScanData.Config.ProxyServerConfiguration.IPAddress = "119.70.40.101"
    #appScan.Scan.ScanData.Config.ProxyServerConfiguration.Port = 8080
    #appScan.Scan.ScanData.Config.ProxyServerConfiguration.Enabled = True

    appScan.Scan.Scan(True, True)
    totalScanDuration = appScan.Scan.ScanData.TotalScanDuration
    print "totalScanDuration = ", totalScanDuration

def GetVisitedUrls():
    '''
    Get the urls visited
    '''
    appData = appScan.Scan.ScanData.AppTreeRoot.GetApplicationData()
    urls = list(appData.VisitedUrls)
    for url in urls:
        print url.Request.Uri.ToString()

def showTestUrlsbyId(advisoryid):
    '''
    show the urls test using
    '''
    issues = appScan.Scan.ScanData.AppTreeRoot.GetIssues()
    issueslist = list(issues)
    for issue in issueslist:
        if issue.IssueType.AdvisoryID != advisoryid:
            continue
        print GetIssueDescription(issue.IssueType)
        tests = list(issue.Variants)
        print len(tests)
        for test in tests:
            request = test.Request.RawRequest
            print request
            print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"

def showAllVuls():
    issues = appScan.Scan.ScanData.AppTreeRoot.GetIssues()
    issueslist = list(issues)
    for issue in issueslist:
        print GetIssueDescription(issue.IssueType)
        tests = list(issue.Variants)
        for test in tests:
            request = test.Request.RawRequest
            print request
            print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
            break

def insertResult(vultype, request, param):

    print "type: ", vultype

    print "request: ", request

    print "param: ", param

def saveScanResults():
    '''
    Display the results of current scan
    '''
    global vuls_conn
   
    issues = appScan.Scan.ScanData.AppTreeRoot.GetIssues()
    issueslist = list(issues)
    print "ISSUES COUNT = ", len(issueslist)

    vuls_conn = win32com.client.Dispatch("ADODB.Connection")
    vuls_DSN = r"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=U:\work\vulns.accdb;Persist Security Info=False;"
    vuls_conn.Open(vuls_DSN)
   
    for issue in issueslist:
        descript = GetIssueDescription(issue.IssueType)
        print "Descript = ", descript

        # XSS
        if issue.IssueType.AdvisoryID == '57':
            tests = list(issue.Variants)
            print len(tests)
           
            for test in tests:
                if test.Vulnerable == True:
                    request = test.Request.RawRequest
                    print request
                    print "~~~~~~~~~~~~~~~~~~~", test.Entity.Name
                    insertResult('XSS', request, test.Entity.Name)
                    break

        # SQL盲注和SQL注入
        if (issue.IssueType.AdvisoryID == '142') or (issue.IssueType.AdvisoryID == '132'):
            tests = list(issue.Variants)
            for test in tests:
                if test.Vulnerable == True:
                    request = test.Request.RawRequest
                    insertResult('SQLInject', request, test.Entity.Name)
                    break

if __name__ == '__main__':
    #getStartingUrl()
    #GetCurrentIssueTypesCount()
    #DisplayAllIssueTypes()
    #DisplayConfigInfo()
    #GetVisitedUrls()
    showAllVuls()
    #showTestUrlsbyId('57')

 

抱歉!评论已关闭.