Day13
示例代码:
public class UploadFileController extends HttpServlet {
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws IOException {
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
ServletFileUpload upload = new ServletFileUpload(factory);
String uploadPath = getServletContext().getRealPath("") + "upload";
File uploadDir = new File(uploadPath);
if (!uploadDir.exists()) {
uploadDir.mkdir();
}
try {
List items = upload.parseRequest(request);if (items != null && items.size() > 0) {for (FileItem item : items) {if (!item.isFormField()) {if (!(item.getContentType().equals("text/plain"))) {throw new Exception("ContentType mismatch");
}
String file = uploadPath + File.separator + item.getName();
File storeFile = new File(file);
item.write(storeFile);
}
}
}
} catch (Exception ex) {
response.sendRedirect("/");
}
}
}
初步看到代码是上传漏洞,只对ContentType的值做了校验,轻松绕过。可是上传文件后,发现并没有返回路径。
然后看到"String file = uploadPath + File.separator + item.getName();"
,此处的文件名用户可控,且未做任何过滤,可通过"../"
来控制上传路径,从而获取webshell。
上传webshell,post包部份数据如下:
ntent-Disposition: form-data; name="filename"; filename="../shell.jsp"
Content-Type: text/plain
成功收到shell。
Day14
示例代码:
import java.io.PrintWriter;
import java.util.*;
import javax.servlet.http.*;
public class Export extends HttpServlet {
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws IOException {
response.setContentType("text/csv");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
String content = buildCSV(request);
out.print(content);
out.flush();
}
public String buildCSV(HttpServletRequest request) {
{
StringBuilder str = new StringBuilder();
List> rows = Arrays.asList(
Arrays.asList("Scott", "editor", request.getParameter("description"))
);
str.append("Name");
str.append(",");
str.append("Role");
str.append(",");
str.append("Description");
str.append("\n");for (List rowData : rows) {
str.append(String.join(",", rowData));
str.append("\n");
}return str.toString();
}
}
}
该示例代码为dde漏洞,响应的数据格式为"text/csv"
格式,在传入的数据中,参数"description"
可控,可构造以"="
或"-"
打头的恶意语句,如:"description==cmd |'/C calc' !A0"
。
执行结果:
Day15
示例代码:
public class FindOnSystem extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
try {
String[] binary = {"find", ".", "-type", "d"};
ArrayList cmd = new ArrayList<>(Arrays.asList(binary));
String[] options = request.getParameter("options").split(" ");for (String i : options) {
cmd.add(i);
}
ProcessBuilder processBuilder = new ProcessBuilder(cmd);
Process process = processBuilder.start();
IOUtils.copy(process.getInputStream(),response.getOutputStream());
} catch(Exception e) {
response.sendRedirect("/");
}
}
}
看到敏感的方法"processBuilder.start()"
,典型的命令执行漏洞。可发现"options"
传入的值全部拼接在find命令后,尝试"; pwd"
、"||"
、"&&"
等常见命令,发现都不能返回正常结果,(但是在终端可以正常执行,不是很明白为啥)。看了下官方提示,使用的是"options=-exec pwd ;"
,可正常执行。
注find -exec用法:"find ./ -type f -exec ls -l {} \;"
。以;
为结束标志,由于各个系统中分号会有不同的意义,因此在前面加上反斜杠。{}
代表前面find查找出来的文件名
执行结果:
Day16
示例代码:
UserEntity.java
@Entity
@DynamicUpdate
@Table(name = "UserEntity", uniqueConstraints = {
@UniqueConstraint(columnNames = "ID"),
@UniqueConstraint(columnNames = "EMAIL") })
public class UserEntity implements Serializable {
public UserEntity(String email, String firstName, String lastName) {
this.email = email;
this.firstName = firstName;
this.lastName = lastName;
}
private static final long serialVersionUID = -1798070786993154676L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID", unique = true, nullable = false)
private Integer userId;
@Column(name = "EMAIL", unique = true, nullable = false, length = 100)
private String email;
@Column(name = "FIRST_NAME", unique = false, nullable = false, length = 100)
private String firstName;
@Column(name = "LAST_NAME", unique = false, nullable = false, length = 100)
private String lastName;
}
FindController.java
public class FindController {
public String escapeQuotes(String in){
return in.replaceAll("'","''");
}
@RequestMapping("/findUsers")
public void findUsers(@RequestParam(name="name") String name, HttpServletResponse res) throws IOException{
Configuration config = new Configuration();
// Create SessionFactory with MySQL driver
SessionFactory sessionFactory = config.configure().buildSessionFactory();
Session session = sessionFactory.openSession();
List users = session.createQuery("from UserEntity where FIRST_NAME ='" + escapeQuotes(name) + "'", UserEntity.class).list();
res.getWriter().println("Found " + users.size() + " Users with that name");
}
}
给出了两个java文件,第一个主要是实体的创建,忽略掉。在FindController文件中,sql语句为"from UserEntity where firstName ='" + escapeQuotes(name) + "'"
,确定为hql注入漏洞。在用户传入的"name"
参数,只通过escapeQuotes方法将"'"
替换成了"''"
,和Hibernate处理字符串文字的单引号方法一致,都是对其进行转义。此时可通过转义"'"
的方式绕过限制。
构造payload,执行结果: