Difference between revisions of "PoisonTap solution"
m |
m (cats) |
||
(8 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
[[File:Poisontap.jpg|300px|right]] | [[File:Poisontap.jpg|300px|right]] | ||
− | PoisonTap is a [[Raspberry Pi]] based device that siphons cookies, exposes internal router & installs web backdoor on locked computers. It works by posing as a USB network adapter that sets itself up as an IP gateway via DHCP. This article provides instructions to set up a simple protection for this attack vector by disabling networking when the screen is locked. It works for GNU/Linux but should be easy to implement in other operating systems. | + | [http://arstechnica.com/security/2016/11/meet-poisontap-the-5-tool-that-ransacks-password-protected-computers/ PoisonTap] is a [[Raspberry Pi]] based device that siphons cookies, exposes internal router & installs web backdoor on locked computers. It works by posing as a USB network adapter that sets itself up as an IP gateway via DHCP. This article provides instructions to set up a simple protection for this attack vector by disabling networking when the screen is locked. It works for GNU/Linux but should be easy to implement in other operating systems. It works by having the simple Perl script below run when the screen saver activates and de-activates. |
− | |||
− | It | ||
<div style="clear:both"></div> | <div style="clear:both"></div> | ||
<source lang="perl"> | <source lang="perl"> | ||
#!/usr/bin/perl | #!/usr/bin/perl | ||
if( $ARGV[0] eq 'start' ) { | if( $ARGV[0] eq 'start' ) { | ||
− | + | system( "dbus-monitor --session \"type=signal,interface=org.gnome.SessionManager.Presence,member=StatusChanged\" | $0 &" ); | |
} else { | } else { | ||
while( <> ) { | while( <> ) { | ||
Line 21: | Line 19: | ||
'''Note''' that it must be launched from your desktop start up applications rather than from ''init.d'' or ''rc.local'' because it needs to run under the user session otherwise ''dbus-monitor'' can't get the information about session events. | '''Note''' that it must be launched from your desktop start up applications rather than from ''init.d'' or ''rc.local'' because it needs to run under the user session otherwise ''dbus-monitor'' can't get the information about session events. | ||
− | == | + | == Running the script on different distros == |
− | + | I'm running this script on LinuxMint 18, but the event names or values used may vary across different GNU/Linux distros. To figure out the appropriate ''dbus-monitor'' filter and the values to use in the regular expression matches that run the network commands, use the following command to observe all events as they occur, and then lock and unlock the screen and check the output to see which events to use. | |
− | + | Here's the command to observe all the ''DBus'' signals being emitted by the system: | |
− | |||
− | Here's the command to observe all the DBus signals being emitted by the system: | ||
<source> | <source> | ||
dbus-monitor --session "type=signal" | dbus-monitor --session "type=signal" | ||
</source> | </source> | ||
− | On my system this a snippet of what was outputted (it was actually about 4 times as much as this), I've highlighted the relevant lines: | + | On my system this a snippet of what was outputted (it was actually about 4 times as much as this,but I chopped it down a bit for clarity), I've highlighted the relevant lines: |
<source> | <source> | ||
signal sender=org.freedesktop.DBus -> dest=:1.63 serial=2 path=/org/freedesktop/DBus; | signal sender=org.freedesktop.DBus -> dest=:1.63 serial=2 path=/org/freedesktop/DBus; | ||
Line 63: | Line 59: | ||
interface=org.Cinnamon.LookingGlass; member=WindowListUpdate | interface=org.Cinnamon.LookingGlass; member=WindowListUpdate | ||
</source> | </source> | ||
− | This shows that the event used on my machine for | + | This shows that the event used on my machine for my session status changes has ''interface=org.gnome.SessionManager.Presence'' and ''member=StatusChanged'' and that the values for the status are ''uint 0'' or ''uint 3'' depending on whether it's locking or unlocking. You can see the screen-saver events prior to the session changes, but those events aren't quite suitable for this purpose since the unlock event fires when the password dialog first opens instead of after we've entered the correct password. We can use this to construct a more specific observation command that only outputs the relevant state changes like this: |
<source> | <source> | ||
− | dbus-monitor --session "type=signal,{!interface=org. | + | dbus-monitor --session "type=signal,{!interface=org.gnome.SessionManager.Presence,member=StatusChanged!}" |
</source> | </source> | ||
− | + | I then used this to make the script above that enables or disables the networking in response to this event and its value. I found Perl simplest for this job, because my shell scripting skills are pretty lame. In my case the start/stop depends on the value being ''uint 0'' and ''uint 3'' so I've used the simple regular expressions to match this which you can see in the ''while'' loop that scans the ''dbus-monitor'' output. | |
+ | When the script is run with the ''start'' parameter it connects itself to the relevant event notifications using the ''dbus-monitor'' command and piping its output to another instance of itself which runs in the background. | ||
− | + | On most distros these days the network is controlled by the Network Manager and you can turn it on and off with: | |
<source> | <source> | ||
nmcli nm enable [true|false] | nmcli nm enable [true|false] | ||
</source> | </source> | ||
− | + | But one some distros this may not be the best choice, some other possible options are: | |
<source> | <source> | ||
service [start|stop] networking | service [start|stop] networking | ||
Line 85: | Line 82: | ||
You need something that disables it and prevents a new device that's plugged in from functioning, but when re-enabled all devices are seen to be functioning normally again. | You need something that disables it and prevents a new device that's plugged in from functioning, but when re-enabled all devices are seen to be functioning normally again. | ||
+ | |||
+ | == Disable networking in login screen at startup == | ||
+ | One problem is that if an attacker were to restart your computer then the networking will be enabled in the initial login screen since it hasn't been disabled by a lock screen event. | ||
+ | |||
+ | To get around this you can have your network disabled initially by adding the disabling command from your script (i.e. '''nmcli nm enable false''') to your ''/etc/rc.local'' file for example. | ||
+ | |||
+ | You can also add the enable command into the ''start'' condition before the ''dbus-monitor'' line in the script so that the network starts up again once you're logged in. | ||
== See also == | == See also == | ||
*[https://samy.pl/poisontap/ Technical info] | *[https://samy.pl/poisontap/ Technical info] | ||
*[http://arstechnica.com/security/2016/11/meet-poisontap-the-5-tool-that-ransacks-password-protected-computers/ Arstechnica article] | *[http://arstechnica.com/security/2016/11/meet-poisontap-the-5-tool-that-ransacks-password-protected-computers/ Arstechnica article] | ||
+ | *[https://hackaday.com/2016/11/16/poinsontap-makes-raspberry-pi-zero-exploit-locked-computers/ Hackaday article] | ||
+ | *[http://www.techtimes.com/articles/186158/20161118/poisontap-is-a-5-exploit-tool-created-to-hack-your-locked-computer-in-1-minute.htm Techtimes article] | ||
+ | *[http://www.bbc.co.uk/news/technology-38012699 BBC news article] | ||
*[[Raspberry Pi]] | *[[Raspberry Pi]] | ||
*[[Security]] | *[[Security]] | ||
*[[SSL]] | *[[SSL]] | ||
+ | [[Category:Linux]][[Category:Hardware]] |
Latest revision as of 19:40, 20 November 2016
PoisonTap is a Raspberry Pi based device that siphons cookies, exposes internal router & installs web backdoor on locked computers. It works by posing as a USB network adapter that sets itself up as an IP gateway via DHCP. This article provides instructions to set up a simple protection for this attack vector by disabling networking when the screen is locked. It works for GNU/Linux but should be easy to implement in other operating systems. It works by having the simple Perl script below run when the screen saver activates and de-activates.
#!/usr/bin/perl
if( $ARGV[0] eq 'start' ) {
system( "dbus-monitor --session \"type=signal,interface=org.gnome.SessionManager.Presence,member=StatusChanged\" | $0 &" );
} else {
while( <> ) {
`nmcli nm enable false` if /uint32 3/;
`nmcli nm enable true` if /uint32 0/;
}
}
Contents
Installation
Just save the script anywhere and ensure that it has executable permissions, then add it to your startup programs with the start parameter. E.g. if you saved it as /home/foo/NoPoison.pl, you'd add /home/foo/NoPoison.pl start as the command in your start up apps.
Note that it must be launched from your desktop start up applications rather than from init.d or rc.local because it needs to run under the user session otherwise dbus-monitor can't get the information about session events.
Running the script on different distros
I'm running this script on LinuxMint 18, but the event names or values used may vary across different GNU/Linux distros. To figure out the appropriate dbus-monitor filter and the values to use in the regular expression matches that run the network commands, use the following command to observe all events as they occur, and then lock and unlock the screen and check the output to see which events to use.
Here's the command to observe all the DBus signals being emitted by the system:
dbus-monitor --session "type=signal"
On my system this a snippet of what was outputted (it was actually about 4 times as much as this,but I chopped it down a bit for clarity), I've highlighted the relevant lines:
signal sender=org.freedesktop.DBus -> dest=:1.63 serial=2 path=/org/freedesktop/DBus;
interface=org.freedesktop.DBus; member=NameAcquired
string ":1.63"
signal sender=:1.19 -> dest=(null destination) serial=1931 path=/org/Cinnamon/LookingGlass;
interface=org.Cinnamon.LookingGlass; member=WindowListUpdate
signal sender=:1.37 -> dest=(null destination) serial=20 path=/org/cinnamon/ScreenSaver;
interface=org.cinnamon.ScreenSaver; member=ActiveChanged
boolean true
signal sender=:1.1 -> dest=(null destination) serial=119 path=/org/gnome/SessionManager/Presence;
interface=org.gnome.SessionManager.Presence; member=StatusChanged
uint32 3
signal sender=:1.24 -> dest=(null destination) serial=892 path=/org/ayatana/NotificationItem/nm_applet/Menu;
interface=com.canonical.dbusmenu; member=LayoutUpdated
uint32 608
int32 0
signal sender=:1.24 -> dest=(null destination) serial=893 path=/org/ayatana/NotificationItem/nm_applet;
interface=org.kde.StatusNotifierItem; member=NewIcon
signal sender=:1.24 -> dest=(null destination) serial=901 path=/org/ayatana/NotificationItem/nm_applet/Menu;
interface=com.canonical.dbusmenu; member=LayoutUpdated
uint32 635
int32 0
signal sender=:1.37 -> dest=(null destination) serial=22 path=/org/cinnamon/ScreenSaver;
interface=org.cinnamon.ScreenSaver; member=ActiveChanged
boolean false
signal sender=:1.1 -> dest=(null destination) serial=123 path=/org/gnome/SessionManager/Presence;
interface=org.gnome.SessionManager.Presence; member=StatusChanged
uint32 0
signal sender=:1.19 -> dest=(null destination) serial=2055 path=/org/Cinnamon/LookingGlass;
interface=org.Cinnamon.LookingGlass; member=WindowListUpdate
This shows that the event used on my machine for my session status changes has interface=org.gnome.SessionManager.Presence and member=StatusChanged and that the values for the status are uint 0 or uint 3 depending on whether it's locking or unlocking. You can see the screen-saver events prior to the session changes, but those events aren't quite suitable for this purpose since the unlock event fires when the password dialog first opens instead of after we've entered the correct password. We can use this to construct a more specific observation command that only outputs the relevant state changes like this:
dbus-monitor --session "type=signal,interface=org.gnome.SessionManager.Presence,member=StatusChanged"
I then used this to make the script above that enables or disables the networking in response to this event and its value. I found Perl simplest for this job, because my shell scripting skills are pretty lame. In my case the start/stop depends on the value being uint 0 and uint 3 so I've used the simple regular expressions to match this which you can see in the while loop that scans the dbus-monitor output.
When the script is run with the start parameter it connects itself to the relevant event notifications using the dbus-monitor command and piping its output to another instance of itself which runs in the background.
On most distros these days the network is controlled by the Network Manager and you can turn it on and off with:
nmcli nm enable [true|false]
But one some distros this may not be the best choice, some other possible options are:
service [start|stop] networking
/etc/init.d/networking [start|stop]
if[up|down] -a
You need something that disables it and prevents a new device that's plugged in from functioning, but when re-enabled all devices are seen to be functioning normally again.
Disable networking in login screen at startup
One problem is that if an attacker were to restart your computer then the networking will be enabled in the initial login screen since it hasn't been disabled by a lock screen event.
To get around this you can have your network disabled initially by adding the disabling command from your script (i.e. nmcli nm enable false) to your /etc/rc.local file for example.
You can also add the enable command into the start condition before the dbus-monitor line in the script so that the network starts up again once you're logged in.