Resources

People often ask me "How did you learn how to hack?" The answer: by reading. This page is a collection of the blog posts and other articles that I have accumulated over the years of my journey. Enjoy!

webOS Revisited - Even More Mistaken Identities- 799

Andreas - recurity    Reference →Posted 4 Years Ago
  • WebOS is the operating system used in LG TVs. WebOS is web, but within an OS! Many things sound JavaScript-y because it is NodeJS running under the hood.
  • The Notification Manager is used by internal system services in order to manage notifications, such as alerting about system- and app updates etc. It cannot be called by regular applications and runs as root. The permission systems works based upon an allowlist of app Ids. Due to a logic flaw within notificationmgr/Settings.cpp, the notifications can be bypassing by sending a request through the luna-send-pub tool. This is not a vulnerability by itself, but does open up a new attack vector for us.
  • The luna://com.webos.notification/createAlert API of Notifications Manager allows for actions to be defined, such as onclick and many more. When calling these, there is a check to validate that the user has the proper permissions to call these APIs.
  • However, the permissions are handled on the API calls themselves via logic and not the file permissions on the operating system. It turns out that the nesting of these URIs is possible. Since the verification ONLY happens on the first URI, the verification can pass while the second call can now perform arbitrary actions. In this case, they call the normally denied luna://com.webos.service.downloadmanager/download.
  • There are MANY other ways to compromise the system with other calls. The important note is that not all of the data was properly verified on the request, which leads to an authentication bypass. Overall, good post on a two bugs that lead to privilege escalation.

AutoWarp: Critical Cross-Account Vulnerability in Microsoft Azure Automation Service- 798

Yanir Tsarimi - Orca Security     Reference →Posted 4 Years Ago
  • Microsoft Azure Automation allows customers to execute automation code in a managed fashion. You can schedule jobs, provide input and output, and more. Each customer’s automation code runs inside a sandbox, isolated from other customers’ code executing on the same virtual machine.
  • The researcher details their full process for finding the vulnerability. When trying to find a cross-client escape, the first thing to do is get a shell on the machine. Now, you can explore how the system works in full, including open ports, files, logs and many other things.
  • While looking through the logs, an interesting line popped up: http://127.0.0.1:40008. Within the web service (C#, which is easy to decompile), they reverse engineered the service to see what it did. Among the interesting things was a GET request to get tokens to allow for calls to be made in your account. By itself, this is fine.
  • The author noticed that the ports would jump around randomly within about 10 ports. So, they ran a port scan within the service and noticed that ports 4000-4010 were always being used. When making the API call to get the JWT token, you can request it for ANY of the accounts in the virtual machine! By making this call to other ports, you would get credentials for other accounts.
  • When vulnerabilities like this are found, it makes me think that there was no pentest on this. This is such a trivial vulnerability to allow for cross-account credential theft. Overall, good write up besides all of the marketing bots and non-sense.

Escaping Privleged Containers for Fun- 797

Jordy Zomer    Reference →Posted 4 Years Ago
  • Many people run containers for security reasons. Containers have great properties, such as resource isolation. However, sometimes, this isolation is a bad thing, which results in a feature called --privileged to be used. These opens up a whole new attack surface for escaping containers.
  • The author decided to hunt for call_usermodehelper_* family of functions because of CVE-2022-0492 .While grepping through the Linux source code they ran into the function call_usermodehelper (used to run a program/script in user mode) within the core dump functionality.
  • When reading through core, they found out where this was called: " If the first character of this file is a pipe symbol (|), then the remainder of the line is interpreted as the command-line for a user-space program (or script) that is to be executed." If the file within this pattern starts with a pipe (|) then it will run our program outside of the context of the container.
  • An obvious prerequisite of this is that the binary needs to be reachable by the host operating system. The folders within OverlayFS (Docker file system) are mounted and easily reachable. To find the location of the mount, the mount command can be ran from the context of the container to find the FULL file path of the container.
  • How do we trigger this script? Cause a core dump by getting a program to segfault. Writing real bad C is easy enough to do for this to work.
  • To run this exploit now, the following steps are used:
    1. Compile a binary with the code to run.
    2. Find out the path of the file system in the container via the mount command.
    3. Write the FULL path of the exploit file to /proc/sys/kernel/core_pattern.
    4. Cause a core dump with the bad C file.
  • Overall, this write up is real cool! Containers are not magic; they are features of the Linux Operating system being used. By understanding how resources are isolated, we can escape the container in question.

Oh Snap! More Lemmings (Local Privilege Escalation in snap-confine)- 796

Qualys    Reference →Posted 4 Years Ago
  • snap-confine is a SUID-root program installed by default on Ubuntu. This is a package manager, similar to apt, for Linux distributions. While reviewing the source code of the package manager, they were about to quit. However, they found a typo within the main function of the program. When checking for permission checks, they noticed that the real_gid of the user was being compared with the getuid function and vice versa. Because of other checks above, this was not exploitable though.
  • Again, while doing source code review, they noticed a code path where an uninitialized variable could be used. If the XDG_RUNTIME_DIR ENV variable was not set, then the contents of this buffer were passed to a helper program. However, this turned out to be unexploitable since they do not control the value and several ENV variables are cleared as defense in depth.
  • snap-confine dynamically obtains the path to snap-update-ns and snap-discard-ns by reading its own path via /proc/self/exe. If snap-confine can be hardlinked into a directory that we own, then the helper script can be set to something that we control. Since this runs as root, this is quite impactful!
  • The above is impossible to exploit in a default configuration because of the configuration fs.protected_hardlinks being set to 1. If this is set to 0, this is exploitable. After going through several issues with AppArmour profile, they eventually were able to figure out a work around to get an unconfined root shell.
  • When setting up the snap sandbox (mount namespace), it is done by creating a temporary directory at /tmp/snap.$SNAP_NAME/tmp or reuses the directory if it already exists. Once there, it bind mounts it onto /tmp inside the snap mount namespace. To prevent race conditions in this, calls are made with the O_NOFOLLOW and O_DIRECTORY flags.
  • But, they were NOT careful enough. The mount syscall will follow symlinks. To exploit this, it requires a very tight timing though. After the call to open but before the call to change the ownership (fchown), the symlink needs to be created. Then, the mount will follow the link.
  • To relibly win this race condition, the file /tmp/snap.lxd can be monitored with inotify, pinning both processes to a single CPU and lowering snaps scheduling priority. That is quite the setup to relibly win the race! I had never heard of this setup; so, this may be a good trick to use in the future.
  • What does this primitive do? Inside the snap mount namespace, an attacker can bind-mount a world-writable, non-sticky directory onto /tmp, or an attacker can bind-mount any other part of the filesystem onto /tmp. The rest of the article goes over two case studies (Ubuntu Desktop and Ubuntu Server) to get a root shell.
  • The exploitation method was done on two different Ubuntu types: Desktop and Server. The main idea is to trick the directory being used in the request to be owned by the user instead of the program. Then, since we own this directory, an attacker can add their own scripts, which will run as root by the program. This required bypassing the App Armour configurations with complain profiles (instead of stop) and abusing some defaults snap libraries.
  • While going through the attack methods above, they explored MANY different avenues that did not work out. In the process, they found bugs in libmount in the unmounting code. First, if the text  (deleted) is found in the end of a text, the text is simply removed. For instance, an attacker could mount /tmp  (deleted). When we attempt to delete this, it will actually delete /tmp. Neat!
  • The similar unmounting effect can be done in certain situations because of a string truncation issue while verifying the user id. When checking the ownership, the code strncmp(user_id, uidstr, sz) == 0 is used. The sz of the string compare is calculated from the current users ID and NOT the larger between the two. As a result, 1000 and 100 would look the same, when truncated.
  • To wrap this up, they found two more bugs within gblic. The first one is an uninitialized memory read via a strange and unlikely flow within realpath(). The second bug was an off by one buffer overflow/underflow in getcwd() IF the size of the buffer is one and the PATH of the resolving file is larger than PATH_MAX.
  • Overall, I love the in depth nature of the exploitation process. From finding the bug, the methodology behind the exploit, the failures and everything in between. These Qualys reports feel like what Security Research is all about. This is worth spending lots of time on in order to understand fully; many things had to be skipped above so that this resource was not the same length as the article!

Multiple vulnerabilities in Concrete CMS – part2 (PrivEsc/SSRF/etc)- 795

Adrian Tiron - Fortbridge    Reference →Posted 4 Years Ago
  • Concrete is a Content Management platform similar to Wordpress.
  • User groups can have hierarchical structures and inherit permissions from each other. On the main endpoint simply dragging a lower privileged user into the admin group did nothing. However, they found another API that did had the group add but WITHOUT the permission check.
  • The authors found a piece of functionality that allowed for the downloading of a remote file; this is a clear SSRF bug waiting to happen. In order to make the exploitation harder, they decided to block the usage of AWS metadata endpoints and certain file extensions were blocked as well. How do we bypass this?
  • The extension denylist can be bypassed with a PHP trick. Some PHP engines will throw out extra parts of a URL path (/info.php/test.html) but still see the extension as HTML. Using this, a one shot GET exploit or a file disclosure bug is possible still.
  • They REALLY wanted the metadata though. So, they used the classic DNS rebinding technique causing a time of check vs. time of use problem (TOCTOU). Rebinder is a service for easily testing and using DNS rebinding in the wild.
  • The final vulnerability was link poisioning on a password reset link. The host header is commonly used for generating the password reset link when multiple hosts are used. However, this can be manipulated by an attacker. By sending a host header with an attacker controlled host, when a user clicks on the reset link, they will get the reset token.
  • My biggest takeaway from the easiness of the DNS rebinding with other tools! In the future, I may try this attack when SSRF IP denylists are being done. I have also seen hidden APIs not get updated properly with security functions.

Catching bugs in VMware: Carbon Black Cloud Workload Appliance and vRealize Operations Manager- 794

https://swarm.ptsecurity.com/catching-bugs-in-vmware-carbon-black-cloud-workload-appliance-and-vrealize-operations-manager/    Reference →Posted 4 Years Ago
  • Carbon Black Cloud Workload Appliance is the first target and VMware vRealize Operations Manager is the second target.
  • While reviewing the application, they found a service called getServiceToken API, which has 100% access in Spring. This API is internal authentication routes sends back a valid JWT to make further requests. Can we hit it? No, we cannot.
  • Now, there are routing and proxy servers they do a fair amount of route rewritting. The rule had two main points: the route /acs/api/v1/service-token will be redirected to /no_cloud and /acs/ will be forwarded to the backend. When using a denylists, it is important that the frontend and backend servers agree on a route perfectly.
  • From there, they did the best thing ever: they read the documentation. In the documentation, the Envoy points out that normalization of the path is disable by default. This means that URL encoding the path with the denylist will get the request forwarded as normal. Because, later on, the Tomcat server will normalize it themselves. Now, this is super user privileges for everything.
  • Moving to Operations Manager, they found several unauthenticated endpoints. One of the endpoints (/casa/nodes/thumbprints), takes an IP address as a parameter. Since this added a path, we can put a question mark (?) to use our complete path.
  • Using this SSRF, they could call authenticated endpoints with a GET request to steal passwords between nodes and other things. This was awesome since it gave us access to endpoints we normally would not have access to. To make this even better, we can steal this auth token by sending a request to ourselves.
  • Once we have these credentials, it is possible to reset the admin password. Since this is noisy and not fun, they wanted to find something else though. They found a fairly classic directy traversal that could be used to write a JSP-shell into the web directory. Now, we can access this endpoint ourselves to execute arbitrary commands on the device.
  • Overall, some great bugs! In particular, I enjoyed the non-traditional SSRF exploit and the URL encoding for the auth bypass. As we see here, denylists never seem to work

CVE-2022-0492 Affecting Cgroups: Can Containers Escape?- 793

Yuval Avrahami - Palo Alto Networks    Reference →Posted 4 Years Ago
  • Control Groups (cgroups) are a Linux feature that allows for admins to limit and isolate resources for processes. Cgroups are managed via cgroupfs, a management API exposed as a file system; editing this file system will affect the cgroups. There are many different cgroup subsystems, such as the memory group.
  • Each subsystem is mounted at /sys/fs/cgroup/<subsystem>. Within these cgroups, there can be childs as well, such as docker. The vulnerability in this post is within cgroups.
  • One of the features within v1 of the cgroup functionality is release_agent. It allows admins to run a script upon the termination of a process within a c group. This is done by writing to the cgroupfs filesystem at /sys/fs/cgroup/memory/release_agent. This script runs with root permissions with access to all namespaces.
  • CVE-2022-0492 simply does NOT check that the process setting the release_agent file has admin privileges (CAP_SYS_ADMIN). As a result, anybody who can set this file is able to escalate privileges. Can this be used as a container escape?
  • The Linux filesystem sets the owner of the file to be root. As a result, only the root user or users with the CAP_DAC_OVERRIDE capability are allowed to do this. Although root only being able to edit this doesn't seem like a problem, the root user may not have full capabilities. Having a namespace within a different container is a different story though.
  • By default, cgroups in containers are mounted read only. A work around for this is to use the unshare SYSCALL to create a child user and cgroup namespace. However, the release_agent is only in the root cgroup, making this not exploitable in some cases. As a result, only the root container process can set the release agent. Interesting!
  • An additional method is possible with the CAP_SYS_ADMIN permission we can mount to the cgroupfs with no questions asked. With this, it would be possible to set the release_agent file for privilege escalation.
  • SELinux and AppArmour prevent BOTH of theses attack from the gate. This is because these prevent mounting to the cgroupfs from the container, making all of the attacks possible. To see if you are vulnerable, there is a list in the article and a script as well.
  • Overall, a super interesting container escape from a simple bug. The analysis of exploitability was fascinating. Defense-in-depth does work to prevent attacks!

Finding an unseen SQL Injection by bypassing escape functions in mysqljs/mysql- 792

Stypr - Flatt Security    Reference →Posted 4 Years Ago
  • MySQL is the most popular MySQL package in NodeJS. By using this properly, all queries are safe against SQL injection with inputs as strings via prepared statements and escaping. However, what happens when the input for the prepared statement is NOT a string? Madness!
  • An example query is shown below:
    connection.query(
    "SELECT * FROM accounts WHERE username = ? AND password = ?",
     [username, password], func...)
    
    Normally, we would expect a string (like 'admin') as the input for the username and password fields. If the query is setup insecurely, we may be able to put arbitrary objects into these fields. I would call this an unintended use case.
  • If an object is inserted, then weird things to start to happen. In particular, inserting a nested object with a 1 will evaluate to true within MySQL. With the query above, sending object like below will bypass the logic:
    data = {
      username: "admin",
      password: {
        password: 1,
      },
    };
    
  • For demonstrating this technique, the author even has a here. This call passes the opinion to SQLString to do the actual formatting. Within SqlString.js, the function format can be found. The logic of this is as follows:
    1. Iterate through each of the provided values.
    2. Convert each data type into something that can be understood by regex. For objects, this is done by objectToValues.
    3. Take the value and escape all malicious characters using a regex.
    4. Replace the placeholder in the query with the actual value.
  • The function objectToValues works by getting the value of each key in the object then running the escape code on each KEY and VALUE. Once done, it sets the SQL to be `<key>` = <value> in the SQL. The backticks are used for literal SQL statements, such as the username column. Interesting and this is NOT how this should work.
  • As a result, when the object is inserted, we are actually altering the query itself! From the payload that we used above, it turns into the query ...`password = password` = 1. For whatever reason, ...`password = password` = 1 will evaluate to true (tested locally in MySQL repl), allowing any user to authenticate as that user. Wow, what a crazy chain of events that makes this work!
  • To not be vulnerable to this issue, simply validate the data being put into queries; an object should never be treated like a string anyway. Overall, I really enjoyed this post and diving into the root cause of the problem on my own :)

Writing a CD-key generator for the Franklin Bookman Desktop Manager- 791

jsyang    Reference →Posted 4 Years Ago
  • Franklin Bookman devices were early eBook readers. Early on, these used ROM cards then a licensing model with memory cards. Eventually they landed on a connectivity kit with a serial/USB transfer cable, a memory card and a CD-ROM with the Bookman Desktop Manager Software. This talk is about cracking the CD-ROM with this on it.
  • To install the Bookman Desktop Manager (BDM), the user must enter a valid CD key. This key was used to generate a Peripheral Identifier (PID) number that was bound to a consumer around. As a result, a user could buy and download the data from the DRM servers to ensure only a single user could write the content of the eBook to their eBook. This is the process documented in the post.
  • The main goal was to reverse engineer the BDM application for this logic. The BDM program was installing using InstallShield. Using a tool such as unshield, they were able to see the raw application DLLs. Within the DLLs was the file installbm3.dll, which contained the logic for the PID and CD-key logic. By owning this up in Ghidra, there are two valid shared libraries. Luckily for the author, the error messages are quite verbose, making it easy to identify what function performs each action.
  • Since we know that CD-keys should always contain a dash between 4 digits and 4 rear digits, the string error message with this indicates that this is where the CD-key information must be processed at. Now, there is a cryptic looking function with many steps to decode all everything. This is done as following from a C string which has the code:
    1. Apply a function to each character in the string (excluding the dash).
    2. Generate a check digit from the inputted values.
    3. Validate that the check digit matches the input keys check digit from the data in step 1.
    4. Bitwise OR operations on the
  • From reading the source code, it appears that there is a checksum check derived from the actual values. The first 7 characters were the actual value while the final (8th) character was the checksum. In order to defeat the DRM, all we have to do is be able to generate checksums are arbitrary values!
  • While trying to recreate the checksum in JavaScript, they were having some troubles. Then the author noticed something strange: they were using integer overflows as a feature! Since JavaScript did not have the same functionality, this was causing a problem. By adding in this functionality manually into JavaScript via the js-cuint package they were able to replicate the code.
  • Overall, this was a fun post on beating DRM. Even though this was definitely insecure by today's standards, it probably stood up well at the time. Good article!

Analyzing a PJL directory traversal vulnerability – exploiting the Lexmark MC3224i printer (part 2) - 790

Cedric Halbronn    Reference →Posted 4 Years Ago
  • The previous article walks through how they got access to the binaries for reverse engineering. This article goes into the actual reverse engineering, vulnerability discovery and exploitation of a printer.
  • The Printer Job Language (PJL) is used for switching printer information at the job level and sharing information about a job to the host machine. PRET is an open source tool for interacting with PJL but excludes many of the vendor specific options. Since this tends to be an externally facing protocol, attackers love to hit this.
  • While reversing, they wanted to find a list of PJL functions; they found these in the hydra binary. When auditing the different functions (no symbols but lots of useful strings and error messages), they found an undocumented function called LDLWELCOMESCREEN.
  • This command allowed for an arbitrary file to be written with arbitrary content, since it suffers from a directory traversal vulnerability. From an exploitability perspective, they had a few problems though. First, the file is only a tmp file, meaning that it gets deleted after its purpose has been served. Secondly, the file cannot already exist.
  • To get around the first issue, we can write more than 0x400 to the PJL. At 0x400 bytes, the buffer is flushed by writing it to the file. If we keep this stream open after the flush, then the file will not be deleted until after the stream has closed.
  • The second issue is pretty stumping though: how do we overwrite something for code execution if it cannot already exist? While auditing the file system they noticed a set of crash handlers called ABRT. According to the documentation, ABRT can have custom hooks that are executed in a directory when some event occurs. This happens for ALL files in a directory; this is perfect since we can add a file to get executed!
  • To add insult to injury, the post-event handler runs with root permissions. At this point, there is a way to get code execution (via the crash handler) but how do we trigger a crash? Since the device has several really old binaries, they found they could trigger a remote crash in Apache via a bug in awk. However, there are likely many other ways to trigger a crash.
  • For the final payload, they had to use bash commands to disable the firewall, configure SSH to work without authentication and a few other things. After writing the file and triggering the crash, SSH was started, allowing the researchers to authenticate!
  • During Pwn2Own, the exploit failed due to an SSH error they had not seen during testing. As a result, they used a backup script that used netcat to connect instead. Having a backup plan was a wonderful idea to make this work! Overall, amazing research to turn small bugs into game over!