/dev/random not accessible from within sandbox
Categories
(Core :: Security: Process Sandboxing, defect, P5)
Tracking
()
People
(Reporter: jjindrak, Unassigned)
Details
Attachments
(1 file)
1.01 KB,
patch
|
Details | Diff | Splinter Review |
User Agent: Mozilla/5.0 (X11; Linux x86_64; rv:72.0) Gecko/20100101 Firefox/72.0
Steps to reproduce:
Steps to reproduce provided to me by a customer that later verified the patch:
- Set up HUB server for node server to register to and to be used to run selenium tests against node server (I used a windows workstation for this step but SLES server can be used)
a. Create a directory on hub server that has the selenium jar file selenium-server-standalone-3.141.59.jar (downloaded from https://www.selenium.dev/downloads/ )
b. Launch a HUB from above directory(done from server with ip address 137.65.132.133):
java -jar selenium-server-standalone-3.141.59.jar -role hub -port 4444
c. To verify whether the hub is running or not using Firefox browser. Open Firefox and navigate to below link :
http://137.65.132.133:4444/grid/console
- Set up a Node server on SLES 12 SP2 to register to the hub (ip address of the node is 137.65.133.28 )
a. Create a directory on node that has selenium jar file and geckodriver file below:
geckodriver (downloaded from https://github.com/mozilla/geckodriver/releases/tag/v0.24.0 -- file is .tar.gz file, need to run gunzip and then tar -xvf to get to "geckodriver" file referenced in the register command below)
selenium-server-standalone-3.141.59.jar (downloaded from https://www.selenium.dev/downloads/ )
b. Register node to the hub using below command:
java -jar -Dwebdriver.gecko.driver=geckodriver selenium-server-standalone-3.141.59.jar -role node -timeout 21600 -hub http://137.65.132.133:4444/grid/register/ -host 137.65.133.28
- Trigger the below java program on Hub machine (I used eclipse to run the below java program on hub against node):
package newpackage;
import org.openqa.selenium.;
import org.openqa.selenium.remote.DesiredCapabilities;
import java.net.MalformedURLException;
import java.net.URL;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.Assert;
import org.testng.annotations.;
public class NewClass {
WebDriver driver;
String baseURL, nodeURL;
@BeforeTest
public void setUp() throws MalformedURLException {
baseURL = "http://demo.guru99.com/test/guru99home/";
nodeURL = "http://137.65.132.133:4444/wd/hub";
DesiredCapabilities capability = DesiredCapabilities.firefox();
capability.setBrowserName("firefox");
capability.setPlatform(Platform.LINUX);
driver = new RemoteWebDriver(new URL(nodeURL), capability);
}
@AfterTest
public void afterTest() {
driver.quit();
}
@Test
public void sampleTest() {
driver.get(baseURL);
if (driver.getPageSource().contains("MOBILE TESTING")) {
Assert.assertTrue(true, "Mobile Testing Link Found");
} else {
Assert.assertTrue(false, "Failed: Link not found");
}
}
}
Test will fail on SLES 12 SP2 server with below error:
Fatal: no entropy gathering module detected
Redirecting call to abort() to mozalloc_abort
[Parent 102356, Gecko_IOThread] WARNING: pipe error (56): Connection reset by peer: file /home/abuild/rpmbuild/BUILD/firefox-60.6.1/ipc/chromium/src/chrome/common/ipc_channel_posix.cc, line 342
###!!! [Parent][MessageChannel] Error: (msgtype=0x160080,name=PBrowser::Msg_Destroy) Channel error: cannot send/recv
A content process crashed and MOZ_CRASHREPORTER_SHUTDOWN is set, shutting down
console.log: Accessibility service init or shutdown observer does not exist.
FYI: For downloading selenium jars and gecko driver, below links can be referred :
https://www.selenium.dev/downloads/
https://github.com/mozilla/geckodriver/releases/tag/v0.24.0
Below link can be referred for additional detailed instructions on Selenium execution :
https://www.guru99.com/introduction-to-selenium-grid.html
Actual results:
Selenium/Firefox crashed. The reason for this is that libgcrypt (or rather libgcrypt-hmac) performs self-tests in fips mode and tries to access /dev/random, which isn't accessible in the sandbox.
Previously, /dev/urandom was added to the sandbox in bug 1372428 as part of https://hg.mozilla.org/mozilla-central/rev/52e1b27c1cb085997440183cf28686c36f5591b3 (I cannot access the bug to verify, I'm merely judging from the commit itself).
Expected results:
Selenium/Firefox not crashing. I am attaching a proposed patch that adds /dev/random to the sandbox (as I assumed that would not be a problem given /dev/urandom is already accessible.
Reporter | ||
Comment 1•5 years ago
|
||
Note: I reported this against the 68esr branch, which is the one we got the report for, but this should be affecting the latest branch too.
Comment 2•5 years ago
|
||
Bugbug thinks this bug should belong to this component, but please revert this change in case of error.
Updated•5 years ago
|
Comment 3•5 years ago
|
||
as I assumed that would not be a problem given /dev/urandom is already accessible
So, that's the thing: we're not entirely sure about that! /dev/urandom is non-blocking. /dev/random is blocking until the entropy pool is filled. At least one of Firefox's sandboxes tries to be robust in the face of hostile code trying to fingerprint users (the DRM modules in the CDM). The concern is now that it's not entirely obvious that being able to observe /dev/random refilling wouldn't be a side channel attack. It's not too far-fetched: one of the inputs to it is known to be keystroke interrupts, and it's been demonstrated that having the timing on those is enough to read the keyboard inputs with some degree of reliability.
This appears to have been fixed as of Linux 5.6, where /dev/random just behaves like /dev/urandom. But we need to behave safely on older versions too.
That brings up the second point: at this point in time, software reading /dev/random is a huge red flag. I'm not clear how (and where, which is relevant to exactly what the sandbox needs to protect against) we can end up relying on "libgcrypt (or rather libgcrypt-hmac) fips mode" when being run through Selenium - and presumably not in other use cases. A full stack for the crash might be useful.
I suspect that allowing /dev/random would be OK for the content process (Which likely has more than enough side channels for an attack such as the above...but maybe not so much after Fission ships?), and I'd be surprised if Selenium in the described use case would somehow end up using the CDM/DRM processes and modules. This could be verified by removing the second part of your patch (i.e. the change in the SandboxBrokerPolicyFactory constructor), which would limit the extra permission to content processes only.
An alternative approach would be to remap /dev/random to /dev/urandom in the sandbox. But that's a bit more work.
Lastly, as a local workaround, one could set the "security.sandbox.content.read_path_whitelist" preference to include /dev/random.
Comment 4•5 years ago
|
||
Jaroslav, how did you end up with a Firefox that is "relying on "libgcrypt (or rather libgcrypt-hmac) fips mode"? See also the note above about his probably being acceptable in the content sandbox, but not the one for CDM modules.
Comment 5•5 years ago
•
|
||
A crash report or gdb dump of the offending calling stack might help. We're not really expecting to call libgcrypt in Firefox as we rely on NSS, so understanding who the caller is would help.
Reporter | ||
Comment 6•5 years ago
|
||
Hi, sorry for the late response. I asked a person with a reproducer to try your last suggested workaround (through the read_path_whitelist config option) and did not want to come back before I have results. I'm afraid the stack won't be of much use as it is triggered on libgcrypt's dynamic load (they are automatically triggered self-tests):
#0 mozalloc_abort (msg=msg@entry=0x55d2df4d16d8 "Redirecting call to abort() to mozalloc_abort\n")
at /usr/src/debug/firefox-68.5.0/memory/mozalloc/mozalloc_abort.cpp:33
#1 0x000055d2df4b5e20 in abort () at /usr/src/debug/firefox-68.5.0/memory/mozalloc/mozalloc_abort.cpp:79
#2 0x00007f2d9db30f24 in _gcry_logv (level=level@entry=40, fmt=0x7f2d9dbf1620 "no entropy gathering module detected\n",
arg_ptr=arg_ptr@entry=0x7ffffdd90938) at misc.c:142
#3 0x00007f2d9db31294 in _gcry_log_fatal (fmt=<optimized out>) at misc.c:230
#4 0x00007f2d9dbc341d in getfnc_gather_random () at random-csprng.c:1163
#5 initialize () at random-csprng.c:333
#6 0x00007f2d9dbc39c5 in _gcry_rngcsprng_initialize (full=full@entry=1) at random-csprng.c:360
#7 0x00007f2d9dbc2878 in _gcry_random_initialize (full=full@entry=1) at random.c:159
#8 0x00007f2d9dbc2c1a in _gcry_create_nonce (buffer=buffer@entry=0x7f2da1f74020, length=length@entry=32) at random.c:444
#9 0x00007f2d9dbcff88 in _gcry_mpi_randomize (w=0x7f2da1f0cf20, nbits=<optimized out>, level=<optimized out>) at mpiutil.c:607
#10 0x00007f2d9dba2ed1 in secret_core_crt (U=0x7f2da1df4f20, Q=0x7f2da1df4f00, P=0x7f2da1df4ee0, Nlimbs=<optimized out>, D=0x7f2da1df4ec0, C=0x7f2da1df4c00,
M=0x7f2da1df4f60) at rsa.c:1125
#11 secret (output=0x7f2da1df4f60, input=0x7f2da1df4c00, skey=<optimized out>) at rsa.c:1178
#12 0x00007f2d9dba3255 in rsa_sign (r_sig=0x7ffffdd90c28, s_data=<optimized out>, keyparms=0x7f2da036cc00) at rsa.c:1593
#13 0x00007f2d9db4097d in _gcry_pk_sign (r_sig=r_sig@entry=0x7ffffdd90c28, s_hash=0x7f2da1dd4200, s_skey=<optimized out>) at pubkey.c:433
#14 0x00007f2d9dba1fad in selftest_sign_2048 (pkey=0x7f2da036b800, skey=<optimized out>) at rsa.c:1812
#15 0x00007f2d9dba2506 in selftests_rsa (report=0x7f2d9db37860 <reporter>) at rsa.c:2047
#16 run_selftests (algo=<optimized out>, extended=<optimized out>, report=0x7f2d9db37860 <reporter>) at rsa.c:2080
#17 0x00007f2d9db41549 in _gcry_pk_selftest (algo=<optimized out>, algo@entry=1, extended=extended@entry=0, report=report@entry=0x7f2d9db37860 <reporter>)
at pubkey.c:958
#18 0x00007f2d9db383aa in run_pubkey_selftests (extended=<optimized out>) at fips.c:572
#19 _gcry_fips_run_selftests (extended=extended@entry=0) at fips.c:784
#20 0x00007f2d9db2ed49 in global_init () at global.c:135
#21 0x00007f2dba6ec1ea in call_init.part () from /lib64/ld-linux-x86-64.so.2
#22 0x00007f2dba6ec2d3 in _dl_init () from /lib64/ld-linux-x86-64.so.2
#23 0x00007f2dba6f0718 in dl_open_worker () from /lib64/ld-linux-x86-64.so.2
#24 0x00007f2dba6ec0a4 in _dl_catch_error () from /lib64/ld-linux-x86-64.so.2
#25 0x00007f2dba6efe7b in _dl_open () from /lib64/ld-linux-x86-64.so.2
I don't think the linkage itself is done through Firefox. Our firefox does not require libgcrypt (AFAIK) and I think it is added through Selenium (would need to confirm, though). Charles, could you confirm?
Comment 7•5 years ago
|
||
Jaroslav, you are correct. Our Firefox builds do not link to libgcrypt.
Reporter | ||
Comment 8•5 years ago
|
||
My apologies for the delays, I got lost in some other bugs and was not able to properly investigate.
We have tried your suggested workaround (security.sandbox.content.read_path_whitelist) and while I believe that does exactly what is needed, it does not work in this case. My guess would be selenium uses a blank firefox profile without this option so I will have to look into the possibilities of injecting it into selenium to properly test it.
However, I am now sure the culprit here is not firefox, but rather selenium. To be more specific, java that runs selenium. I have found the following list of dependencies (SLES12SP2 rpms/libs):
- selenium
- java-1_8_0-ibm
- javapackages-tools
- libxslt-tools
- libxslt.so.1 (provided by libxslt1)
- libgcrypt.so.20 (provided by libgcrypt20-32bit)
- HMAC integrity check
- /dev/random
As such, I will be closing this as invalid, but I will make sure to update the bug once I resolve the issue in case other firefox users encounter this in the future. Thank you very much for your help!
Description
•