AppScan9.0.3.5漏洞掃描記錄


1.跨站點腳本編制

這個安全漏洞拿cookie做文章,而且是將前端的一些彈窗方法,要么通過腳本注入,要么通過url.encode之后注入,看幾個變異的版本:

版本一: 

cookie  從以下位置進行控制: a5d5b093-a2c1-47e5-9604-b661c124344a 至:a5d5b093-a2c1-47e5-9604-b661c124344a"==aalertlert(15)+"

 之前是將一個alert注入,現在這個軟件知道了,只過濾一次,那我就拆成兩個,你過濾一個,合起來還是alert。好賤啊這軟件

 

 

解決處理:好吧,那我就遞歸處理了,沒想到出現了版本二的變體了,厲害了

版本二:

 var _cookies="bosssoft.com.cn=7717ef32-34a8-4a42-b26cf6804549a370;JSESSIONID=Kzdsb2QTHGkTx08XBhTBNJQN7GQlhmnWv0YhmS2tLDxQQT2YbCvK!-2054262092"+
[window['location']='\x6a\x61\x76\x61\x73\x63\x72\x69\x70\x74\x3a\x61\x6c\x65\x72\x74\x2832\x29']
+"";

我的天,前端那么多腳本注入方式,這么搞不行啊,而且人家還是通過url.encode,前端彈窗還有各種方式。:

1.window.open()
2.window.location=javascript:alert(1)
3.comfirm("xxx")
4.prompt("xxxx")
5.alert
...

那不是搞死了?防不勝防啊。

解決方案:后來想想,反正這個cookie,在業務系統也沒用到,但是jsessionid主要用於負載均衡策略session粘滯。

好吧,一不做二不休。想想既然能夠執行的都是函數體,那我就把cookie里頭包含以下字符:(、)、[、]、\的全部替換了。

                Pattern scriptPattern = Pattern.compile("\\(",
                        Pattern.CASE_INSENSITIVE);
                if(scriptPattern.matcher(value).find()){
                    flag=true;
                    return flag;
                }
                
                scriptPattern = Pattern.compile("'",
                        Pattern.CASE_INSENSITIVE);
                if(scriptPattern.matcher(value).find()){
                    flag=true;
                    return flag;
                }
                
                scriptPattern = Pattern.compile("\\\\",
                        Pattern.CASE_INSENSITIVE);
                if(scriptPattern.matcher(value).find()){
                    flag=true;
                    return flag;
                }
                
                scriptPattern = Pattern.compile("\\[",
                        Pattern.CASE_INSENSITIVE);
                if(scriptPattern.matcher(value).find()){
                    flag=true;
                    return flag;
                }
                
                scriptPattern = Pattern.compile("\\]",
                        Pattern.CASE_INSENSITIVE);
                if(scriptPattern.matcher(value).find()){
                    flag=true;
                    return flag;
                }

好吧,cookie的總算解決了,然這軟件,坑爹的,用到了表單上,天啊,表單就不能這么搞了,但是安全漏洞不過,不讓上線。后來經理說,能解決再說,我們后面補丁撤回來。

沒想到,這軟件絕了,改值,然后通過url.encode。注入表單,厲害了。

你絕,那我也絕了,把你響應回來的內容,字符我全部給你做了替換了,解決方案如下:

try {
                value=URLDecoder.decode(value,"UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            
            value= StringEscapeUtils.escapeJavaScript(value);
            value= StringEscapeUtils.escapeHtml(value);
            value= StringEscapeUtils.escapeXml(value);

首先通過URLDecoder.decode將編碼的恢復正常,然后通過escapeJavaScript、escapeHtml、escapeXml等將輸出的返回到前台,嗯嗯,這下總算解決了這個漏洞,當然上線的時候不能這么搞==!

2.使用 HTTP 動詞篡改的認證旁路  

這個漏洞,首先將它有問題的鏈接改成指定的方法,然后再通過第一漏洞處理后,這漏洞就沒了

3.會話標識未更新  

漏洞原因:在我們的cookie里頭存有兩個session值,一個是jessionid。一個是我們自己業務系統要使用的,在登錄前后這兩個session值都要發生變化,這個軟件才會認為是安全的,但是jessionid如果變了,可能會影響負載均衡的粘滯問題。既然是為了安全掃描,業務系統登錄前后的session是有變化的,但是jessionid是沒變,所以把jessionid變了,就好了。這個漏洞就可以解決了。

4.已解密的登錄請求 

這個漏洞主要是因為傳遞的參數沒有通過ssl即https的方式進行傳播,將weblogic開啟https,此外如果有Nginx也要開通https,這個漏洞就可以解決了。附一份nginx配置: 

#user  nobody;
worker_processes  4;

#error_log  logs/error.log;
error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;
worker_rlimit_nofile 20000;

events {
    use epoll;
    worker_connections  10240;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    server_tokens off;

    keepalive_timeout           60 20;
    client_header_timeout       3m;
    client_body_timeout         3m;
    send_timeout                3m;

    client_header_buffer_size           16k;
    large_client_header_buffers         4 32k;
    server_names_hash_max_size          512;
    server_names_hash_bucket_size       64;

    sendfile        on;
    tcp_nopush      on;
    tcp_nodelay     on;

#    limit_req_zone $binary_remote_addr zone=http:10m rate=10r/s;
#    limit_req_zone $http_user_agent zone=useragenttrack:10m rate=10r/s;

    log_format  main
        '$remote_addr - $remote_user [$time_local] $request '
        '"$status" $body_bytes_sent "$http_referer" '
        '"$http_user_agent" "$http_x_forwarded_for"';
    access_log logs/access.log  main;

    map $http_user_agent $is_bot {
        default 0;
        ~[a-z]bot 1;
        ~[sS]pider 1;
        ~spi_der 1;
        ~crawler 1;
        ~ysearch 1;
        ~Yahoo\sPipes 1;
        ~BingPreview 1;
        ~YoudaoFeedFetcher 1;
        'Yahoo!\sSlurp' 1;
        'Mediapartners-Google' 1;
        #'Mozilla/5.0' 1;
    }

    include appconf/upstream.conf;
    include appconf/gzip.conf;

    #lua_need_request_body on;
    #init_by_lua_file conf/waf/init.lua;
    #access_by_lua_file conf/waf/waf.lua;

#    lua_shared_dict limit 50m;
#    lua_package_path /opt/openresty/nginx/conf/waf/?.lua;
#    init_by_lua_file conf/waf/init.lua;
#    access_by_lua_file conf/waf/waf.lua;


    server {
         listen       18002 ssl;
         server_name  localhost;

         ssl_certificate      ./ssl/server.crt;
         ssl_certificate_key  ./ssl/server.key;

    proxy_set_header       Host $http_host;
    proxy_set_header  X-Real-IP  $remote_addr;
    proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto  $scheme;
    proxy_set_header Cookie $http_cookie;
    add_header                  Set-Cookie "HttpOnly";
    add_header                  Set-Cookie "Secure";
    add_header                  X-Frame-Options "SAMEORIGIN";

         if ($request_method !~ ^(GET|POST|HEAD|DELETE)$ ) {
            return 405;
         }

         location ~ ^/(WEB-INF)/ {
            return 404;
         }

         location ~ ^/(js|css|img|scripts|stylesheets|uploads)/ {
            root html;
            access_log off;
            expires 30d;
         } 

         location ~ \.(apk|torrent|htm|html|asp|php|gif|jpg|jpeg|png|bmp|ico|rar|css|js|zip|map|java|jar|txt|flv|swf|mid|doc|ppt|xls|pdf|txt|mp3|wma)$ {
            root html;
            access_log off;
            expires 30d;
         }
         ssl_session_cache    shared:SSL:1m;
         ssl_session_timeout  5m;
         ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers
"ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
         #ssl_ciphers  HIGH:!aNULL:!MD5;
         ssl_prefer_server_ciphers  on;
         location / {
               root   html;
               index  index.html index.htm;  
            set $mscheme $scheme;
            if ($http_referer ~* ^https.*) {
                set $mscheme "https";
            }
            proxy_set_header X-Forwarded-Proto $mscheme;
           }

    location /finance-web{
           proxy_pass http://10.56.30.91:7001/finance-web;
            set $mscheme $scheme;
            if ($http_referer ~* ^https.*) {
                set $mscheme "https";
            }
            proxy_set_header X-Forwarded-Proto $mscheme;
        }

        location /appframe-web{
           proxy_pass http://10.56.30.91:7001/appframe-web;
            set $mscheme $scheme;
            if ($http_referer ~* ^https.*) {
                set $mscheme "https";
            }
            proxy_set_header X-Forwarded-Proto $mscheme;
        }

        location /agency-web{
           proxy_pass http://10.56.30.91:7001/agency-web;

            set $mscheme $scheme;
            if ($http_referer ~* ^https.*) {
                set $mscheme "https";
            }
            proxy_set_header X-Forwarded-Proto $mscheme;
        }
  }
    
    


#        location ~ ^/nstatus {
#            stub_status on;
#            access_log off;
#            allow 127.0.0.1;
#            allow 10.236.57.0/24;
#            deny all;
#        }

    error_page 502 504 /502.html;
    error_page 503 /503.html;
    error_page 404 /404.html;
    error_page 403 /403.html;
    }
    

 5.加密會話(SSL)Cookie 中缺少 Secure 屬性

 這個問題主要是因為cookie里頭的屬性secure未設置true。因為部署的容器是weblogic所以在應用的weblogic.xml文件里頭新增屬性:

<?xml version="1.0" encoding="UTF-8"?>
<weblogic-web-app xmlns="http://www.bea.com/ns/weblogic/90" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <container-descriptor>
        <prefer-web-inf-classes>true</prefer-web-inf-classes> 
        <index-directory-enabled>true</index-directory-enabled>
          <show-archived-real-path-enabled>true</show-archived-real-path-enabled>
    </container-descriptor> 
    <charset-params>
        <input-charset>
            <resource-path>/*</resource-path>
            <java-charset-name>UTF-8</java-charset-name>
        </input-charset> 
    </charset-params> 
    <context-root>/appframe-web</context-root>
    <session-descriptor>
        <cookie-http-only>true</cookie-http-only>
        <cookie-secure>true</cookie-secure>
    </session-descriptor>
</weblogic-web-app>

如圖要新增

    <session-descriptor>
        <cookie-http-only>true</cookie-http-only>
        <cookie-secure>true</cookie-secure>
    </session-descriptor>

如何驗證呢?

可以加,

但是沒加前,獲取cookie是空的 ,也就是說沒有通過https傳遞cookie,那么document.cookie獲取不到cookie

此外在nginx配置里頭也要加上

 

    add_header                  Set-Cookie "HttpOnly";
    add_header                  Set-Cookie "Secure";
    add_header                  X-Frame-Options "SAMEORIGIN"

另外如果是shiro工程,要在spring-shiro.xml下加上配置:

    <!-- 會話Cookie模板 -->
    <bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
        <constructor-arg value="bosssoft.com.cn"/>
        <property name="httpOnly" value="true"/>
        <property name="secure" value="true"/>
        <!--cookie的有效時間 -->
        <property name="maxAge" value="-1"/>
    </bean>  

基於安全的考慮,需要給cookie加上Secure和HttpOnly屬性,HttpOnly比較好理解,設置HttpOnly=true的cookie不能被js獲取到,無法用document.cookie打出cookie的內容。
Secure屬性是說如果一個cookie被設置了Secure=true,那么這個cookie只能用https協議發送給服務器,用http協議是不發送的。換句話說,cookie是在https的情況下創建的,而且他的Secure=true,那么之后你一直用https訪問其他的頁面(比如登錄之后點擊其他子頁面),cookie會被發送到服務器,你無需重新登錄就可以跳轉到其他頁面。但是如果這是你把url改成http協議訪問其他頁面,你就需要重新登錄了,因為這個cookie不能在http協議中發送。

6.檢查到目標URL存在http host頭攻擊漏洞 

上述問題出現的原因為在項目中使用了 request.getServerName 導致漏洞的出現,不要使用request中的serverName,也就是說host header可能會在攻擊時被篡改,依賴request的方法是不可靠的,形如JSP頭部中的: 

String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"

這樣的使用方法就會被漏洞檢測工具查出來,認定有頭攻擊漏洞。

解決方案:在CSRFFilter過濾器中加入頭部攻擊判斷:

        String requestHost=((HttpServletRequest) request).getHeader("host");
        if(requestHost!=null&&!isWhiteHost(requestHost)){
            ((HttpServletResponse) response).setStatus(403);
            return;
        }

7.檢查到目標站點存在JavaScript框架庫漏洞

這個問題,主要是因為jquery.js在低版本中存在安全漏洞的問題,只要替換高版本的jQuery.js庫就可以解決了,當然要考慮高版本對IE8的兼容問題。可以參考博文《Jquery3.x高版本支持IE8

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM