VirtualBox

Changeset 91631 in vbox for trunk/src/VBox/Devices/Network


Ignore:
Timestamp:
Oct 7, 2021 10:00:09 PM (3 years ago)
Author:
vboxsync
Message:

NAT/tftp: bugref:9350 - Redo r128102. Just reject pathnames that try
to use "..", like BSD tftpd does. Always convert backslashes into
forward slashes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Network/slirp/tftp.c

    r91627 r91631  
    7575    TFPTPSESSIONOPTDESC OptionTimeout;
    7676
     77    const char *pcszFilenameHost;
    7778    char szFilename[TFTP_FILENAME_MAX];
    7879} TFTPSESSION, *PTFTPSESSION, **PPTFTPSESSION;
     
    135136
    136137/**
    137  * This function evaluate file name.
    138  * @param pu8Payload
    139  * @param cbPayload
    140  * @param cbFileName
    141  * @return VINF_SUCCESS -
    142  *         VERR_INVALID_PARAMETER -
     138 * This function resolves file name relative to tftp prefix.
     139 * @param pData
     140 * @param pTftpSession
    143141 */
    144 DECLINLINE(int) tftpSecurityFilenameCheck(PNATState pData, PCTFTPSESSION pcTftpSession)
    145 {
    146     int rc = VINF_SUCCESS;
    147     AssertPtrReturn(pcTftpSession, VERR_INVALID_PARAMETER);
    148 
    149     /* only allow exported prefixes */
    150     if (!tftp_prefix)
    151         rc = VERR_INTERNAL_ERROR;
    152     else
    153     {
    154         char *pszFullPathAbs = RTPathAbsExDup(tftp_prefix, pcTftpSession->szFilename, RTPATH_STR_F_STYLE_HOST);
    155 
    156         if (   !pszFullPathAbs
    157             || !RTPathStartsWith(pszFullPathAbs, tftp_prefix))
    158             rc = VERR_FILE_NOT_FOUND;
    159 
    160         RTStrFree(pszFullPathAbs);
    161     }
     142DECLINLINE(int) tftpSecurityFilenameCheck(PNATState pData, PTFTPSESSION pTftpSession)
     143{
     144    int rc = VERR_FILE_NOT_FOUND; /* guilty until proved innocent */
     145
     146    AssertPtrReturn(pTftpSession, VERR_INVALID_PARAMETER);
     147    AssertReturn(pTftpSession->pcszFilenameHost == NULL, VERR_INVALID_PARAMETER);
     148
     149    /* prefix must be set to an absolute pathname.  assert? */
     150    if (tftp_prefix == NULL || RTPathSkipRootSpec(tftp_prefix) == tftp_prefix)
     151        goto done;
     152
     153    /* replace backslashes with forward slashes */
     154    char *s = pTftpSession->szFilename;
     155    while ((s = strchr(s, '\\')) != NULL)
     156        *s++ = '/';
     157
     158    /* deny attempts to break out of tftp dir */
     159    if (RTStrStartsWith(pTftpSession->szFilename, "../"))
     160        goto done;
     161
     162    const char *dotdot = RTStrStr(pTftpSession->szFilename, "/..");
     163    if (dotdot != NULL && (dotdot[3] == '/' || dotdot[3] == '\0'))
     164        goto done;
     165
     166    char *pszPathHostAbs;
     167    int cbLen = RTStrAPrintf(&pszPathHostAbs, "%s/%s",
     168                           tftp_prefix, pTftpSession->szFilename);
     169    if (cbLen == -1)
     170        goto done;
     171
     172    LogRel2(("NAT: TFTP: %s\n", pszPathHostAbs));
     173    pTftpSession->pcszFilenameHost = pszPathHostAbs;
     174    rc = VINF_SUCCESS;
     175
     176  done:
    162177    LogFlowFuncLeaveRC(rc);
    163178    return rc;
     
    254269DECLINLINE(void) tftpSessionTerminate(PTFTPSESSION pTftpSession)
    255270{
     271    if (pTftpSession->pcszFilenameHost != NULL)
     272    {
     273        RTStrFree((char *)pTftpSession->pcszFilenameHost);
     274        pTftpSession->pcszFilenameHost = NULL;
     275    }
     276
    256277    pTftpSession->fInUse = 0;
    257278}
     
    378399
    379400 found:
    380     memset(pTftpSession, 0, sizeof(*pTftpSession));
     401    if (pTftpSession->pcszFilenameHost != NULL)
     402    {
     403        RTStrFree((char *)pTftpSession->pcszFilenameHost);
     404        // pTftpSession->pcszFilenameHost = NULL; /* will be zeroed out below */
     405    }
     406    RT_ZERO(*pTftpSession);
     407
    381408    memcpy(&pTftpSession->IpClientAddress, &pcTftpIpHeader->IPv4Hdr.ip_src, sizeof(pTftpSession->IpClientAddress));
    382409    pTftpSession->u16ClientPort = pcTftpIpHeader->UdpHdr.uh_sport;
     
    437464}
    438465
    439 DECLINLINE(int) pftpSessionOpenFile(PNATState pData, PTFTPSESSION pTftpSession, PRTFILE pSessionFile)
    440 {
    441     char szSessionFilename[TFTP_FILENAME_MAX];
    442     ssize_t cchSessionFilename;
     466DECLINLINE(int) pftpSessionOpenFile(PTFTPSESSION pTftpSession, PRTFILE pSessionFile)
     467{
    443468    int rc;
    444469    LogFlowFuncEnter();
    445470
    446     cchSessionFilename = RTStrPrintf2(szSessionFilename, TFTP_FILENAME_MAX, "%s/%s", tftp_prefix, pTftpSession->szFilename);
    447     if (cchSessionFilename > 0)
    448     {
    449         LogFunc(("szSessionFilename: %s\n", szSessionFilename));
    450         if (RTFileExists(szSessionFilename))
    451         {
    452             rc = RTFileOpen(pSessionFile, szSessionFilename, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
    453         }
    454         else
     471    if (pTftpSession->pcszFilenameHost == NULL)
     472    {
     473        rc = VERR_FILE_NOT_FOUND;
     474    }
     475    else
     476    {
     477        rc = RTFileOpen(pSessionFile, pTftpSession->pcszFilenameHost,
     478                        RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
     479        if (RT_FAILURE(rc))
    455480            rc = VERR_FILE_NOT_FOUND;
    456481    }
    457     else
    458         rc = VERR_FILENAME_TOO_LONG;
    459482
    460483    LogFlowFuncLeaveRC(rc);
     
    462485}
    463486
    464 DECLINLINE(int) tftpSessionEvaluateOptions(PNATState pData, PTFTPSESSION pTftpSession)
     487DECLINLINE(int) tftpSessionEvaluateOptions(PTFTPSESSION pTftpSession)
    465488{
    466489    int rc;
     
    470493    LogFlowFunc(("pTftpSession:%p\n", pTftpSession));
    471494
    472     rc = pftpSessionOpenFile(pData, pTftpSession, &hSessionFile);
     495    rc = pftpSessionOpenFile(pTftpSession, &hSessionFile);
    473496    if (RT_FAILURE(rc))
    474497    {
     
    569592
    570593    u16BlkSize = (uint16_t)pcTftpSession->OptionBlkSize.u64Value;
    571     rc = pftpSessionOpenFile(pData, pcTftpSession, &hSessionFile);
     594    rc = pftpSessionOpenFile(pcTftpSession, &hSessionFile);
    572595    if (RT_FAILURE(rc))
    573596    {
     
    639662    int rc;
    640663
    641     rc = tftpSessionEvaluateOptions(pData, pTftpSession);
     664    rc = tftpSessionEvaluateOptions(pTftpSession);
    642665    if (RT_FAILURE(rc))
    643666    {
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette