Installing WordPress on OpenBSD 6.0 with Httpd

Introduction

In the previous posts, we setup a minimal but secure web server using OpenBSD 6.0. In this post, we start from a fresh install with httpd, MariaDB and PHP 5.6.23 setup on the host. In most cases, you may now want to install a web application on it. One of the most popular is WordPress. If you have followed all the steps in the previous tutorial, installing WordPress will be fairly easy. However, because the web server is sand boxed in OpenBSD, many issues can arise. Additionally, introduction of new application may also introduce new security concerns. In this tutorial, we go through the basics of setting the database and configuring the application. We’ll also assume that you have the networking aspect configured and working. You can also consult the accompanying video.

Setting Up WordPress 4.7 on OpenBSD 6.0

To install WordPress on OpenBSD 6.0 using the native httpd web server requires quite a few steps, but most are straightforward and requires only some Linux command shell knowledge. It’s a good idea to be well-versed in the Bash scripting language and basic Linux/OpenBSD knowledge. In any case, following the steps below will get you going with your new WordPress blog in no time.

Downloading WordPress

Once validated, unzip and untar the archive into your web root directory, likely /var/www/htdocs using:

This will untar all files into /var/www/htdocs/wordpress. Feel free to rename the wordpress directory to anything you’d like.

Configuring the Database

In previous post, we installed MariaDB and thus this section will assume you have installed this database application. Otherwise, refer to the documentation of your database to use the proper SQL statements to create databases, users and manage permissions.

Log into the MariaDB database using  mysql -u root -p your_password . If you are logging from a remote location, use the  -h host argument. Once logged in, we will conduct 3 steps:

    1. Create a database for the WordPress application:

    1. Create a user for WordPress to use in order to connect to the database by using the following SQL statement:

    1. Grant permissions to the new user in order to edit the database and tables as required:

Now, the WordPress application has a place to store data on our database. Before we proceed thought, I encourage you to look at the ~/.mysql_history for a glimpse of what happened while you were doing the steps above. As you will see, the password for the user has been logged into this file. Remove this file with rm ~/.mysql_history  and let’s disable logging to prevent such leaks by adding this line in your rc.conf.local file:

Installing WordPress

From a remote host, use your favorite browser and go to https://<your_address>/wordpress/ and the installer should popup automatically. The first step is create the configuration file by filling information about the database. So gather the following information, which we have from the previous section and click “Let’s Go“:

  1. Database name: Database name use with the “CREATE DATABASE” SQL statement, i.e. “db_wordpress
  2. Database username: Username enter in the “CREATE USER” SQL statement, i.e. “wp_user
  3. Database password: type in your password;
  4. Database host; Enter 127.0.0.1 or ::1. Do not leave it as “localhost” as we want to use the sockets;
  5. Table prefix; Prefix for each table created. Unless you plan to have multiple WordPress sites, leave the default value.
Wordpress Installer Welcome Page
The WordPress Installer will guide you step-by-step on setting it up.

On the next page, enter the required data and click “Submit“. If every thing is setup right, you will be prompted to continue with the setup of the site. However, you may also get a blank “step2” page, i.e. the URL will be “setup-config.php?step=2” but nothing will show up. This problem can be caused by many different things. First, make sure you have setup PHP to use your MySQL database by enabling the proper extensions in the php-5.6.ini configuration file. See previous post for an explanation on how to do this.

Next issue you may encounter is a warning that WordPress cannot create the wp-config.php file. This is mostly due to permissions issues with /var/www/htdocs/wordpress/. The best option is to manually create the file by copy-pasting its contents. Another alternative is to temporarily change the permissions of the directory to allow write permissions with  chmod 777 /var/www/htdocs/wordpress for the installer to create the file. Doing so allows anyone to write and execute code to your directory and as such, it must be change immediately after you are finished installing and configuring WordPress.

Wordpress Fail to Create Wp-config.php
WordPress warns that it could not create the wp-config.file.

Quick Hardening

Before calling “Mission Accomplished”, take some time to test your new site and set the proper file permissions. Create a test post and try to upload an image to it. You may find that it fails, again because of permission issues. According to [1], you should have the following permissions for your WordPress install:

  • Folder set to 755;and
  • Files set to 644, except wp-config.php should be 440 or 400

This can be done with the following commands;

Furthermore, note the following quote from [1]:

No directories should ever be given 777, even upload directories. Since the php process is running as the owner of the files, it gets the owners permissions and can write to even a 755 directory.

Meaning that you should avoid the temptation to solve your uploads issues, or any other issues by setting full permissions, even the upload folder. Based on [2], all files outside the wp-content directory should be owned by your OpenBSD user account so they cannot be modified. The owner of the wp-content will be set to www and will be writable, allowing uploads of files themes and plugins. Note that once you chose your theme and plugins, you could further harden your blog by restricting the wp-content/themes and wp-content/plugins directories as some attackers hide web shells in those.

Retest to make sure it works.

Upload Failures due to Directory Permissions
Setting the minimal and proper permissions on the Uploads directory is critical.

One last quick thing you may want to do is delete unneeded installation files.  WordPress should have remove them for you, but just double check. You can also remove the readme.html and any release notes that may be present, this way, it will be harder for an attacker to find the version of your WordPress installation.

Conclusion

WordPress becomes insecure when adding plugins, which introduces the majority of new vulnerabilities. As such, attempt to avoid unnecessary plugins and themes and uninstall them once they are unneeded. Also enable auto-updates. There are quite further actions you can take to harden your WordPress install, and I’d recommend reading the reference at [1]. You can also review the database permissions you have granted to the “wp_user” in MariaDB, and possibly restrict them to simply INSERT/UPDATE/SELECT/DELETE instructions. Then test your installation with wp-scan, a great, free and open-source WordPress vulnerability assessment.

References

[1] Hardening WordPress, Core Directories/Files, WordPress.org, https://codex.wordpress.org/Hardening_WordPress (accessed on 2017-01-09)

[2] Correct File Permissions for WordPress, StackOverflow, http://stackoverflow.com/questions/18352682/correct-file-permissions-for-wordpress, (accessed on 2017-01-16)

See Also

Secure WebServers with OpenBSD 6.0 – Setting Up Httpd, MariaDB and PHP

Introduction

In this tutorial, we setting up a web server on OpenBSD 6.0 using the native httpd web server, MariabDB and PHP. There can be quite a few issues popping up unlike other systems, mostly due to the fact that the web server is “chroot jailed” during execution. In other words, the web server is sandboxed and cannot access other parts of the operating system, which requires more work than other similar setups on other distributions. However, this greatly decreases the damages if your server gets whacked. In this post, we setup a minimal web server that will allow you to host simple web content. I’ll assume you have an OpenBSD 6.0 VM created with root access to it. From there, we will stand up our web server with HTTPS, install MariaDB and PHP. Please note that this tutorial is not meant for professional/commercial settings, but for personal and educational uses. A video version of this tutorial is also available.

Standing up a Minimal Web Server with Httpd

The strategy we will employ is to create a very minimal web server, test if it works as intended, and then enable additional features as we go along. So first, we’ll start by enabling the httpd daemon. To do so, first copy the httpd.conf file from /etc/examples/httpd.conf to /etc/ by typing  cp /etc/examples/httpd.conf /etc . Open the copied file as root using vi or another text editing tool if you have any install. In the file, you will delete all the examples provided and only keep the “minimal web server” and “types” sections:

Make sure you save your changes and now start your web server with the following command:  /etc/rc.d/httpd -f start . Make sure you include the  -f , other you may get an error message. We will fix this later. If everything goes well, you should get an “httpd(ok)” message. Otherwise, there is likely an error in your configuration file. You can confirm by using  httpd -n .

Let’s confirm everything works so far. Retrieve your IP address using  ifconfig em0 and using another host on your network, browse to http://<your_ip>. If everything works as expected, you will see something similar to the figure below:

OpenBSD WebServer - 403 Forbidden
Receiving a 403 Forbidden error from the OpenBSD web server.

We received a 403 error because we do not have any web pages created yet and by default, httpd prevents directory listing – which is a good thing. So let’s create a quick index.html web page. Use the following command  vi /var/www/htdocs/index.html and type the following:

Save the file and point your browser to http://<your_ip>/index.html. You should see your web page. If not, make sure you created the file in /var/www/htdocs and you haven’t made a typo in your URL. Also note that if you go to http://<your_ip>/, you will also end up on your web page. By default httpd looks for “index.html” and serves this web page when none is specified.

Fantastic. We got ourselves a web server. But not a very secure or useful one unless you want to host Geocities-like webpages. Next, we will enable HTTPS on our web server and redirect all traffic to it. We’ll need to do this in 2 steps:

  1. Create a certificate for your web server; and
  2. Setup httpd to use your certificate and HTTPS

First, we’ll need to generate a SSL private key. This is straightforward by using openssl:

The server.key file is your private key and must be secured! It’s very important that nobody else other than you have access to it. Next, we will use this key to generate a self-signed certificate. This is also done by using openssl:

The command above basically requests OpenSSL to generate a certificate (server.crt) using our private key (server.key) that will be valid for 365 days. Afterwards, you will be asked a couple of questions to craft the certificate. Since this is self-signed, feel free to enter anything. Once done, the first step is completed. Next, we will modify our configuration file again and update out minimal web server to tell it to use HTTPS:

Every time your modify the httpd.conf file, you will need to restart your web server for the changes to take effect. Use  /etc/rc.d/httpd -f restart do so and test your website again, this time using https://<your_ip>. You should be greeted with a warning message fro your browser, warning you that it cannot validate the certificate. That’s because it is self-signed. Click on “Advanced” and add it to the exceptions. Afterwards, you will be serve our web page via an encrypted link.

Web Server Certificate Exception
Receiving a warning from the browser on self-signed certificate.

So at this point, we have a functioning web server over HTTPS. However, unencrypted communications are still enabled. We would like to have ALL users over HTTPS. This can be done by replacing this line in httpd.conf:

with

Anyone using http://<your_site> will be automatically redirected to https://<your_site>.

Setting Up MariaDB

Installing the database is quite simple in contrast with many other activities we need to do. First, we’ll need to download some packages, so make sure you have the PKG_PATH environment defined with a mirror containing the packages you need. If not, select a mirror on openbsd.org and define your variable:

And as root, install the mariadb-server package:

Once completed, install the database using the included script by typing  mysql_install_db and when completed, start the mysqld daemon:  /etc/rc.d/mysqld -f start . The last step is to configure it by running the  mysql_secure_installation . The script will ask you a couple of questions:

  1. First, it will ask you to set a password for root. Choose a good password. Long simple passwords can be more efficient than short complex one that you won’t remember;
  2. It will then ask if it should remove anonymous users. Select “Y” to remove them;
  3. When asked if it should disallow remote root access, answer by the positive to prevent root access from remote hosts;
  4. Choose to remove all test databases; and
  5. Press “Y” to reload all privileges in the database application.

You are now done with installing the database. Before moving on to the next section, confirm that everything is working by login into MariaDB:

If everything went fine, you will be given access to the database engine. Type  quit; to exit the application.

Setting Up PHP

The last step of this tutorial involve downloading and install PHP. Very few webpages nowadays rely solely on static HTML, and I suspect most will want to install web applications later on, so let’s setup PHP. First, download some of the required packages. Note that additional packages may be needed depending on the web applications you wish to install later on, but for now, let’s setup the core PHP packages:

There are several versions of PHP available on the OpenBSD repository. What is important is that you select the same version for all packages you install. For example, at the time of writing version 5.6.23 and 7.0.8 were available, but php-mysql 7.0.8 was not, thus we select 5.6.23 for all PHP packages to prevent issues later one. Dismiss any packages ending with “-ap2” as these are for the Apache web server. For the purpose of this tutorial, we will select version 5.6.23 every time we are asked.

Before starting up PHP, we have a couple of things to do. First, we need to tell httpd to send PHP pages to the PHP processor. We also need to specify the PHP processor that we have a database it needs to be aware of. So let’s start by modifying our httpd.conf file again by adding a section about .php files. Also, we’ll add a “directory” section to tell the web server to look for “index.php” files first instead of “index.html“:

Next, let’s modify the PHP configuration file to enable MySQL. We do so by adding extensions to the /etc/php5.6.ini file. Open this file as root and add the following lines under the “Dynamic Extensions” section:

Since we modified configuration files, we’ll need to restart the httpd and php-fpm daemons. Do so with  /etc/rc.d/httpd -f restart and  /etc/rc.d/php56-fpm start . Hopefully, you will get “httpd(ok)” and “php56_fpm(ok)”. Otherwise, you may have introduce a typo in your configuration files or some packages may have not downloaded/installed properly.

Wrapping Up

One last thing we will do before calling it quit for today, is to make sure the httpd, php56-fpm and mysqld services are started on bootup of OpenBSD. To do so create a new rc.conf.local file in /etc/ using  vi /etc/rc.conf.local and type the following in it:

At startup, OpenBSD will use this file to initiate the services and the PKG_PATH environment variable. You will not have to use the  -f anymore when restarting the httpd daemon.

Conclusion

So in this post, we have enabled a HTTPS web server, along with a MariaDB and PHP, allowing use to serve dynamic content on a OpenBSD 6.0 machine. At this point, you should be able to host basic dynamic content. However, if you try to install more complex web applications, you will need an extra few steps in many cases. Sometimes, you will need additional packages and extra work to connect to the database via your web application. In the next tutorial, we will install WordPress to show some of the difficulties you may encounter with the chroot jail and file permissions of the web root.

See Also

The Byte-BOS Real-Time Multitasking Operating System

Compared to operating systems in general computing, the world of embedded devices remains a world to be discovered by security analysts and hackers alike, and it offers much to explore. While reverse engineering of many newer appliances is revealing well known operating systems such as Windows or Linux, others remains fairly unexplored, such as TinyOS or μOS. Legacy devices, still in used across many industries, also provide a rich variety of unknown software and architectures. One of them is the Byte-BOS Real-Time Multitasking Operating System (RTMOS).

Introduction

Compared to operating systems in general computing, the world of embedded devices remains a world to be discovered by security analysts and hackers alike, and it offers much to explore. While reverse engineering of many newer appliances is revealing well known operating systems such as Windows or Linux, others remain fairly unexplored, such as TinyOS or μOS. Legacy devices, still in use across many industries, also provide a rich variety of unknown software and architectures. One of them is the Byte-BOS Real-Time Multitasking Operating System (RTMOS). This short article attempts, based on limited information, to detail this little known system, explore its history, usage and basic composition.

History

The Byte-BOS RTMOS was initially developed in 1994 by Numerical Services Inc. The company, defunct since 2004, sold the full C source code of the RTMOS to customers for 7495 $USD. Possession of the source code allowed the buyer full customization of the operating system according to the device being designed. The system supported a restricted set of microcontrollers (see table 1) including the Intel x86 and Motorola M68000. Other lesser known microprocessors supported included architectures from Hitachi, Mitsubishi and Texas Instruments, which were used in embedded devices within the medical, industrial and telecommunications sectors. Due to the long life-cycle of these devices, it may still be possible to identify devices leveraging the Byte-BOS RTMOS. Development and support for the RTMOS ceased around 2004. As such, documentation is very scarce, and remnants of information are available only via the Internet Archive [1]. At the time of writing, the domain “www.bytebos.com” resolves to “Scheumacher Engineering”, owned by the original developer of Byte-BOS. However the website is nothing more than a single page which was last updated in 2013.

Table 1 – Microprocessors supported by the Byte-BOS RTMOS.
Intel 80×86 Coldfire Mitsubishi M16C Texas Instruments
C2x/C5x DSP
Intel 80188/86 Motorola 68000 Mitsubishi M32D Texas Instruments
C3x/C4x DSP
Intel 80×86 (32bit) Motorola 68HC11 Hitachi H8300 ARM/THUMB
Intel 8096 Motorola 68HC16 Hitachi H8300H
Intel i960 Mitsubishi
M37700
Hitachi SHX

Description

The Byte-BOS RTMOS is a minimal operating system providing task scheduling management for user applications, along with typical OS activities such as interprocess messaging, memory allocation and prioritization. It performs pre-emptive and non-pre-emptive scheduling of an unlimited number of queued tasks. The system enforces scheduling via interrupt service routines (ISRs) which can suspend and/or resume tasks based on events and their priority. When multiple tasks with a similar priority are requesting resources, the RTMOS assign the resources via a round-robin selection method.

As other operating systems, memory allocation appears to follow a standard process by keeping track of used and free memory chunks via a heap implemented by a double-linked list, which is the data structure used across the RTMOS to store unlimited numbers of objects. Tasks can dynamically allocate and free memory as needed. It also manages events and interaction with devices on behalf of user applications by abstracting the underlying hardware via a Device object (see figure 1). Byte-BOS also provides inter-tasks communications mechanisms for synchronization amongst tasks such as messages and semaphores.  In terms of data structures the double linked list and buffer objects appear to be the main structures used across the RTOS. Memory chunks, tasks and most of the other objects are all managed via the List object.  It also supports the queue structure used to manage tasks. A software stack is also provided and used by tasks to run.

Security-wise, Byte-BOS does not have any authentication or specific security methods for access to memory or special “kernel” functions; all tasks have the same level of authority than the RTOS. Basically, Byte-BOS is completely flat.

Architecture

The RTMOS is written in C or specific variety of C specification depending on the targeted microprocessor. The 10 main components of the operating systems are represented in figure 1 and provide an excellent overview of the functions accomplished. A simulated “this” pointer to the various “struct”s is made available to the developer to give an Oriented-Object Programming (OOP) feel. This section describes briefly the main components of Byte-BOS, along with some of the features marketed by the original developer.

UML Representation of the different objectsfooun in the Byte-BOS RTMOS
Figure 1 – UML Representation of the different objects defined in the Byte-BOS RTMOS

The Task Object

The main object of the RTMOS is the Task object, which is very similar to the similar concept modern software development. Just as in any C/C++ object, a constructor is initiated prior to executing the body of the task, which is defined by the developer to conduct a specific task. Data of the task is allocated and accessible via the this_data pointer. Tasks also allocate sub-objects, opens required devices, initialize variables and synchronize state machines. Once constructed, the task runs its main function until it returns or is removed. Access to a task is done via the this_task pointer. Both pointers described are always in scope and usable within the task. Once the main task completes, the destructor of the structure is called, which frees memory and pointers of sub-objects. It also terminates any internal state machine.

The Memory Object

This object manages the memory heap and stores the pointer to the heap, the block size and the number of memory blocks. It also exposes various functions for memory management, mainly alloc_fmem and free_fmem. The heap is implemented using a double-linked list in which each node contains metadata about the memory blocks. While details are not available, it can be assumed that the size of the block, its status (free or allocated) and a pointer to the next block is included.

The Semaphore Object

As its name implies, the Semaphore is used for signaling and control between multiple tasks by either being in the Up or Down status. A timeout can be defined as needed.

The MessageBox Object

The MessageBox acts as a central repository for tasks to exchange data. Tasks and ISRs can create messages to initiate other tasks or exchange . The MessageBox basically provides two functions: put and get. When a new message is created, memory is allocated. Similarly, the memory is freed when retrieved from the box.

The Timer Object

Similar to any standard timer in other system, this object is used to create timeouts and schedules of tasks and events.

The Event Object

Events are created by tasks and ISRs to schedule other tasks.

The Device Object

This item abstracts interaction between the user application and the hardware device. It does so by pointing to the memory blocks used by the device and managing input/output to the area.

The List, Queue and Buffer Objects

These objects, as their name implies, are implementation of a linked list, a queue and buffer data structures.

Features

Byte-BOS boasted the following additional features on their website from 2000, providing some extra insight on the internals of the system.

Interrupt Handling

ISRs can make operating systems calls and schedule tasks by including the ENTER_ISR and EXIT_ISR macros at the beginning and end of the routine. Most services are available to ISRs, giving them considerable access over the entire OS.

Critical Section Handling

Byte-BOS provides critical section handling by protecting non-reentrant code sections from both interrupt and task pre-emption. Protection of critical sections appears to be done via the following mechanisms:

  • Disabling interrupts
  • Locking and unlocking code sections
  • Prioritization of tasks

Task Execution Trace

Tasks are provided with a trace buffer configurable at both compile time and run time. The trace buffer contains information about the sequence of calls, the parameters passed, and the return value of the called function. The tracing option is extremely useful for debugging purposes.

System Requirements

The Byte-BOS RTMOS requires very little in terms of resources. While the requirements varies depending on the underlying processor, the size of the kernel is a few kilobytes, while the RAM requirements are less than 100 bytes of globally accessible memory and less than 100 bytes per task and ISR. The detail figures are listed in table 2.

Table 2 – Memory requirements for the Byte-BOS RTMOS according to microprocessor
Microprocessor Minimum Kernel
Size (KB)
Maximum Kernel
Size (KB)
RAM Requirement
for Global Variables
(bytes)
RAM Requirement
per Task (bytes)
Intel 80×86* 4 10 28 30
Intel 80×86
(32bit)*
6 15 48 58
Intel 80188/86* 2 10 28 30
Intel 8096 2 8 20 20
Motorola 68000 1.5 12 50 70
Motorola 68HC11 1.2 8 28 20
Motorola 68HC16 2 8 28 20
Mitsubishi M37700 2 10 28 20
Mitsubishi M16C 2 12 64 48
Mitsubishi M32D N/A N/A N/A N/A
Hitachi H8300 1.2 8 28 20
Hitachi H8300H 2 10 38 40
Hitachi SHX 7.8 19.5 72 60
Texas Instruments
C2x/C5x DSP
1.2 8 28 20
Texas Instruments
C3x/C4x DSP
2.3 19.5 28 words 20 words
ARM/THUMB 4 15 50  70

* For Intel-based architecture, the memory footprint reported above is based on usage of the Borland C++ compiler.

Additional volatile memory is required for objects created dynamically. As such, the numbers provided above do not represent the total amount of memory consumed by Byte-BOS.

Compilers Supported

In general, Byte-BOS supports the development tools and compilers provided by the semi-conductor manufacturer. For Intel-based processors, the Borland C/C++ compiler was supported. The complete list of supported compilers is provided in table 3.

Table 3 – Supported compilers by the Byte-BOS RTMOS.
Microprocessor Supported Compilers
Intel 80×86 Microsoft C/C++ (large model)
Borland C/C++
Watcom C/C++
Intel 80×86(32bit) Watcom, Metaware and most of C compilers
Intel 80188/86 Microsoft C/C++ (large model)
Borland C/C++
Intel 8096 IAR
BSO Tasking Compiler
Motorola 68000 Cross-Code
Intermetrics
Introl
Microtec
Motorola 68HC11 IAR
Introl
Cosmic
Motorola 68HC16 Introl
Cosmic
Mitsubishi M37700 IAR
Microtec
Mitsubishi M16C IAR
Mitsubishi Compiler
Mitsubishi M32D N/A
Hitachi H8300 IAR
Microtec
Hitachi H8300H IAR
Hitachi SHX GNU
Green Hills
Texas Instruments
C2x/C5x DSP
Code Composer /
Texas Instrument Compiler
Texas Instruments
C3x/C4x DSP
Code Composer /
Texas Instrument Compiler
ARM/THUMB  ARM

Identification

Devices using the Byte-BOS RTMOS can be identified by looking at ASCII and Unicode strings in their firmware. In almost all cases, if not all, the firmware will contain a copyright notice identifying it as well as the target microcontroller it was compiled for. For example, by extracting the strings from the firmware for the Seagate Cheetah 10K.6 Disc Drive, either using the simple strings.exe (or strings in Linux) or IDA, the copyright notice string “Byte-BOS 8096 Multitasking Operating System — Copyright 1990 Numerical Services Inc.” can be observed (see figure 2).

Byte-BOS Copyright Notice into the Firmware of the Seagate 10K.6 Disc Drive
Figure 2 – Byte-BOS Copyright Notice into the Firmware of the Seagate 10K.6 Disc Drive

While appliances posterior to 2004 will likely use modern RTMOS such as Linux , Byte-BOS can still be found on legacy devices. One such example is the Baxter IPump pain management medical device, which refers to its usage in the manual [2]. Of note, the manual refers to the detection of stack overflows within the Byte-BOS RTMOS. Industrial controls, aircraft, telecommunications systems and other systems designed prior to the 2000s may still harbour this little known RTMOS.

Conclusion

The Byte-BOS RTMOS will likely disappear as legacy embedded devices are life-cycled for newer systems with more processing power and extended memory. Until that moment, for developers of these systems, or simple hobbyists, information remains scarce and limited. While we provided a brief overview of its architecture and features, details about creating user applications remains obscured by the lack of online information such as an API description, code examples or more importantly, the source code. Such data would greatly ease development and engineering efforts of legacy systems.

References

[1] “Bytebos Home Page.” Bytebos Home Page. Internet Archive, 20 Oct. 2000. Web. 01 Nov. 2015. <https://web.archive.org/web/19990208011926/http://www.bytebos.com/>.

[2] Baxter IPump Pain Management System – Service Manual, Baxter Healthcare Corporation, Chapter 4 – Troubleshooting, p.4-8. 2007. Web. 01 Nov. 2015. <Link>