//此套WAF防护正则表达式规则来源于ShareWAF(http://www.sharewaf.com/)
//测试方法建议:请依下方测试使用的test语句进行,根据true、false,可知是否能识别出***并记录到数据库

var regexp_debug = 0;
exports.anti_sqlinj_rule =[
   // /select|update|delete|truncate|join|union|exec|insert|drop|count|Sp_sqlexec|order by|’|"|>|    /select.+(from|limit)/,
   /(?:(union(.*?)select))/,
   // /having|rongjitest/,
   /sleep\((\s*)(\d*)(\s*)\)/,
   /group\s+by.+\(/,
   /(?:from\W+information_schema\W)/,
   /(?:(?:current_)user|database|schema|connection_id)\s*\(/,

//新增
   /\s*or\s+.*=.*/i,
   /order\s+by\s+.*--$/i
];

if( regexp_debug == 1) {
    ///select|update|delete|truncate|join|union|exec|insert|drop|count|Sp_sqlexec|order  by|’|"|>|    //不区分大小写的字符串匹配,留给影卫字符匹配,这里不使用

//.匹配除“\n”之外的任何单个字符
   //含意:匹配select from或select limit语句
   //注意:区分大小写,如要取消大小写区分,加:/i

   //新增,匹配' or 1=1 –,规则:/空格出现或不出现 or 空格出现1次或多次 任何字符不限次数 = 任意字符不限次数
   console.log( /\s*or\s+.*=.*/i.test("'or 1=1") ); //true
   console.log( /\s*or\s+.*=.*/i.test("'or 1!=2") ); //true
   console.log( /\s*or\s+.*=.*/i.test("'or 'a'='a'") ); //true
   console.log( /\s*or\s+.*=.*/i.test("'or'a'='a'") ); //false
   console.log( /\s*or\s+.*=.*/i.test("'or1=1") ); //false

   //新增,匹配:order by 1 --
   console.log( /order\s+by\s+.*--$/i.test("order by 1 --") ); //true
   console.log( /order\s+by\s+.*--$/i.test("order   by 2  --") ); //true
   console.log( /order\s+by\s+.*--$/i.test("order BY 3 --") ); //true

console.log( /select.+(from|limit)/.test("select * from abc") ); //true
   console.log( /select.+(from|limit)/.test("select top 10 * from abc") ); //true
   console.log( /select.+(from|limit)/.test("select top 10") ); //false
   console.log( /select.+(from|limit)/.test("Select top 10 from") ); //false

//(?:X):仅分组
   //.:任意字符号
   //X*?:字符出现0次或多次
   //(.*):任意字符出现0次或多次
   //含意:匹配union select语法
   //注意:区分大小写,如要取消大小写区分,加:/i
   console.log( /(?:(union(.*?)select))/.test("union select 1,2,3 from") ); //true
   console.log( /(?:(union(.*?)select))/.test("UNION select 1,2,3 from") ); //false
   console.log( /(?:(union(.*?)select))/.test("abc union abc select 1,2,3 from") ); //true
   console.log( /(?:(union(.*?)select))/.test("abc union /* */ select 1,2,3 from") ); //true
   console.log( /(?:(union(.*?)select))/.test("abc union /* */") ); //false
   console.log( /(?:(union(.*?)select))/.test("select col from table union all select col2 from table2") ); //true
   //对这条语法存疑,写的可能有问题,下面一行的测试说明:(?:)(仅分组,不记录分组序号,也不捕获该匹配)是无意义的
   console.log( /union(.*?)select/.test("abc union /* */ select 1,2,3 from"),"test" ); //true

//\s :空白字符
   //\s* :空白字符出现0次或多次(出现或不出现)
   //\d:数字
   //\d*:任意数字出现0次或多次
   //含意:匹配sleep(数字)函数,括号里可以有任何空白字符
   //注意:区分大小写,如要取消大小写区分,加:/i
   console.log( /sleep\((\s*)(\d*)(\s*)\)/.test("sleep(1)") ); //true
   console.log( /sleep\((\s*)(\d*)(\s*)\)/.test("sleep(   1 )") ); //true
   console.log( /sleep\((\s*)(\d*)(\s*)\)/.test("sleep('abc')") ); //false
   console.log( /sleep\((\s*)(\d*)(\s*)\)/.test("sleep(' abc')") ); //false
   console.log( /sleep\((\s*)(\d*)(\s*)\)/.test("SLEEP(1)") ); //false
   //加i,不区分大小写
   console.log( /sleep\((\s*)(\d*)(\s*)\)/i.test("SLEEP(1)"),"test2" ); //true

//\s :空白字符
   //.:任意字符号
   //含意:匹配group by语法
   //注意:区分大小写,如要取消大小写区分,加:/i
   //不确定:这条规则可能有误,不应该有(符号,group by语句没有(
   console.log( /group\s+by.+\(/.test("group by id(") ); //true
   console.log( /group\s+by.+\(/.test("group by id") ); //false

//information_schema:mysql自带数据库
   //\W:不能构成单词的字符,等价于[^A-Za-z0-9_]
   //(?:X)仅分组
   console.log( /(?:from\W+information_schema\W)/.test("select TABLES from * information_schema * ") ); //true
   console.log( /(?:from\W+information_schema\W)/.test("select TABLES from/**/information_schema/**/") ); //true
   console.log( /(?:from\W+information_schema\W)/.test("select TABLES from 123 /**/ union information_schema/**/") ); //false
   //(?:X)仅分组无意义,应该可改为:
   console.log( /from\W+information_schema\W/.test("select TABLES from/**/information_schema/**/") ); //true

//(?:X):仅分组
   //|:或
   //\s:空白字符
   //注意:区分大小写,如要取消大小写区分,加:/i
   console.log( /(?:(?:current_)user|database|schema|connection_id)\s*\(/.test("current_user (") ); //true
   console.log( /(?:(?:current_)user|database|schema|connection_id)\s*\(/.test("current_database(") ); //true
   console.log( /(?:(?:current_)user|database|schema|connection_id)\s*\(/.test("current_connection_id   (") ); //true
   console.log( /(?:(?:current_)user|database|schema|connection_id)\s*\(/.test("current_connection_id = (") ); //false
   console.log( /(?:(?:current_)user|database|schema|connection_id)\s*\(/.test("connection_id(") ); //true
   console.log( /(?:(?:current_)user|database|schema|connection_id)\s*\(/.test("connection_ID(") ); //false
   //应该可简化为:
   console.log( /(?:current_)user|database|schema|connection_id\s*\(/.test("current_connection_id   (") ); //true
   console.log( /(?:current_)user|database|schema|connection_id\s*\(/.test("connection_id(") ); //true
}


exports.anti_cookieinj_rule =[
   /select.+(from|limit)/,
   /(?:(union(.*?)select))/,
   ///having|rongjitest/,
   /sleep\((\s*)(\d*)(\s*)\)/,
   /benchmark\((.*)\,(.*)\)/,
   /base64_decode\(/,
   /(?:from\W+information_schema\W)/,
   //修改,增加version
   /(?:(?:current_)user|database|version|schema|connection_id)\s*\(/,
   /(?:etc\/\W*passwd)/,
   /into(\s+)+(?:dump|out)file\s*/,
   /group\s+by.+\(/,
   /xwork.MethodAccessor/,
    /(?:define|eval|file_get_contents|include|require|require_once|shell_exec|phpinfo|system|passthru|preg_\w+|execute|echo|print|print_r|var_dump|(fp)open|alert|showmodaldialog)\(/
];
if( regexp_debug == 1) {
   //\i大小写区分问题不再赘述,普遍存在
   //mysql函数benchmark
   //检测例::benchmark(1000,encode("hello","goodbye"))
   console.log( /benchmark\((.*)\,(.*)\)/.test('select BENCHMARK(1000000,encode("hello","goodbye"))') ); //false
   console.log( /benchmark\((.*)\,(.*)\)/.test('select benchmark(1000000,encode("hello","goodbye"))'),"benchmark"); //true

///base64_decode\(/
   //检测base64_decode()函数
   //到此,大至可理解:此套规则是针对mysql、php的
   console.log( /base64_decode\(/.test("base64_decode('abc')") ); //true
   console.log( /base64_decode\(/.test("base64_Decode('abc')") ); //false

console.log( /(?:(?:current_)user|database|schema|connection_id)\s*\(/.test("user(") ); //false
   console.log( /(?:(?:current_)user|database|schema|connection_id)\s*\(/.test("current_user(") ); //true
   console.log( /(?:(?:current_)user|database|schema|connection_id)\s*\(/.test("current_user (") ); //true
   console.log( /(?:(?:current_)user|database|schema|connection_id)\s*\(/.test("current_user   (") ); //true
   console.log( /(?:(?:current_)user|database|schema|connection_id)\s*\(/.test("current_usEr   (") ); //false
   console.log( /(?:(?:current_)user|database|schema|connection_id)\s*\(/.test("current_user  * (") ); //false

//etc路径加passwd检测
   //\W:不能构成单词的字符
   console.log( /(?:etc\/\W*passwd)/.test("etc/passwd") ); //true
   console.log( /(?:etc\/\W*passwd)/.test("etc//passwd") ); //true
   console.log( /(?:etc\/\W*passwd)/.test("etc passwd") ); //false
   console.log( /(?:etc\/\W*passwd)/.test("etc////passwd") ); //true
   console.log( /(?:etc\/\W*passwd)/.test("etc////PASSWD") ); //false

//mysql的file系列函数检测:dumpfile\outfile
   //X+,X字符出现一次或多次
   //\s:空白字符
   console.log ( /into(\s+)+(?:dump|out)file\s*/.test("select * from test into outfile '/tmp/test.txt'") ); //true
   console.log ( /into(\s+)+(?:dump|out)file\s*/.test("select * from test into dumpfile '/tmp/test.txt'") ); //true
   console.log ( /into(\s+)+(?:dump|out)file\s*/.test("select * from test into dumpFILE '/tmp/test.txt'") ); //false

///xwork.MethodAccessor/,
   //这是struts2相关的一个漏洞关键字
   console.log( /xwork.MethodAccessor/.test("xwork.MethodAccessor") ); //true
   console.log( /xwork.MethodAccessor/.test("xwork.MethodAccessoR") ); //false

//w+:可以构成单词的字符
   //检测各种函数
    /(?:define|eval|file_get_contents|include|require|require_once|shell_exec|phpinfo|system|passthru|preg_\w+|execute|echo|print|print_r|var_dump|(fp)open|alert|showmodaldialog)\(/
   console.log(   /(?:define|eval|file_get_contents|include|require|require_once|shell_exec|phpinfo|system|passthru|preg_\w+|execute|echo|print|print_r|var_dump|(fp)open|alert|showmodaldialog)\(/.test("define")  ); //false
   console.log(   /(?:define|eval|file_get_contents|include|require|require_once|shell_exec|phpinfo|system|passthru|preg_\w+|execute|echo|print|print_r|var_dump|(fp)open|alert|showmodaldialog)\(/.test("define(")  ); //true
   console.log(   /(?:define|eval|file_get_contents|include|require|require_once|shell_exec|phpinfo|system|passthru|preg_\w+|execute|echo|print|print_r|var_dump|(fp)open|alert|showmodaldialog)\(/.test("define(")  ); //true
   console.log(   /(?:define|eval|file_get_contents|include|require|require_once|shell_exec|phpinfo|system|passthru|preg_\w+|execute|echo|print|print_r|var_dump|(fp)open|alert|showmodaldialog)\(/.test("preg_a(")  ); //true
}

exports.anti_xss_rule = [
   //注释掉
   // /<|>|:|'|""|`|--|()|[]|{}|/,
   /\<(iframe|script|body|img|layer|div|meta|style|base|object|input)/,
   /(onmouseover|onmousemove|onerror|onload)\=/i,
   //新增
   /javascript:/i
];

if( regexp_debug == 1){

console.log( /\<(iframe|script|body|img|layer|div|meta|style|base|object|input)/.test("    console.log( /\<(iframe|script|body|img|layer|div|meta|style|base|object|input)/.test("iframe")); //false

console.log( /\<(iframe|script|body|img|layer|div|meta|style|base|object|input)/.test("

console.log( /(onmouseover|onmousemove|onerror|onload)\=/i.test("onerror='alert(1)'")); //true


console.log( /javascript:/i.test("javascript:alert(1);") );

}


exports.anti_folder_iterator_rule = [


/..\/..\//,

// /(?:etc\/\W*passwd\/shadow)/

//修改:

// /(?:etc\/\W*passwd)/i


];

if( regexp_debug == 1){

//匹配:../../

console.log( /..\/..\//.test("../../pass/") ); //true

console.log( /..\/..\//.test("../pass/") ); //false

}


exports.anti_cmdinj_rule = [

//修改

// || 命令

/\|\|.*(?:ls|pwd|whoami|ll|ifconfog|ipconfig|&&|chmod|cd|mkdir|rmdir|cp|mv)/,

//命令||

/(?:ls|pwd|whoami|ll|ifconfog|ipconfig|&&|chmod|cd|mkdir|rmdir|cp|mv).*\|\|/

];

if(regexp_debug == 1){

console.log(   /\|\|.*(?:ls|pwd|whoami|ll|ifconfog|ipconfig|&&|chmod|cd|mkdir|rmdir|cp|mv)/.test("||ipconfig")  ); //true

console.log( /\|\|.*(?:ls|pwd|whoami|ll|ifconfog|ipconfig|&&|chmod|cd|mkdir|rmdir|cp|mv)/.test("||cd") ); //true

console.log( /\|\|.*(?:ls|pwd|whoami|ll|ifconfog|ipconfig|&&|chmod|cd|mkdir|rmdir|cp|mv)/.test("cd") ); //false

console.log( /\|\|.*(?:ls|pwd|whoami|ll|ifconfog|ipconfig|&&|chmod|cd|mkdir|rmdir|cp|mv)/.test("|cd") ); //false

}


exports.anti_remote_file_include_rule = [

/http:\/\/|https:\/\//,

/(?:define|eval|file_get_contents|include|require|require_once|shell_exec|phpinfo|system|passthru|preg_\w+|execute|echo|print|print_r|var_dump|(fp)open|alert|showmodaldialog)\(/,

//注释

// /(gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\:\//,

];

if(regexp_debug == 1){

console.log( /http:\/\/|https:\/\/|..\/..\//.test("http://") ); //true

console.log( /http:\/\/|https:\/\/|..\/..\//.test("http:") ); //false

console.log( /http:\/\/|https:\/\/|..\/..\//.test("https:") ); //false

}


exports.anti_local_file_include_rule = [

//这行容易误报

// /..\//,

/(?:etc\/\W*passwd)/,

//注释

//   /(?:define|eval|file_get_contents|include|require|require_once|shell_exec|phpinfo|system|passthru|preg_\w+|execute|echo|print|print_r|var_dump|(fp)open|alert|showmodaldialog)\(/,

/(gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\:\//

];

if( regexp_debug == 1){

//匹配:etc/ 不能构成单词的任意字符不出现或出现或出现多次 password

console.log( /(?:etc\/\W*passwd)/i.test("etc//passwd") ); //true

console.log( /(?:etc\/\W*passwd)/i.test("etc/passwd") ); //true

console.log( /(?:etc\/\W*passwd)/i.test("etc//**/passwd") ); //true

console.log( /(?:etc\/\W*passwd)/i.test("etc\\passwd") ); //false


console.log( /(gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\:\//.test("file:/") ); //true

console.log( /(gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\:\//.test("file:") ); //false

}