Use of the API without .NET, JAVA, or gacmd. A proof-of-concept in Powershell.

If you have a new question you’d like our support staff to post a response to, please visit our customer community, Data Security Insiders, to pose the question in our Discussion Boards. We have a thread “Ask Our Tech Experts” that our support team monitors on a regular basis, or you can start a new discussion where other GoAnywhere users and support staff can weigh in. Log in or create your new account at

If you need an immediate response, please create a support ticket or contact our support team by email at [email protected].
1 post Page 1 of 1


Posts: 1
Joined: Tue Jan 10, 2017 6:06 pm

Post by Cignul9 » Tue Jan 10, 2017 6:28 pm
Here's a Powershell script that doesn't drive gacmd, use the .NET api or the Java api. I wiresharked the web calls gacmd was making. Powershell pretends to be that client to the server. The good news is this is sessionless; one web call gives one result. The data in motion security is totally dependent upon the fact that this web call should happen over a secure connection, ie: https. Going through a reverse proxy should work just fine.

Now, I didn't completely reverse engineer gacmd. I just wanted to show that it can be done and encourage the GoAnywhere devs to release the web call details, maybe give us a wsdl or a wadl (and for god sake please provide support for json bodies or something more reasonable). I only support three commands. Hack this up and add more. While your at it here are some improvements you could throw in:
  • * ParameterSets for each command
    * Parameter descriptors, maybe take input from the pipeline, that kind of thing
    * Better exception handling
    * Better output format. I'm just dumping xml. I'm lazy.
    * More commands supported (lookin at you for that wsdl, devs)
    * Some kind of GPL license up in there. I don't care just take it.
This is useful if you want to integrate with CRM, for example, and your CRM people want web calls not Java or .NET API's. This way you can demonstrate how to do that. If anyone's interested I can post decoded HTTP so you can get a raw look at a request and response.
Code: Select all
  [string]$url = [ your server url here, including the port ex: ],
  [string]$user = [ the account name use to manage web users ],
  [string]$password [ the account password you use to manage web users ],
function Create-MultiPartBody{
  $body = ''
  foreach($part in $Parts.GetEnumerator()){
    if($part.Name -eq 'commandAction'){
      $disposition = "form-data; name=`"file`"; filename=`"$($part.Name)`""
      $type = 'application/octet-stream; charset=ISO-8859-1'
      $encoding = 'binary'
      $disposition = "form-data; name=`"$($part.Name)`""
      $type = 'text/plain; charset=UTF-8'
      $encoding = '8bit'
    $bodySegment = @"
Content-Disposition: $($disposition)
Content-Type: $($type)
Content-Transfer-Encoding: $($encoding)


    $body += $bodySegment
  $body += "--$($boundary)--`n"
  return $body
function Create-CommandXml{
  [xml]$doc = ''
  $rootNode = $doc.CreateElement('command')
  $command.GetEnumerator() | ?{$_.Value -ne $null} | %{
    $parameter = $doc.CreateElement($_.Name)
    if($_.Value -is [boolean] -or $_.Value -is [switch]){
      $value = $_.Value.ToString().ToLower()
      $value = $_.Value
    $parameter.InnerText = $value
  return $doc.OuterXml.Trim()
function Send-WebRequest{
  $apiURL = "$($url)/goanywhere/servlets/commandCenter"
  Write-Verbose "URL: `n$($apiURL)"
  $randomString = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes([System.Guid]::NewGuid().ToString()))
  $boundary = $randomString.Substring($randomString.Length-39)
  $userAgent = 'Jakarta Commons-HttpClient/3.1'
  $headers = [ordered]@{
    'Transfer-Encoding' = 'chunked';
    'Content-Type' =  "multipart/form-data; boundary=$($boundary)";
  $body = Create-MultiPartBody $contentParts $boundary
  Write-Verbose "Body: `n$($body)"
    $response = Invoke-WebRequest `
      -Uri $apiURL `
      -DisableKeepAlive `
      -UserAgent $userAgent `
      -Headers $headers `
      -Method POST `
      -Body $body
    Write-Verbose $_.Exception.Message
  return $response
$commandActions = @{
  deleteWebUser = [ordered]@{
    userName              = $webUserName;
  addWebUser = [ordered]@{
    webUserTemplate       = $webUserTemplate;
    userName              = $webUserName;
    userPassword          = $webUserPassword;
    firstName             = $webUserFirstName;
    lastName              = $webUserLastName;
    description           = $webUserDescription;
    email                 = $webUserEmail;
  resetWebUserPassword = [ordered]@{
    userName              = $webUserName;
    generatePassword      = $generatePassword;
    userPassword          = $webUserPassword;
    forcePasswordChange   = $forcePasswordChange;
    displayPassword       = $true;
    emailPassword         = $emailPassword;
$contentParts = [ordered]@{
  command = $command
  user = $user;
  password = $password;
  passwordIsEncrypted = 'false';
  commandAction = Create-CommandXml $commandActions.$Command
$response = Send-WebRequest $url $contentParts

#.\Set-MFTWebUser.ps1 -webUserName 'TestUser' -command 'addWebUser' -webUserDescription 'Delete this user' -webUserEmail '[email protected]'
#.\Set-MFTWebUser.ps1 -webUserName 'TestUser' -command 'resetWebUserPassword' -generatePassword -emailPassword
#.\Set-MFTWebUser.ps1 -webUserName 'TestUser' -command 'deleteWebUser'
1 post Page 1 of 1