第1章   概述

1.1   目標

Nginx(發音同engine x)是一款輕量級的Web服務器/反向代理服務器及電子郵件(IMAP/POP3)代理服務器,由俄羅斯的程序設計師Igor Sysoev所開發,可以穩定地運行在Linux、Windows等操作系統上,其特點是佔用內存少,併發能力強。

同其他軟件一樣,Nginx也出現過一些安全漏洞,利用這些漏洞可以對Web服務器進行滲透攻擊。本文主要描述互聯網架構中常用產品Nginx 的配置和安全加固工作,最終用以指導系統實施。

1.2   預期讀者

本文檔用於指導系統工程師進行系統實施工作,架構師和系統工程師應該通讀本文檔,選擇適當方式用於自己的系統。

第2章    產品介紹

Nginx是一個輕量級,高性能的Web服務器/反向代理和電子郵件代理(IMAP/POP3),它可以運行在UNIX,GNU/Linux,BSD變種,MACOS X,Solaris和Microsoft Windows上。根據Netcraft的調查數據顯示,互聯網上11%的域名都使用了Nginx Web服務器。Nginx是解決C10K問題的服務器之一,與傳統服務器不一樣,Nginx不依賴於線程處理請求,相反,它使用了一個更具擴展性的事件驅動(異步)架構。Nginx在很多高流量網站上得到了應用,如WordPress,Hulu,Github和SourceForge。

第3章   Nginx的安全加固配置

3.1  Nginx版本統一

查看當前系統中部署的Nginx版本。

1
2
[[email protected]] # nginx -v
nginxversion: nginx /1 .2.5


 

3.2   禁用autoindex

確保nginx.conf配置文件上禁用autoindex模塊,即沒有autoindex的配置。

加固檢查:

確保nginx.conf配置文件上禁用autoindex,即autoindex off或者沒有配置autoindex。

 

3.3   關閉服務器標記

如果開啓的話(默認情況下)所有的錯誤頁面都會顯示服務器的版本和信息。nginx.conf配置如下:

1
2
3
4
5
6
7
http{
     include       naxsi_core.rules;
     include      mime.types;
     default_type  application /octet-stream ;
     sendfile        on;
     server_tokens off;
     ... ...


加固檢查:

1
2
3
4
5
6
7
8
9
[[email protected]~] # curl -I http://localhost/wavsep
HTTP /1 .1301 Moved Permanently
Server:nginx
Date:Tue, 31 Dec 2013 23:20:29 GMT
Content-Type:text /html
Content-Length:178
Location:http: //localhost/wavsep/
Connection:keep-alive
Keep-Alive:timeout=30


其中,http://localhost/wavsep表示一個應用URL

 

3.4   自定義緩存

設置自定義緩存以限制緩衝區溢出攻擊。nginx.conf配置如下:

1
2
3
4
5
6
7
8
9
http{
     ... ...
     server{
         ... ...
         client_body_buffer_size  16K;
        client_header_buffer_size  1k;
         client_max_body_size  1m;
        large_client_header_buffers  4  8k;
         ... ...


     注:上述的參數不是最優參數,僅供參考。

加固檢查:

     確保server模塊中配置了上述標紅的配置。

 

3.5   設置timeout

設置timeout設低來防禦DOS攻擊,nginx.conf配置如下:

1
2
3
4
5
6
http {
     ... ...
        client_body_timeout   10;
        client_header_timeout  30;
        keepalive_timeout     30  30;
        send_timeout          10;


加固檢查:

1
2
3
4
5
6
7
8
9
[[email protected]~] # curl -I http://localhost/wavsep
HTTP /1 .1301 Moved Permanently
Server:nginx
Date:Tue, 31 Dec 2013 23:20:29 GMT
Content-Type:text /html
Content-Length:178
Location:http: //localhost/wavsep/
Connection:keep-alive
Keep-Alive:timeout=30


其中,http://localhost/wavsep表示一個應用URL

 

 

3.6   配置日誌

鑑於日誌的輸出格式還未確定,目前暫時先使用Nginx默認的日誌格式。nginx.conf配置如下:

http {

    ......

    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;

    ... ...

加固檢查:

     查看Nginx的日誌文件是否存在,並且訪問應用時,有日誌輸出。

[[email protected]~]# tail -3f /usr/local/nginx/logs/dfh.smartcity.com.log

Client_IP:10.5.220.27  Client_IP_For:- - - [10/Jan/2014:10:42:20+0800] "method:GET /portal/images/service_6.jpg HTTP/1.1"Protocol:"http" Status:304 Size:0"http://dfh.smartcity.com/portal/ext/index/index.jsp"  Args:- Browser:"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1;Trident/5.0; BOIE9;ZHCN)"

Client_IP:10.1.108.133  Client_IP_For:- - - [10/Jan/2014:10:42:23+0800] "method:GET/search/search?collId=1,2,3,4,5,6&query=%B3%C7%CA%D0%B9%E3%B2%A5HTTP/1.1" Protocol:"http" Status:200 Size:4145"http://dfh.smartcity.com/search/search?collId=1,2,3,4,5,6&query=%E5%9F%8E%E5%B8%82%E5%B9%BF%E6%92%AD&appID=1&ucode=utf-8"  Args:- Browser:"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/30.0.1599.101 Safari/537.36"

Client_IP:10.5.220.27  Client_IP_For:- - - [10/Jan/2014:10:42:24+0800] "method:GET /portal/images/change/service1_1.png HTTP/1.1"Protocol:"http" Status:304 Size:0"http://dfh.smartcity.com/portal/ext/index/index.jsp"  Args:- Browser:"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1;Trident/5.0; BOIE9;ZHCN)"

注:日誌輸出格式需要看配置的情況。

3.7   限制訪問的方法

在目前的應用系統中值使用到POST和GET方法,所以除了它們之外,其他方式的請求均可拒絕。Nginx.conf配置如下:

1
2
3
4
5
6
server{
        ... ...
        if ($request_method !~ ^(GET|HEAD|POST)$) {        
                      return404;
               }
        ... ...


     注:因爲目前統一錯誤應用沒有定版,所以先使用404,實際中應該使用444.

加固檢查:

使用火狐瀏覽器的poster插件:

wKioL1TMOKXQUZjMAAIlx1GgLrY988.jpg

 

嘗試使用不同的請求方式試試,能不能訪問。

 

3.8   Nginx日誌切割

Nginx日誌主要用於日後的審計和分析,對系統的安全有着重要的意義。但是隨着時間的推移,日誌文件會變得越來越大,這就需要對日誌進行處理分割了。

第一步:建立腳本文件:

1
2
[[email protected]] # vim nginx_log.sh
#/bin/bash


 

#日誌將要存放的路徑

1
savepath_log= '/logs/nginx/logs'


 

#nginx的日誌路徑

1
2
3
4
5
6
nglogs= '/usr/logs'
  
mkdir -p $savepath_log/$( date  +%Y)/$( date  +%m)
mv $nglogs /centoshost .com.log $savepath_log/$( date  +%Y)/$( date +%m) /centoshost $( date  +%Y%m%d%H%M).log
mv $nglogs /wavsep .com.log $savepath_log/$( date  +%Y)/$( date  +%m) /wavsep $( date +%Y%m%d%H%M).log
kill -USR1 $( cat  /var/run/nginx/nginx .pid)


其中,savepath_log和nglogs分別表示日誌分割後的存放目錄和Nginx的日誌目錄,均需要根據實際情況修改;centoshost.com.log和wavsep.com.log爲Nginx現在的文件文件名稱,也需要根據實際情況修改;centoshost和wavsep表示切割後保存的日誌文件名稱,需要根據實際情況修改。

第二步:爲nginx_log.sh分配可以執行權限

[[email protected] home]# chmod 755 nginx_log.sh

第三步:設定定時器

1
2
[[email protected]] # crontab -e
0000 * * *  /home/nginx_log .sh  #執行文件存放路徑,每天凌晨00:00執行


注:保存方式與vim一致,輸入:wq。

第四部:重啓定時器

1
2
3
4
[[email protected]] # cd /etc/init.d
[[email protected]] # ./crond restart
停止 crond:                                    [確定]
正在啓動 crond:                                [確定]


 

過程圖:

第一:Nginx日誌切割前

wKiom1TMOG3y0Wm9AACruyvV0Yw662.jpg

第二:保存日誌的目錄(切割前)

wKioL1TMOUaTdP6CAAA_0WKx4NE021.jpg


第三:Nginx日誌切割後

wKiom1TMOFPwEYEtAACjclxCqJI986.jpg


第四:保存日誌的目錄(切割後)

wKioL1TMOSrSdRR8AACKipWmi8A288.jpg

 

3.9   限制訪問IP

模塊 ngx_http_access_module 允許限制某些IP地址的客戶端訪問。

如下範例:

location/ {

    deny  192.168.1.1;

    allow 192.168.1.0/24;

    allow 10.1.1.0/16;

    allow 2001:0db8::/32;

    deny  all;

}

注:規則按照順序依次檢測,直到匹配到第一條規則。 在這個例子裏,IPv4的網絡中只有 10.1.1.0/16 和 192.168.1.0/24允許訪問,但 192.168.1.1除外, 對於IPv6的網絡,只有2001:0db8::/32允許訪問。

 

3.10集成Naxsi模塊

Naxsi模塊的集成,是基於Nginx已經部署了或已經存在系統中。

第一步:下載naxsi

[[email protected]]$ wget  http://naxsi.googlecode.com/files/naxsi-core-0.51-1.tgz

wKiom1TMOOeQ95Q7AAG2G5s1fxY163.jpg

注:如果不能上網可以事先下載,再上傳到服務器中。

第二步:解壓naxsi

[[email protected] install]$ tar -zxvfnaxsi-core-0.51-1.tgz

第三步:切換到naxsi-core-0.51-1目錄,並複製其配置文件到nginx.conf同目錄下

[[email protected]_config]$ cp naxsi_core.rules /etc/nginx/naxsi_core.rules

修改naxsi_core.rules的配置如下:

 

##################################

## INTERNAL RULESIDS:1-999     ##

##################################

#@MainRule "msg:weirdrequest, unable to parse" id:1;

#@MainRule"msg:request too big, stored on disk and not parsed" id:2;

#@MainRule"msg:invalid hex encoding, null bytes" id:10;

#@MainRule"msg:unknown content-type" id:11;

#@MainRule"msg:invalid formatted url" id:12;

#@MainRule "msg:invalidPOST format" id:13;

#@MainRule"msg:invalid POST boundary" id:14;

 

##################################

## SQL InjectionsIDs:1000-1099 ##

##################################

MainRule"rx:select|union|update|delete|insert|table|from|ascii|hex|unhex|drop""msg:sql keywords" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie""s:$SQL:8" id:1000;

MainRule"str:\"" "msg:double quote""mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8,$XSS:8"id:1001;

MainRule"str:0x" "msg:0x, possible hex encoding""mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:2" id:1002;

## Hardcore rules

MainRule"str:/*" "msg:mysql comment (/*)""mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1003;

MainRule"str:*/" "msg:mysql comment (*/)""mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1004;

MainRule "str:|""msg:mysql keyword (|)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8"id:1005;

##MainRule"str:&&" "msg:mysql keyword (&&)""mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1006;

## end of hardcore rules

MainRule"str:--" "msg:mysql comment (--)""mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1007;

MainRule "str:;""msg:; in stuff" "mz:BODY|URL|ARGS""s:$SQL:4,$XSS:8" id:1008;

MainRule "str:=""msg:equal in var, probable sql/xss" "mz:ARGS|BODY""s:$SQL:2" id:1009;

MainRule "str:(""msg:parenthesis, probable sql/xss""mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$SQL:4,$XSS:8"id:1010;

MainRule "str:)""msg:parenthesis, probable sql/xss""mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$SQL:4,$XSS:8"id:1011;

MainRule "str:'""msg:simple quote" "mz:ARGS|BODY|URL|$HEADERS_VAR:Cookie""s:$SQL:4,$XSS:8" id:1013;

MainRule "str:,""msg:, in stuff" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie""s:$SQL:4" id:1015;

MainRule "str:#""msg:mysql comment (#)""mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1016;

 

###############################

## OBVIOUS RFIIDs:1100-1199 ##

###############################

MainRule"str:http://" "msg:http:// scheme""mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1100;

MainRule"str:https://" "msg:https:// scheme""mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1101;

MainRule"str:ftp://" "msg:ftp:// scheme""mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1102;

MainRule"str:php://" "msg:php:// scheme""mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1103;

MainRule"str:sftp://" "msg:sftp:// scheme""mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1104;

MainRule"str:zlib://" "msg:zlib:// scheme""mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1105;

MainRule"str:data://" "msg:data:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie""s:$RFI:8" id:1106;

MainRule"str:glob://" "msg:glob:// scheme""mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1107;

MainRule"str:phar://" "msg:phar:// scheme""mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1108;

MainRule"str:file://" "msg:file:// scheme""mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1109;

 

#######################################

## Directory traversalIDs:1200-1299 ##

#######################################                                         

MainRule "str:..""msg:double dot" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie""s:$TRAVERSAL:4" id:1200;

MainRule"str:/etc/passwd" "msg:obvious probe""mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:4"id:1202;

MainRule"str:c:\\" "msg:obvious windows path" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie""s:$TRAVERSAL:4" id:1203;

MainRule"str:cmd.exe" "msg:obvious probe""mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:4"id:1204;

MainRule"str:\\" "msg:backslash""mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:4"id:1205;

MainRule "str:/""msg:slash in args" "mz:ARGS|BODY|$HEADERS_VAR:Cookie""s:$TRAVERSAL:2" id:1206;

 

########################################

## Cross Site ScriptingIDs:1300-1399 ##

########################################

MainRule"str:<" "msg:html open tag""mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$XSS:8" id:1302;

MainRule"str:>" "msg:html close tag""mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$XSS:8" id:1303;

MainRule "str:[""msg:[, possible js" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie""s:$XSS:4" id:1310;

MainRule "str:]""msg:], possible js" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie""s:$XSS:4" id:1311;

MainRule "str:~""msg:~ character" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie""s:$XSS:4" id:1312;

MainRule"str:`"  "msg:grave accent!" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$XSS:8"id:1314;

MainRule "rx:%[2|3]."  "msg:double encoding !""mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$XSS:8" id:1315;

MainRule "rx:%3[c|e]."  "msg:double encoding !""mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$XSS:8" id:1316;

MainRule "rx:\\\u003[c|e]"  "msg:tag encoding !""mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$XSS:8" id:1317;

MainRule "str:&#" "msg:utf7/8 encoding" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie""s:$EVADE:4" id:1318;

 

####################################

## Evading tricks IDs:1400-1500 ##

####################################

MainRule"str:&#" "msg: utf7/8 encoding""mz:ARGS|BODY|URL|$HEADERS_VAR:Cookie" "s:$EVADE:4"id:1400;

MainRule"str:%U" "msg: M$ encoding""mz:ARGS|BODY|URL|$HEADERS_VAR:Cookie" "s:$EVADE:4"id:1401;

MainRule negative"rx:multipart/form-data|application/x-www-form-urlencoded""msg:Content is neither mulipart/x-www-form..""mz:$HEADERS_VAR:Content-type" "s:$EVADE:4" id:1402;

 

#############################

## File uploads: 1500-1600##

#############################

MainRule"rx:.ph|.asp|.ht" "msg:asp/php file upload!""mz:FILE_EXT" "s:$UPLOAD:8" id:1500;

MainRule "rx:.jsp""msg:asp/php file upload!" "mz:FILE_EXT""s:$UPLOAD:8" id:1501;

MainRule "rx:.html""msg:asp/php file upload!" "mz:FILE_EXT""s:$UPLOAD:8" id:1502;

MainRule "rx:.php""msg:asp/php file upload!" "mz:FILE_EXT""s:$UPLOAD:8" id:1503;注:(1)nginx.conf所有的目錄是在nginx編譯安裝時,默認的配置是<prefix>/conf/nginx.conf。

     (2)鑑於原有的naxsi_core.rules文件中規則不足,最好是採用本文檔中的配置規則。

第四步:編譯安裝Nginx

查看系統原來編譯Nginx的參數:

[qiang @srv-dfh526 ~]#nginx  -V

nginx version: nginx/1.3.0

TLS SNI support enabled

configure arguments:--with-http_stub_status_module --with-http_gzip_static_module--with-http_ssl_module --prefix=/usr/local/nginx--with-openssl=/root/install/openssl-1.0.1c --with-pcre=/root/install/pcre-8.20

在原來的編譯參數的首行加入--add-module=/root/install/naxsi-core-0.51-1/naxsi_src。

[[email protected]]#./configure  

--add-module=/root/install/naxsi-core-0.51-1/naxsi_src\

--with-http_stub_status_module\

--with-http_gzip_static_module\

--with-http_ssl_module \

--prefix=/usr/local/nginx\

--with-openssl=/root/install/openssl-1.0.1c\

--with-pcre=/root/install/pcre-8.20

[[email protected]]# make && make install

注:上述的參數可以根據實際情況選擇,但是標紅的需要有。

 

第五步:驗證nginx是否安裝成功

[[email protected]]# nginx

nginx: [warn] low addressbits of 192.168.1.65/26 are meaningless in /etc/nginx/nginx.conf:78

[[email protected]]# ps -ef |grep nginx

root      3086    1  0 10:53 ?        00:00:00 nginx: master process nginx

root      3087 3086  1 10:53 ?        00:00:00 nginx: worker process

root      3088 3086  1 10:53 ?        00:00:00 nginx: worker process

root      3089 3086  1 10:53 ?        00:00:00 nginx: worker process

root      3090 3086  1 10:53 ?        00:00:00 nginx: worker process

root      3093 3073  4 10:53 pts/1    00:00:00 grep nginx

 

第六步:配置過濾條件

切換目錄到與nginx.conf同目錄下,新建nbs.rules文件。

[[email protected] nginx]#vim nbs.rules

##LearningMode;

#Enables learningmode--stop

SecRulesEnabled;

##Disables learning

##SecRulesDisabled;

DeniedUrl"/RequestDenied";

## check rules

CheckRule "$SQL >=8" BLOCK;

CheckRule "$RFI >=8" BLOCK;

CheckRule "$TRAVERSAL>= 8" BLOCK;

CheckRule "$EVADE>= 8" BLOCK;

CheckRule "$XSS >=8" BLOCK;

 

############################################################

##      STOP  ALL   RULES(如果不需要可以關閉全部過濾規則)  ##

############################################################

#BasicRule wl:0;

 

##################################

## INTERNAL RULESIDS:1-999     ##

##################################

BasicRulewl:1,2,10,11,12,13,14;

 

 

##################################

## SQL InjectionsIDs:1000-1099 ##

##################################

BasicRule wl: 1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,1016;

 

 

###############################

## OBVIOUS RFIIDs:1100-1199 ##

###############################

BasicRulewl:1100,1101,1102,1103,1104,1105,1106,1107,1108,1109;

 

 

 

#######################################

## Directory traversalIDs:1200-1299 ##

#######################################

BasicRulewl:1200,1202,1203,1204,1205,1206;

 

 

########################################

## Cross Site ScriptingIDs:1300-1399 ##

########################################

BasicRulewl:1310,1311,1312,1313,1314,1315,1318;

 

 

####################################

## Evading tricks IDs:1400-1500 ##

####################################

BasicRulewl:1400,1401,1402;

 

 

#############################

## File uploads: 1500-1600##

#############################

BasicRule wl:1500,1501,1502,1503;

 注:該nbs.rules文件的規則需要根據不同的業務應用制定。

 

第七步:配置nginx.conf

http{

    #必須配置

    include       naxsi_core.rules;

    include       mime.types;

    default_type  application/octet-stream;

    .......

    server {

        listen       80;

        server_name  localhost centoshost.com;

        charset utf-8;

        .......

        location /wavsep/ {

            .......

            #每一個location配置首行都需要添加該行

            includenbs.rules;

            .......

        }

        #與應用處於相同的server配置

        location /RequestDenied {

            error_page  404 /404.html;

        }

注:wavsep表示一個demo應用。

第八步:重啓nginx

[[email protected]]# nginx -t -c /etc/nginx/nginx.conf

nginx:[warn] low address bits of 192.168.1.65/26 are meaningless in/etc/nginx/nginx.conf:78

nginx:the configuration file /etc/nginx/nginx.conf syntax is ok

nginx:configuration file /etc/nginx/nginx.conf test is successful

[[email protected]]# nginx -s reload

nginx:[warn] low address bits of 192.168.1.65/26 are meaningless in/etc/nginx/nginx.conf:78

 

第九步:測試攔截規則是否啓用

上述的規則僅過濾「<」、「>」。

測試XSS注入:

wKioL1TMOeeSQQrFAAFW1kAODH4636.jpg

結果:

wKioL1TMOfTT31s9AAE0gGY-_xc260.jpg

第十步:替換應用中的ajax

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
function  htmlEncode (str){
     var  s =  "" ;
31
32
33
34
35
36
37
38
function  htmlEncode (str){
     var  s =  "" ;
     if  (str.length == 0)  return  "" ;
     //s = str.replace(/ /g, "&nbsp;");
     //s = str.replace(/&/g, "&amp;");
     s = str.replace(/</g,  "&lt;" );
     s=s.replace(/%3C/g, "&lt;" );