Let's take a look at the inverted quotes to successfully execute the named code fragment. The code is as follows:
Copy Code code as follows:
' Ls-al ';
' Ls-al ';
echo "SSS"; ' Ls-al ';
$sql = "Select ' username ' from ' table ' WHERE 1";
$sql = ' SELECT ' username ' from ' table ' WHERE 1 '
/*
Nothing more than a white-space character before, or after the end of a line of code, followed by write, the following two behavioral accidents, that is, the SQL command in the inverted quotation marks, to exclude it.
*/
How do you write regular expressions?
Analysis:
What are some common features of portability? What is the difference with other normal parts that contain inverted quotes?
They can be preceded by a space, tab, and other white-space characters. You can also have program code, provided that the quotation marks (single and double) must be closed. Is dangerous and hidden. CFC4N gave the following positive: "(:(?: ^ (?: \ S+) | (?:(? P<quote>["']) [^ (? P=quote)]+? (? p=quote) [^ ']*?)] `(? p<shell>[^ ']+ ' ".
Explain:
"(?:(?: ^ (?: \ S+) | (?:(? P<quote>["']) [^ (? P=quote)]+? (? p=quote) [^ ']*?)] "matches the start position or the start position with a white space character or preceded by a code, and the code has a closed single double quote." (This python is used for capture naming and reverse references)
"' (? p<shell>[^ ']+ ' "This is relatively simple, matching the string in the middle of the inverted quote.
Python script detects PHP Webshell
I then wrote the code into the program and ran the Discuz program. The result is a false alarm. The location of the false positives is "define" in "config.inc.php" (' Uc_dbtablepre ', ' ucenter '. uc_ '); "And what causes it?" This line of code conforms to the enclosed quotation marks and the use of inverted quotes, so that it is detected in accordance with the requirements. How can we eliminate this situation? What's so special about this? Preceded by a comma ","? If the string is concatenated with the dot number "." It? And then exclude commas?
Well, I was wrong, I should not use my thinking to mislead you. Another way of thinking. Find the case of the front string of the code that can be inverted quotes, they can only be the beginning of the line, or there are white space characters (including spaces, tab, etc.), and then there may be the end of the code to identify the semicolon ";" All other cases are not enforceable? Well, it should be. (If there is a mistake, welcome treatise) Since the idea has, that regular code is better written. as follows "(^| (?) <=;)) \s* ' [^ ']+ '], explain, "(^|? <=;)) "matches the position, is the beginning of the line, or preceded by a semicolon"; ". "\s* ' [^ ']+ '"] any one of the blank characters, then be ... (you know). OK, after writing, testing, and found a problem.
Matching the introduction of the file will also match the "require_once './include/db_ '. $database." Class.php '; ' This kind of code, what cause, you analyze it yourself.
Give the Python code after the fix, as follows:
Copy Code code as follows:
#!/usr/bin/python
#-*-Encoding:utf-8-*-
###
# # @package
##
# # @author cfc4n <cfc4nphp@gmail.com>
# # @copyright Copyright (c) Www.cnxct.Com
# # @Version $Id: check_php_shell.py notoginseng 2010-07-22 09:56:28z cfc4n $
###
Import OS
Import Sys
Import re
Import time
def listdir (dirs,liston= ' 0 '):
Flog = open (OS.GETCWD () + "/check_php_shell.log", "A +")
If not Os.path.isdir (dirs):
Print "Directory%s is not exist"% (dirs)
Return
Lists = Os.listdir (dirs)
For list in lists:
filepath = Os.path.join (dirs,list)
If Os.path.isdir (filepath):
If Liston = = ' 1 ':
Listdir (filepath, ' 1 ')
Elif Os.path.isfile (filepath):
filename = os.path.basename (filepath)
If Re.search (r "\:p hp|inc|html?) $ ", filename, re. IGNORECASE):
i = 0
Iname = 0
f = open (filepath)
While F:
File_contents = F.readline ()
If not file_contents:
Break
i + 1
Match = Re.search (r "") (? p<function>\b (?: Include|require) (?: _once) \b) \s*\ (? \s*["'] (? p<filename>[^;] * (? <!\. (?:p hp|inc))) [']\ '] \s* ', file_contents, re. ignorecase| Re. MULTILINE)
If match:
function = Match.group ("function")
filename = match.group ("filename")
If Iname = 0:
info = ' \n[%s]: \ n '% (filepath)
Else
info = '
info + = ' \t|--[%s]-[%s] line [%d] \ n '% (function,filename,i)
Flog.write (Info)
Print Info
Iname + 1
Match = Re.search (R ' \b) (? P<function>eval|proc_open|popen|shell_exec|exec|passthru|system) \b\s*\ (', file_contents, re. ignorecase| Re. MULTILINE)
If match:
function = Match.group ("function")
If Iname = 0:
info = ' \n[%s]: \ n '% (filepath)
Else
info = '
Info + + ' \t|--[%s] line [%d] \ n '% (function,i)
Flog.write (Info)
Print Info
Iname + 1
Match = Re.search (R ' (^|) (? <=;)) \s* ' (? p<shell>[^ ']+) ' \s* ', file_contents, re. IGNORECASE)
If match:
Shell = Match.group ("Shell")
If Iname = 0:
info = ' \n[%s]: \ n '% (filepath)
Else
info = '
info + = ' \t|--['] command is [%s] in line [%d] \ n '% (shell,i)
Flog.write (Info)
Print Info
Iname + 1
F.close ()
Flog.close ()
If ' __main__ ' = __name__:
Argvnum = Len (SYS.ARGV)
Liston = ' 0 '
If Argvnum = 1:
Action = Os.path.basename (Sys.argv[0])
print ' Command is like:\n%s D:\wwwroot\ \ n%s D:\wwwroot\ 1--recurse subfolders '% (action,action)
Quit ()
elif Argvnum = = 2:
Path = Os.path.realpath (Sys.argv[1])
Listdir (Path,liston)
Else
Liston = sys.argv[2]
Path = Os.path.realpath (Sys.argv[1])
Listdir (Path,liston)
Flog = open (OS.GETCWD () + "/check_php_shell.log", "A +")
isotimeformat= '%y-%m-%d%x '
Now_time = Time.strftime (Isotimeformat,time.localtime ())
Flog.write ("\ n----------------------%s checked---------------------\ n"% (Now_time))
Flog.close ()
A little bit of the Discuz7.2 code was detected, or wrongly reported, the false report of this contains SQL code:
Copy Code code as follows:
$query = $db->query ("Select ' Status ', ' threads ', ' posts ')
From ' {$tablepre}forums ' WHERE
' Status ' = ' 1 ';
");
A little bit of the Discuz7.2 code was detected, or wrongly reported, the false report of this contains SQL code:
Copy Code code as follows:
$query = $db->query ("Select ' Status ', ' threads ', ' posts ')
From ' {$tablepre}forums ' WHERE
' Status ' = ' 1 ';
");
Because this script is handled on a line of code, there is this false alarm. You have to fix it yourself. Compared to the web-circulated script, it is still more accurate.
Welcome to reprint. Reprint please indicate the source, as well as leave the blog link, at the same time, can not be used for commercial purposes. (Has been repaired, added inverted quotes behind the "\s*;" judgment. 2010-07-27 17:06)
PS: If the upload file is also considered a dangerous, noteworthy operation, it is recommended to add Move_uploaded_file function detection. You know where to add it. ^_^
2010-12-17 about the code, has been placed on Google's code hosting. SVN address for http://code.google.com/p/cnxct/to get the latest version.
I am a phper, write Python a little suppressed, a bit lazy, but also please the security sector of Daniel, the predecessor of the program industry do not despise, to give advice, thank you. PHP version of the later in writing it. At the same time, the security enthusiasts are welcome to feedback the latest Web Shell feature code, I try to add to the program Central.
The complete code
Copy Code code as follows:
#!/usr/bin/python
#-*-Encoding:utf-8-*-
###
# # @package
##
# # @author cfc4n <cfc4nphp@gmail.com>
# # @copyright Copyright (c) Www.cnxct.Com
# # @Version $Id $
###
Import OS
Import Sys
Import re
Import time
def listdir (dirs,liston= ' 0 '):
Flog = open (OS.GETCWD () + "/check_php_shell.log", "A +")
If not Os.path.isdir (dirs):
Print "Directory%s is not exist"% (dirs)
Return
Lists = Os.listdir (dirs)
For list in lists:
filepath = Os.path.join (dirs,list)
If Os.path.isdir (filepath):
If Liston = = ' 1 ':
Listdir (filepath, ' 1 ')
Elif Os.path.isfile (filepath):
filename = os.path.basename (filepath)
If Re.search (r "\:p hp|inc|html?) $ ", filename, re. IGNORECASE):
i = 0
Iname = 0
f = open (filepath)
While F:
File_contents = F.readline ()
If not file_contents:
Break
i + 1
Match = Re.search (r "") (? p<function>\b (?: Include|require) (?: _once) \b) \s*\ (? \s*["'] (? p<filename>[^;] * (? <!\. (?:p hp|inc))) [']\ '] \s* ', file_contents, re. ignorecase| Re. MULTILINE)
If match:
function = Match.group ("function")
filename = match.group ("filename")
If Iname = 0:
info = ' \n[%s]: \ n '% (filepath)
Else
info = '
info + = ' \t|--[%s]-[%s] line [%d] \ n '% (function,filename,i)
Flog.write (Info)
Print Info
Iname + 1
Match = Re.search (R ' \b) (? p<function>eval|proc_open|popen|shell_exec|exec|passthru|system|assert|fwrite|create_function) \b\s*\ (', File_contents, Re. ignorecase| Re. MULTILINE)
If match:
function = Match.group ("function")
If Iname = 0:
info = ' \n[%s]: \ n '% (filepath)
Else
info = '
Info + + ' \t|--[%s] line [%d] \ n '% (function,i)
Flog.write (Info)
Print Info
Iname + 1
Match = Re.search (R ' (^|) (? <=;)) \s* ' (? p<shell>[^ ']+) ' \s* ', file_contents, re. IGNORECASE)
If match:
Shell = Match.group ("Shell")
If Iname = 0:
info = ' \n[%s]: \ n '% (filepath)
Else
info = '
info + = ' \t|--['] command is [%s] in line [%d] \ n '% (shell,i)
Flog.write (Info)
Print Info
Iname + 1
Match = Re.search (R ') (? P<shell>\$_ (?:P os| ge| reques) T) \s*\[[^\]]+\]\s*\ (', file_contents, re. IGNORECASE)
If match:
Shell = Match.group ("Shell")
If Iname = 0:
info = ' \n[%s]: \ n '% (filepath)
Else
info = '
info + = ' \t|--['] command is [%s] in line [%d] \ n '% (shell,i)
Flog.write (Info)
Print Info
Iname + 1
F.close ()
Flog.close ()
If ' __main__ ' = __name__:
Argvnum = Len (SYS.ARGV)
Liston = ' 0 '
If Argvnum = 1:
Action = Os.path.basename (Sys.argv[0])
print ' Command is like:\n%s D:\wwwroot\ \ n%s D:\wwwroot\ 1--recurse subfolders '% (action,action)
Quit ()
elif Argvnum = = 2:
Path = Os.path.realpath (Sys.argv[1])
Listdir (Path,liston)
Else
Liston = sys.argv[2]
Path = Os.path.realpath (Sys.argv[1])
Listdir (Path,liston)
Flog = open (OS.GETCWD () + "/check_php_shell.log", "A +")
isotimeformat= '%y-%m-%d%x '
Now_time = Time.strftime (Isotimeformat,time.localtime ())
Flog.write ("\ n----------------------%s checked---------------------\ n"% (Now_time))
Flog.close ()