Fossil

Check-in [1f63db59]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix the SSH sync protocol to avoid "ssh" command-line option injection attacks such as those fixed in Git 2.14.1, Mercurial 4.2.3, and Subversion 1.9.7. As "ssh://" URLs cannot be buried out of sight in Fossil, the vulnerability does not appear to be as severe as in those other systems.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256:1f63db591c77108cd722fd9ededaabf65e238f21d82b42ffbc19f0eb4f5eed3d
User & Date: drh 2017-08-11 15:29:56
Original Comment: Fix the SSH sync protocol to avoid "ssh" command-line option injection attacks such as those fixed in Git 2.14.1 and Mercurial 4.2.3.
Context
2017-08-11
16:00
Increase the version number to 2.4 and update the change log. check-in: 3ebbe7bc user: drh tags: trunk
15:29
Fix the SSH sync protocol to avoid "ssh" command-line option injection attacks such as those fixed in Git 2.14.1, Mercurial 4.2.3, and Subversion 1.9.7. As "ssh://" URLs cannot be buried out of sight in Fossil, the vulnerability does not appear to be as severe as in those other systems. check-in: 1f63db59 user: drh tags: trunk
2017-08-07
20:22
Hyperlinks to the SSL versions of the website. Redirect to the local unversioned source for the "precompiled binaries" link on the homepage. check-in: b130b64c user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/http_transport.c.

71
72
73
74
75
76
77













78
79
80
81
82
83
84
...
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
  if( pnSent ) *pnSent = transport.nSent;
  if( pnRcvd ) *pnRcvd = transport.nRcvd;
  if( resetFlag ){
    transport.nSent = 0;
    transport.nRcvd = 0;
  }
}














/*
** Default SSH command
*/
#ifdef _WIN32
static const char zDefaultSshCmd[] = "plink -ssh -T";
#else
................................................................................
  if( pUrlData->user && pUrlData->user[0] ){
    zHost = mprintf("%s@%s", pUrlData->user, pUrlData->name);
  }else{
    zHost = mprintf("%s", pUrlData->name);
  }
  n = blob_size(&zCmd);
  blob_append(&zCmd, " ", 1);
  shell_escape(&zCmd, zHost);
  blob_append(&zCmd, " ", 1);
  shell_escape(&zCmd, mprintf("%s", pUrlData->fossil));
  blob_append(&zCmd, " test-http", 10);
  if( pUrlData->path && pUrlData->path[0] ){
    blob_append(&zCmd, " ", 1);
    shell_escape(&zCmd, mprintf("%s", pUrlData->path));
  }
  if( g.fSshTrace ){
    fossil_print("%s\n", blob_str(&zCmd)+n);  /* Show tail of SSH command */
  }
  free(zHost);
  popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid);
  if( sshPid==0 ){







>
>
>
>
>
>
>
>
>
>
>
>
>







 







|





|







71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
...
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
  if( pnSent ) *pnSent = transport.nSent;
  if( pnRcvd ) *pnRcvd = transport.nRcvd;
  if( resetFlag ){
    transport.nSent = 0;
    transport.nRcvd = 0;
  }
}

/*
** Remove leading "-" characters from the input string.
**
** This prevents attacks that try to trick a victim into using
** a ssh:// URI with a carefully crafted hostname of other
** parameter that ends up being interpreted as a command-line
** option by "ssh".
*/
static const char *stripLeadingMinus(const char *z){
  while( z[0]=='-' ) z++;
  return z;
}

/*
** Default SSH command
*/
#ifdef _WIN32
static const char zDefaultSshCmd[] = "plink -ssh -T";
#else
................................................................................
  if( pUrlData->user && pUrlData->user[0] ){
    zHost = mprintf("%s@%s", pUrlData->user, pUrlData->name);
  }else{
    zHost = mprintf("%s", pUrlData->name);
  }
  n = blob_size(&zCmd);
  blob_append(&zCmd, " ", 1);
  shell_escape(&zCmd, stripLeadingMinus(zHost));
  blob_append(&zCmd, " ", 1);
  shell_escape(&zCmd, mprintf("%s", pUrlData->fossil));
  blob_append(&zCmd, " test-http", 10);
  if( pUrlData->path && pUrlData->path[0] ){
    blob_append(&zCmd, " ", 1);
    shell_escape(&zCmd, mprintf("%s", stripLeadingMinus(pUrlData->path)));
  }
  if( g.fSshTrace ){
    fossil_print("%s\n", blob_str(&zCmd)+n);  /* Show tail of SSH command */
  }
  free(zHost);
  popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid);
  if( sshPid==0 ){